# MCP eRegistrations

**AI-powered Service Design for Government Digital Transformation**

MCP servers for the eRegistrations platform — enabling AI assistants like Claude to manage BPA (service design), GDB (database builder), and Keycloak (IAM administration) through natural language.

## What It Does

Design and configure BPA services through conversation:

```
You: Create a "Business License" service
Claude: Created service with registration. Service ID: abc-123

You: Add a reviewer role
Claude: Added "Reviewer" role to the service

You: Set a $50 processing fee
Claude: Created fixed cost of $50 attached to the registration
```

Each step uses the right MCP tool. Full audit trail. Rollback if needed.

## Installation

### Claude Plugin Marketplace (Recommended)

```bash
# First-time install
claude plugins marketplace add unctad-digital-government
claude plugins install bpa-mcp@unctad-digital-government          # BPA service design tools
claude plugins install ds-mcp@unctad-digital-government           # DS admin/ops monitoring (optional)
claude plugins install gdb-mcp@unctad-digital-government          # GDB database tools (optional)
claude plugins install keycloak-mcp@unctad-digital-government     # Keycloak IAM tools (optional)
```

After install, restart Claude Code, then run `/bpa-mcp:install` to register instance profiles (shared across all servers).

For Keycloak, authenticate with admin credentials:
```
/keycloak-mcp:login jamaica
```

```bash
# Update to latest version
claude plugins marketplace update unctad-digital-government
claude plugins uninstall bpa-mcp@unctad-digital-government
claude plugins install bpa-mcp@unctad-digital-government
# If DS installed:
claude plugins uninstall ds-mcp@unctad-digital-government
claude plugins install ds-mcp@unctad-digital-government
# If GDB installed:
claude plugins uninstall gdb-mcp@unctad-digital-government
claude plugins install gdb-mcp@unctad-digital-government
# If Keycloak installed:
claude plugins uninstall keycloak-mcp@unctad-digital-government
claude plugins install keycloak-mcp@unctad-digital-government
```

### Manual (`uvx`)

No install needed — `uvx` runs directly from PyPI:

## Manual Configuration

The MCP server supports two authentication providers:
- **Keycloak** (modern BPA systems) — OIDC with PKCE
- **CAS** (legacy BPA systems) — OAuth2 with Basic Auth

The provider is auto-detected based on which environment variables you set.

### Keycloak Configuration (Modern Systems)

**For Claude Desktop** — add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "BPA-elsalvador-dev": {
      "command": "uvx",
      "args": ["mcp-eregistrations@latest"],
      "env": {
        "BPA_INSTANCE_URL": "https://bpa.dev.els.eregistrations.org",
        "KEYCLOAK_URL": "https://login.dev.els.eregistrations.org",
        "KEYCLOAK_REALM": "SV"
      }
    }
  }
}
```

**For Claude Code** — add to `.mcp.json` in your project:

```json
{
  "mcpServers": {
    "BPA-elsalvador-dev": {
      "command": "uvx",
      "args": ["mcp-eregistrations@latest"],
      "env": {
        "BPA_INSTANCE_URL": "https://bpa.dev.els.eregistrations.org",
        "KEYCLOAK_URL": "https://login.dev.els.eregistrations.org",
        "KEYCLOAK_REALM": "SV"
      }
    }
  }
}
```

**Or via CLI** — install globally with one command:

```bash
claude mcp add --scope user --transport stdio BPA-kenya \
  --env BPA_INSTANCE_URL=https://bpa.test.kenya.eregistrations.org \
  --env KEYCLOAK_URL=https://login.test.kenya.eregistrations.org \
  --env KEYCLOAK_REALM=KE \
  -- uvx mcp-eregistrations@latest
```

### CAS Configuration (Legacy Systems)

For older BPA deployments using CAS (e.g., Cuba test environment):

#### Step 1: Register OAuth Client in CAS

Before configuring the MCP server, you must register an OAuth client in CAS with:

| Setting | Value |
|---------|-------|
| Client ID | Your chosen ID (e.g., `mcp-bpa`) |
| Client Secret | Generated secret |
| Redirect URI | `http://127.0.0.1:8914/callback` |

> **Important:** The redirect URI must be exactly `http://127.0.0.1:8914/callback`. The MCP server uses a fixed port (8914) because CAS requires exact redirect URI matching.

#### Step 2: Configure MCP Server

**For Claude Desktop** — add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "BPA-cuba-test": {
      "command": "uvx",
      "args": ["mcp-eregistrations@latest"],
      "env": {
        "BPA_INSTANCE_URL": "https://bpa.test.cuba.eregistrations.org",
        "CAS_URL": "https://eid.test.cuba.eregistrations.org/cback/v1.0",
        "CAS_CLIENT_ID": "mcp-bpa",
        "CAS_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}
```

**For Claude Code** — add to `~/.claude.json` (global) or `.mcp.json` (project):

```json
{
  "mcpServers": {
    "BPA-cuba-test": {
      "command": "uvx",
      "args": ["mcp-eregistrations@latest"],
      "env": {
        "BPA_INSTANCE_URL": "https://bpa.test.cuba.eregistrations.org",
        "CAS_URL": "https://eid.test.cuba.eregistrations.org/cback/v1.0",
        "CAS_CLIENT_ID": "mcp-bpa",
        "CAS_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}
```

**Or via CLI** — install globally with one command:

```bash
claude mcp add --scope user --transport stdio BPA-cuba-test \
  --env BPA_INSTANCE_URL=https://bpa.test.cuba.eregistrations.org \
  --env CAS_URL=https://eid.test.cuba.eregistrations.org/cback/v1.0 \
  --env CAS_CLIENT_ID=mcp-bpa \
  --env CAS_CLIENT_SECRET=your-client-secret \
  -- uvx mcp-eregistrations@latest
```

> **Note:** CAS requires `CAS_CLIENT_SECRET` (unlike Keycloak which uses PKCE). Get this from your BPA administrator.

> **Troubleshooting:** If you get "command not found: uvx", you installed via curl which puts uvx in `~/.local/bin` (not in GUI app PATH). Fix: either `brew install uv`, or use `"command": "/bin/zsh", "args": ["-c", "$HOME/.local/bin/uvx mcp-eregistrations"]`

On first use, a browser opens for login. Your BPA permissions apply automatically.

> **Tip:** Name each MCP after its instance (e.g., `BPA-elsalvador-dev`, `BPA-cuba-test`) to manage multiple environments, or use the multi-instance feature below to target any profile from a single server.

## Multi-Instance Support

A single MCP server can target multiple BPA instances using named profiles, eliminating the need for a separate server process per country.

### Setup

The `BPA_INSTANCE_URL` env var configures the **default instance**. Additional instances are registered at runtime via `instance_add`:

```
You: Register the Nigeria BPA instance
Claude: [calls instance_add("nigeria", "https://bpa.gateway.nipc.gov.ng", keycloak_url=..., keycloak_realm="NG")]
Done. Profile "nigeria" saved.

You: List all configured instances
Claude: [calls instance_list()]
Active (default): jamaica — https://bpa.jamaica.eregistrations.org
Profiles: nigeria — https://bpa.gateway.nipc.gov.ng
```

### Per-Call Targeting

Every tool accepts an optional `instance` parameter:

```
You: List services in Nigeria
Claude: [calls service_list(instance="nigeria")]

You: Now check the same service in Jamaica
Claude: [calls service_get("abc-123")]   ← uses default (Jamaica)
```

No switching, no restarts. Both instances usable in the same conversation.

### Authentication per Instance

Each instance has its own isolated token:

```
You: Log in to Nigeria
Claude: [calls auth_login(username="admin@nipc.gov.ng", password="...", instance="nigeria")]

You: Check Jamaica connection
Claude: [calls connection_status()]   ← Jamaica default, separate token
```

### Profiles Storage

Profiles are saved to `~/.config/mcp-eregistrations-bpa/profiles.json`. Each profile stores its own token, audit log, and rollback state under a separate data directory.

### Instance Management Tools

| Tool | Description |
|------|-------------|
| `instance_list` | List all configured profiles + active env-var instance |
| `instance_add` | Register a new BPA instance profile |
| `instance_remove` | Remove a profile by name |

## 215 MCP Tools

| Category          | Capabilities                                                    |
| ----------------- | --------------------------------------------------------------- |
| **Services**      | Create, read, update, copy, export, transform to YAML           |
| **Registrations** | Full CRUD with parent service linking                           |
| **Institutions**  | Assign/unassign institutions to registrations                   |
| **Forms**         | Read/write Form.io components with container support            |
| **Roles**         | Create reviewer/approver/processor roles                        |
| **Bots**          | Configure workflow automation                                   |
| **Determinants**  | Text, select, numeric, boolean, date, classification, grid      |
| **Behaviours**    | Component visibility/validation effects with JSONLogic          |
| **Costs**         | Fixed fees and formula-based pricing                            |
| **Documents**     | Link document requirements to registrations                     |
| **Workflows**     | Arazzo-driven intent-based natural language service design      |
| **Debugging**     | Scan, investigate, and fix service configuration issues         |
| **Audit**         | Complete operation history with rollback                        |
| **Analysis**      | Service inspection and dependency mapping                       |
| **Keycloak IAM**  | Realm, user, role, theme, mapper, JWT, and profile management   |

## Natural Language Workflows

Ask Claude to design services using plain English:

| What you say                            | What happens                                         |
| --------------------------------------- | ---------------------------------------------------- |
| "Create a permit service"               | Creates service + registration with proper structure |
| "Add a reviewer role to this service"   | Adds UserRole with 'processing' assignment           |
| "Set a $75 application fee"             | Creates fixed cost attached to registration          |
| "Add document requirement for ID proof" | Links requirement to the registration                |

The workflow system uses [Arazzo](https://spec.openapis.org/arazzo/latest.html) specifications to orchestrate multi-step operations. It extracts your intent, validates inputs, and executes with full audit trail.

### Workflow Tools

| Tool | Purpose |
|------|---------|
| `workflow_list` | List available workflows by category |
| `workflow_search` | Find workflows matching natural language intent |
| `workflow_describe` | Get workflow details, inputs, and steps |
| `workflow_execute` | Run workflow with provided inputs |
| `workflow_start_interactive` | Begin guided step-by-step execution |
| `workflow_status` | Check execution progress |
| `workflow_rollback` | Undo a completed workflow |

## Service Debugger Tools

AI-assisted debugging for BPA service configuration issues. Scan, investigate, and fix problems collaboratively.

### Available Tools

| Tool | Purpose |
|------|---------|
| `debug_scan` | Scan service for configuration issues |
| `debug_investigate` | Analyze root cause of a specific issue |
| `debug_fix` | Execute fix for a single issue |
| `debug_fix_batch` | Fix multiple issues of the same type |
| `debug_group_issues` | Group issues by type, severity, or fix strategy |
| `debug_plan` | Generate phased fix plan with dependencies |
| `debug_verify` | Verify fixes were applied successfully |

### Issue Types Detected

| Type | Severity | Auto-Fixable |
|------|----------|--------------|
| `effects_determinant` | High | Yes |
| `determinant` | High | Yes |
| `translation_moustache` | Medium | Yes |
| `catalog` | Medium | Yes |
| `missing_determinants_in_component_behaviours` | Medium | Yes |
| Component moustache issues | Low | Manual |
| Role/registration issues | Low | Manual |

### Usage Example

```
You: Scan this service for issues

Claude: Found 144 issues across 5 categories:
        - 67 effects referencing deleted determinants (HIGH)
        - 18 orphaned determinants (HIGH)
        - 33 translation issues (MEDIUM)
        [shows summary]

You: Fix all the high severity issues

Claude: I'll fix these in two phases:
        Phase 1: Delete 67 orphaned effects
        Phase 2: Delete 18 orphaned determinants

        Proceed? [waits for approval]

You: Yes, proceed

Claude: Fixed 85 issues. Audit IDs saved for rollback.
        Verification scan shows 0 high-severity issues remaining.
```

## Key Features

**Audit Trail** — Every operation logged (who, what, when). Query history with `audit_list`.

**Rollback** — Undo any write operation. Restore previous state with `rollback`.

**Export** — Get complete service definitions as clean YAML (~25x smaller than raw JSON) for review or version control.

**Copy** — Clone existing services with selective component inclusion.

**Pagination** — All list endpoints support `limit` and `offset` for large datasets. Responses include `total` and `has_more` for navigation.

## Form MCP Tools

BPA uses Form.io for dynamic forms. These tools provide full CRUD operations on form components.

### Available Tools

| Tool | Purpose |
|------|---------|
| `form_get` | Get form structure with simplified component list |
| `form_component_get` | Get full details of a specific component |
| `form_component_add` | Add new component to form |
| `form_component_update` | Update component properties |
| `form_component_remove` | Remove component from form |
| `form_component_move` | Move component to new position/parent |
| `form_update` | Replace entire form schema |

### Form Types

- `applicant` (default) - Main application form
- `guide` - Guidance/help form
- `send_file` - File submission form
- `payment` - Payment form

### Property Availability

Properties vary by tool. Use `form_get` for overview, `form_component_get` for full details:

| Property | `form_get` | `form_component_get` |
|----------|------------|----------------------|
| key | Yes | Yes |
| type | Yes | Yes |
| label | Yes | Yes |
| path | Yes | Yes |
| is_container | Yes | No |
| children_count | For containers | No |
| required | When present | Yes (in validate) |
| validate | No | Yes |
| registrations | No | Yes |
| determinant_ids | No | Yes (in raw) |
| data | No | Yes |
| default_value | No | Yes |
| raw | No | Yes (complete object) |

### Container Types

Form.io uses containers to organize components. Each has different child accessors:

```
Container Type    Children Accessor
--------------    -----------------
tabs              components[] (tab panes)
panel             components[]
columns           columns[].components[] (2-level)
fieldset          components[]
editgrid          components[] (repeatable)
datagrid          components[]
table             rows[][] (HTML table)
well              components[]
container         components[]
```

### Usage Examples

**Get form overview:**
```
form_get(service_id="abc-123", form_type="applicant")
# Returns: component_count, component_keys, simplified components list
```

**Get specific component details:**
```
form_component_get(service_id="abc-123", component_key="firstName")
# Returns: full component with validate, data, determinant_ids, raw object
```

**Add component to form:**
```
form_component_add(
    service_id="abc-123",
    component={"key": "email", "type": "email", "label": "Email Address"},
    parent_key="personalInfo",  # Optional: nest under panel
    position=0                   # Optional: insert at position
)
```

**Update component:**
```
form_component_update(
    service_id="abc-123",
    component_key="firstName",
    updates={"validate": {"required": True}, "label": "First Name *"}
)
```

**Move component:**
```
form_component_move(
    service_id="abc-123",
    component_key="phoneNumber",
    new_parent_key="contactPanel",
    new_position=1
)
```

All write operations include `audit_id` for rollback capability.

## Determinant & Conditional Logic Tools

Create conditional logic that controls form behavior based on user input.

### Determinant Types

| Type | Use Case | Example |
|------|----------|---------|
| `textdeterminant` | Text field conditions | Show panel if country = "USA" |
| `selectdeterminant` | Dropdown selection | Different fees by business type |
| `numericdeterminant` | Numeric comparisons | Require docs if amount > 10000 |
| `booleandeterminant` | Checkbox conditions | Show section if newsletter = true |
| `datedeterminant` | Date comparisons | Validate expiry > today |
| `classificationdeterminant` | Catalog selections | Requirements by industry code |
| `griddeterminant` | Grid/table row conditions | Validate line items |

### Behaviour Effects

Apply determinants to components to control visibility and validation:

```
effect_create(
    service_id="abc-123",
    determinant_id="det-456",
    component_key="additionalDocs",
    effect_type="visibility"  # or "required", "disabled"
)
```

Use `componentbehaviour_list` and `componentbehaviour_get` to inspect existing effects.

## Example Session

```
You: List all services

Claude: Found 12 services. [displays table with IDs, names, status]

You: Analyze the "Business Registration" service

Claude: [shows registrations, roles, determinants, documents, costs]
        Found 3 potential issues: orphaned determinant, missing cost...

You: Create a copy called "Business Registration v2"

Claude: Created service with ID abc-123. Copied 2 registrations,
        4 roles, 8 determinants. Audit ID: xyz-789
```

## Authentication

Login once, then all sessions auto-authenticate silently — no browser popups, no OS keychain prompts.

### First Login

```
You: Log me in to Jamaica
Claude: What are your credentials?
You: admin@jamaica.gov / mypassword
Claude: [calls auth_login(username="admin@jamaica.gov", password="...", instance="jamaica")]
        Authenticated. Credentials saved for future sessions.
```

Credentials are stored locally in `~/.config/mcp-eregistrations-bpa/auth.json` (chmod 600). Shared across all eRegistrations MCP servers (BPA, GDB, DS).

### Subsequent Sessions (Auto-Login)

```
You: List services in Jamaica
Claude: [calls service_list(instance="jamaica")]
        → Silently authenticates from stored credentials. No user interaction.
```

### How It Works

Each MCP server (BPA, GDB, DS, Keycloak) can authenticate independently:

1. **Cached token** — reuse current session
2. **Refresh token** — silently refresh expired session
3. **Stored credentials** — silent password grant (no browser)
4. **Browser login** — OIDC/PKCE if no credentials stored (first time only)
5. **Ask credentials** — prompt the user via Claude

### Auth Providers

| Configuration | Provider |
|---|---|
| `KEYCLOAK_URL` set | Keycloak (modern, OIDC with PKCE) |
| `CAS_URL` set | CAS (legacy, Basic Auth with client secret) |

> **Keycloak requirement:** Password grant requires "Direct Access Grants" enabled on the Keycloak client.

## Configuration

### Common Variables

| Variable           | Description                 | Required |
| ------------------ | --------------------------- | -------- |
| `LOG_LEVEL`        | DEBUG, INFO, WARNING, ERROR | No       |

> **Note:** Instance URLs are configured via profiles (`instance_add` tool or `instances.yaml`), not environment variables.

### Keycloak Variables

| Variable           | Description                 | Required |
| ------------------ | --------------------------- | -------- |
| `KEYCLOAK_URL`     | Keycloak server URL         | Yes      |
| `KEYCLOAK_REALM`   | Keycloak realm name         | Yes      |

### CAS Variables

| Variable            | Description                          | Required | Default |
| ------------------- | ------------------------------------ | -------- | ------- |
| `CAS_URL`           | CAS OAuth2 server URL                | Yes      | —       |
| `CAS_CLIENT_ID`     | OAuth2 client ID                     | Yes      | —       |
| `CAS_CLIENT_SECRET` | OAuth2 client secret                 | Yes      | —       |
| `CAS_CALLBACK_PORT` | Local callback port for redirect URI | No       | 8914    |

> **Note:** The callback port must match the redirect URI registered in CAS. Default is 8914 (`http://127.0.0.1:8914/callback`).

> **Note:** The PARTC URL for fetching user roles is automatically derived from `CAS_URL` by replacing `/cback/` with `/partc/`.

Logs: `~/.config/mcp-eregistrations-bpa/instances/{instance-slug}/server.log`

### Multi-Instance Profiles

Named profiles are stored at `~/.config/mcp-eregistrations-bpa/profiles.json`. Each profile is a JSON object with the same fields as the env vars above:

```json
{
  "profiles": {
    "nigeria": {
      "bpa_instance_url": "https://bpa.gateway.nipc.gov.ng",
      "keycloak_url": "https://login.nipc.gov.ng",
      "keycloak_realm": "NG"
    },
    "cuba": {
      "bpa_instance_url": "https://bpa.test.cuba.eregistrations.org",
      "cas_url": "https://eid.test.cuba.eregistrations.org/cback/v1.0",
      "cas_client_id": "mcp-client",
      "cas_client_secret": "..."
    }
  }
}
```

Profiles are managed via `instance_add` / `instance_remove` tools, or by editing the file directly. Each profile gets its own isolated data directory, token store, audit log, and rollback state.

## Development

```bash
# Clone and install
git clone https://github.com/UNCTAD-eRegistrations/MCP_eRegistrations.git
cd MCP_eRegistrations
uv sync

# Run tests (1200+ tests)
uv run pytest

# Lint and format
uv run ruff check . && uv run ruff format .

# Type checking
uv run mypy src/
```

### Packages

| Package | Entry Point | Description |
|---------|-------------|-------------|
| `mcp_eregistrations_bpa` | `mcp-eregistrations-bpa` | BPA service design tools (164 tools) |
| `mcp_eregistrations_ds` | `mcp-eregistrations-ds` | DS admin/ops monitoring tools (33 tools) |
| `mcp_eregistrations_gdb` | `mcp-eregistrations-gdb` | GDB database builder tools |
| `mcp_eregistrations_keycloak` | `mcp-eregistrations-keycloak` | Keycloak Admin API tools (51 tools) |
| `mcp_eregistrations_common` | — | Shared config, auth, instance management |

### Keycloak MCP Development

The Keycloak package provides 51 tools for managing Keycloak realms, users, roles, themes, protocol mappers, and JWT tokens across all eRegistrations instances.

**Plugin commands:**

| Command | Description |
|---------|-------------|
| `/keycloak-mcp:install` | Verify the server is loaded and ready |
| `/keycloak-mcp:login <instance>` | Authenticate with admin credentials |
| `/keycloak-mcp:status [instance]` | Check connection status |
| `/keycloak-mcp:doctor` | Diagnose and fix common issues |

**Running locally:**

```bash
# Run the Keycloak MCP server
uv run mcp-eregistrations-keycloak

# Run Keycloak tests only
uv run pytest tests/test_keycloak/ -v
```

**Architecture:**
- `keycloak_client/` — Async httpx client with dual-URL support (`/admin` for admin API, public base for OIDC endpoints), exponential backoff, token refresh mutex, and large response truncation
- `tools/` — 51 tools across 10 modules: realms, users, user_profile, roles, themes, mappers, jwt_tools, export, diagnostics, system
- `audit/` — SQLite audit logger with rollback state tracking (all 21 write tools are audited)
- `rollback/` — Keycloak-specific rollback endpoints for realm/user/role/theme/profile/mapper operations
- `tools/validation.py` — Input validation (realm, UUID, role names) + field allowlists for update operations

**Auth requirements:** The authenticated user needs Keycloak `realm-management` roles (`manage-users`, `manage-realm`, `view-realm`). The default client ID is `admin-cli` (Keycloak's built-in admin client). Both password and client_credentials grants are supported.

### DS MCP

The DS (Display System) package provides 33 read-only tools for monitoring live application data — files in progress, payments, workflow states, documents, messages, users, and financial reports.

**Install via marketplace:**

```bash
claude plugins install ds-mcp@unctad-digital-government
```

**Or run directly with uvx (Claude Desktop / Claude Code config):**

```json
"DS-jamaica": {
  "command": "uvx",
  "args": ["--from", "mcp-eregistrations@latest", "mcp-eregistrations-ds"]
}
```

**Requirements:**
- Admin user required (`is_staff` or `is_superuser` in the DS Django backend)
- Compatible with v2.x Keycloak instances only — not supported on v1.x or CAS deployments
- Auth is shared with BPA via OS keyring: log in once via BPA (`auth_login`), DS auto-authenticates

**Tools by domain (33 total):**

| Domain | Tools |
|--------|-------|
| System / Auth | `ds_health`, `ds_auth_login`, `ds_instance_add`, `ds_instance_list` |
| Services | `service_list`, `service_get`, `service_roles` |
| Files | `file_list`, `file_get`, `file_data_get`, `file_kyc_status`, `file_payment_status` |
| Processes | `process_list`, `process_get`, `process_history`, `process_task_variables` |
| Documents | `document_list`, `file_document_list`, `certificate_list`, `certificate_get` |
| Messages | `message_list_admin`, `message_get`, `alert_list_admin`, `alert_get` |
| Users | `user_search`, `business_entity_list` |
| Payments | `payment_transaction_list`, `payment_provider_list`, `file_payment_status` |
| Finance | `financial_report_data`, `financial_report_export` |
| Instances | `ds_instance_add`, `ds_instance_list` |

**Key tool — `ds_url_parse`:** Paste any DS browser URL and get extracted IDs (file ID, process ID, service ID) along with suggested investigation steps. Use this as a starting point for any monitoring task.

**Running locally:**

```bash
# Run the DS MCP server
uv run mcp-eregistrations-ds

# Run DS tests only
uv run pytest tests/test_ds/ -v
```

## Complete Tool Reference

### Authentication & Instance Management (5 tools)

| Tool | Description |
|------|-------------|
| `auth_login` | Authenticate with BPA (browser, password grant, or keyring). Accepts `instance=` to target a specific profile. |
| `connection_status` | Check current authentication state. Accepts `instance=` to check a specific profile. |
| `instance_list` | List all configured BPA instance profiles and the active env-var instance |
| `instance_add` | Register a new BPA instance profile (saved to profiles.json) |
| `instance_remove` | Remove a BPA instance profile by name |

> **Multi-instance:** Every tool accepts `instance="profile_name"` to target a named profile instead of the default `BPA_INSTANCE_URL`. See the [Multi-Instance Support](#multi-instance-support) section above.

### Services (6 tools)

| Tool | Description |
|------|-------------|
| `service_list` | List all services with pagination |
| `service_get` | Get service details by ID |
| `service_create` | Create new service |
| `service_update` | Update service properties |
| `service_publish` | Publish service for frontend |
| `service_activate` | Activate/deactivate service |

### Registrations (6 tools)

| Tool | Description |
|------|-------------|
| `registration_list` | List registrations with service filter |
| `registration_get` | Get registration details |
| `registration_create` | Create registration in service |
| `registration_delete` | Delete registration |
| `registration_activate` | Activate/deactivate registration |
| `serviceregistration_link` | Link registration to service |

### Institutions (7 tools)

| Tool | Description |
|------|-------------|
| `registrationinstitution_list` | List institution assignments |
| `registrationinstitution_get` | Get assignment details |
| `registrationinstitution_create` | Assign institution to registration |
| `registrationinstitution_delete` | Remove institution assignment |
| `registrationinstitution_list_by_institution` | List registrations by institution |
| `institution_discover` | Discover institution IDs |
| `institution_create` | Create institution in Keycloak |

### Fields (2 tools)

| Tool | Description |
|------|-------------|
| `field_list` | List fields for a service |
| `field_get` | Get field details |

### Forms (7 tools)

| Tool | Description |
|------|-------------|
| `form_get` | Get form structure |
| `form_component_get` | Get component details |
| `form_component_add` | Add component to form |
| `form_component_update` | Update component properties |
| `form_component_remove` | Remove component |
| `form_component_move` | Move component |
| `form_update` | Replace entire form schema |

### Determinants (12 tools)

| Tool | Description |
|------|-------------|
| `determinant_list` | List determinants for service |
| `determinant_get` | Get determinant details |
| `determinant_search` | Search determinants by criteria |
| `determinant_delete` | Delete determinant |
| `textdeterminant_create` | Create text comparison |
| `textdeterminant_update` | Update text determinant |
| `selectdeterminant_create` | Create dropdown selection |
| `numericdeterminant_create` | Create numeric comparison |
| `booleandeterminant_create` | Create checkbox condition |
| `datedeterminant_create` | Create date comparison |
| `classificationdeterminant_create` | Create catalog selection |
| `griddeterminant_create` | Create grid row condition |

### Behaviours (5 tools)

| Tool | Description |
|------|-------------|
| `componentbehaviour_list` | List behaviours for service |
| `componentbehaviour_get` | Get behaviour by ID |
| `componentbehaviour_get_by_component` | Get behaviour for component |
| `effect_create` | Create visibility/validation effect |
| `effect_delete` | Delete behaviour/effect |

### Actions (2 tools)

| Tool | Description |
|------|-------------|
| `componentaction_get` | Get component actions by ID |
| `componentaction_get_by_component` | Get actions for component |

### Bots (5 tools)

| Tool | Description |
|------|-------------|
| `bot_list` | List bots for service |
| `bot_get` | Get bot details |
| `bot_create` | Create workflow bot |
| `bot_update` | Update bot properties |
| `bot_delete` | Delete bot |

### Classifications (5 tools)

| Tool | Description |
|------|-------------|
| `classification_list` | List catalog classifications |
| `classification_get` | Get classification with entries |
| `classification_create` | Create classification catalog |
| `classification_update` | Update classification |
| `classification_export_csv` | Export as CSV |

### Notifications (2 tools)

| Tool | Description |
|------|-------------|
| `notification_list` | List service notifications |
| `notification_create` | Create notification trigger |

### Messages (5 tools)

| Tool | Description |
|------|-------------|
| `message_list` | List global message templates |
| `message_get` | Get message details |
| `message_create` | Create message template |
| `message_update` | Update message |
| `message_delete` | Delete message |

### Roles (8 tools)

| Tool | Description |
|------|-------------|
| `role_list` | List roles for service |
| `role_get` | Get role with statuses |
| `role_create` | Create UserRole or BotRole |
| `role_update` | Update role properties |
| `role_delete` | Delete role |
| `roleinstitution_create` | Assign institution to role |
| `roleregistration_create` | Assign registration to role |

### Role Status (4 tools)

| Tool | Description |
|------|-------------|
| `rolestatus_get` | Get status transition details |
| `rolestatus_create` | Create workflow transition |
| `rolestatus_update` | Update status |
| `rolestatus_delete` | Delete status |

### Role Units (4 tools)

| Tool | Description |
|------|-------------|
| `roleunit_list` | List units for role |
| `roleunit_get` | Get unit assignment |
| `roleunit_create` | Assign unit to role |
| `roleunit_delete` | Remove unit assignment |

### Documents (5 tools)

| Tool | Description |
|------|-------------|
| `requirement_list` | List global requirements |
| `documentrequirement_list` | List requirements for registration |
| `documentrequirement_create` | Link requirement to registration |
| `documentrequirement_update` | Update requirement |
| `documentrequirement_delete` | Remove requirement |

### Costs (4 tools)

| Tool | Description |
|------|-------------|
| `cost_create_fixed` | Create fixed fee |
| `cost_create_formula` | Create formula-based cost |
| `cost_update` | Update cost |
| `cost_delete` | Delete cost |

### Export (3 tools)

| Tool | Description |
|------|-------------|
| `service_export_raw` | Export service as JSON |
| `service_to_yaml` | Transform to AI-optimized YAML |
| `service_copy` | Clone service with new name |

### Analysis (1 tool)

| Tool | Description |
|------|-------------|
| `analyze_service` | AI-optimized service analysis |

### Audit (2 tools)

| Tool | Description |
|------|-------------|
| `audit_list` | List audit log entries |
| `audit_get` | Get audit entry details |

### Rollback (3 tools)

| Tool | Description |
|------|-------------|
| `rollback` | Undo write operation |
| `rollback_history` | Get object state history |
| `rollback_cleanup` | Clean old rollback states |

### Workflows (13 tools)

| Tool | Description |
|------|-------------|
| `workflow_list` | List available workflows |
| `workflow_describe` | Get workflow details |
| `workflow_search` | Search by intent |
| `workflow_execute` | Run workflow |
| `workflow_status` | Check execution status |
| `workflow_cancel` | Cancel running workflow |
| `workflow_retry` | Retry failed workflow |
| `workflow_rollback` | Undo completed workflow |
| `workflow_chain` | Execute workflow sequence |
| `workflow_start_interactive` | Begin guided mode |
| `workflow_continue` | Continue interactive session |
| `workflow_confirm` | Confirm and execute |
| `workflow_validate` | Validate workflow definitions |

### Debugging (7 tools)

| Tool | Description |
|------|-------------|
| `debug_scan` | Scan for configuration issues |
| `debug_investigate` | Analyze issue root cause |
| `debug_fix` | Fix single issue |
| `debug_fix_batch` | Fix multiple issues |
| `debug_group_issues` | Group issues by criteria |
| `debug_plan` | Generate fix plan |
| `debug_verify` | Verify fixes applied |

### Keycloak — Realms (5 tools)

| Tool | Description |
|------|-------------|
| `kc_list_realms` | List all accessible realms |
| `kc_get_realm` | Get realm configuration |
| `kc_create_realm` | Create new realm (audited) |
| `kc_update_realm` | Update realm settings with field allowlist (audited + rollback) |
| `kc_delete_realm` | Delete realm with safety guard (audited + rollback) |

### Keycloak — Users (7 tools)

| Tool | Description |
|------|-------------|
| `kc_list_users` | List users with search and pagination |
| `kc_get_user` | Get user details |
| `kc_get_user_sessions` | Get active sessions for a user |
| `kc_create_user` | Create user (audited, PII-safe logging) |
| `kc_update_user` | Update user with field allowlist (audited + rollback) |
| `kc_delete_user` | Delete user (audited + rollback) |
| `kc_reset_user_password` | Reset password (audited, password never logged) |

### Keycloak — User Profile (5 tools)

| Tool | Description |
|------|-------------|
| `kc_get_user_profile_config` | Get user profile configuration |
| `kc_update_user_profile_config` | Replace full profile config (audited + rollback) |
| `kc_add_user_attribute` | Add attribute to profile (audited + rollback) |
| `kc_update_user_attribute` | Update attribute definition (audited + rollback) |
| `kc_remove_user_attribute` | Remove attribute (audited + rollback) |

### Keycloak — Roles (15 tools)

| Tool | Description |
|------|-------------|
| `kc_list_realm_roles` | List realm roles with search |
| `kc_get_realm_role` | Get role details |
| `kc_list_role_users` | List users assigned to a role |
| `kc_list_client_roles` | List roles for a client |
| `kc_create_realm_role` | Create role with managed-by tag (audited) |
| `kc_update_realm_role` | Update role with field allowlist (audited + rollback) |
| `kc_delete_realm_role` | Delete role with MCP-managed check (audited + rollback) |
| `kc_get_composite_roles` | Get child roles of a composite |
| `kc_add_composite_roles` | Add children to composite (audited) |
| `kc_remove_composite_roles` | Remove children from composite (audited) |
| `kc_get_user_role_mappings` | Get all role mappings for a user |
| `kc_get_effective_realm_roles` | Get effective (direct + inherited) roles |
| `kc_get_available_realm_roles` | Get roles available to assign |
| `kc_assign_realm_roles` | Assign roles to user (audited) |
| `kc_remove_user_realm_roles` | Remove roles from user (audited) |

### Keycloak — Themes (3 tools)

| Tool | Description |
|------|-------------|
| `kc_list_themes` | List available themes from server info |
| `kc_get_realm_theme` | Get current theme assignments for a realm |
| `kc_set_realm_theme` | Set login/account/admin/email themes (audited + rollback) |

### Keycloak — Protocol Mappers (3 tools)

| Tool | Description |
|------|-------------|
| `kc_list_client_mappers` | List protocol mappers for a client |
| `kc_add_client_mapper` | Add protocol mapper (audited) |
| `kc_delete_client_mapper` | Delete protocol mapper (audited + rollback) |

### Keycloak — JWT (4 tools)

| Tool | Description |
|------|-------------|
| `kc_get_token_info` | Get current session token metadata (claims only, no raw token) |
| `kc_decode_token` | Decode JWT without verification |
| `kc_validate_token` | Validate JWT signature against JWKS |
| `kc_introspect_token` | Introspect token via RFC 7662 |

### Keycloak — Export & Diagnostics (4 tools)

| Tool | Description |
|------|-------------|
| `kc_export_realm_yaml` | Export realm config + roles as YAML |
| `kc_compare_realms` | Cross-instance role diff |
| `kc_debug_scan_realm` | Health check (empty composites, missing descriptions, themes) |
| `kc_connection_status` | Verify connectivity, version, realm count |

### Keycloak — System (5 tools)

| Tool | Description |
|------|-------------|
| `kc_auth_login` | Authenticate (password or client_credentials grant) |
| `kc_audit_log` | List audit log entries |
| `kc_rollback` | Execute rollback by audit ID |
| `kc_rollback_list` | List available rollback points |
| `kc_rollback_cleanup` | Delete old rollback states |

## Arazzo Workflow Reference (96 workflows)

### Service Creation

| Workflow | Description |
|----------|-------------|
| `createMinimalService` | Create service with registration |
| `createCompleteService` | Full service with roles and costs |
| `createQuickService` | Minimal service setup |

### Service Publishing

| Workflow | Description |
|----------|-------------|
| `fullPublish` | Complete publish workflow |
| `publishServiceChanges` | Publish pending changes |
| `activateService` | Activate service |
| `deactivateService` | Deactivate service |

### Roles & Workflow

| Workflow | Description |
|----------|-------------|
| `addRole` | Add role to service |
| `updateRole` | Update role properties |
| `configureStandardWorkflow` | Setup standard approval flow |
| `createCustomStatus` | Create workflow status |
| `updateCustomStatus` | Update status |
| `deleteRoleStatus` | Remove status |
| `createUserDefinedStatusWithMessage` | Status with notification |
| `updateUserDefinedStatusMessage` | Update status message |
| `getRoleFull` | Get complete role details |
| `getRoleStatus` | Get status details |
| `getRoleBots` | Get role bots |
| `getRoleUnits` | Get role units |
| `getRoleInstitutions` | Get role institutions |
| `getRoleHistory` | Get role version history |
| `listRolesWithDetails` | List all roles with details |
| `addUnitToRole` | Assign unit to role |
| `assignRoleInstitution` | Assign institution |
| `assignRegistrationToRole` | Assign single registration |
| `assignRegistrationsToRole` | Assign multiple registrations |
| `revertRoleVersion` | Rollback role version |

### Forms

| Workflow | Description |
|----------|-------------|
| `getApplicantForm` | Get applicant form |
| `getGuideForm` | Get guide form |
| `getDocumentForm` | Get document form |
| `updateApplicantForm` | Update applicant form |
| `updateGuideForm` | Update guide form |
| `toggleApplicantForm` | Enable/disable form |
| `deleteComponent` | Remove form component |
| `getField` | Get field details |
| `listFields` | List all fields |
| `getComponentActions` | Get component actions |
| `getComponentValidation` | Get validation rules |
| `getComponentFormula` | Get calculation formula |
| `updateComponentActions` | Update actions |
| `updateComponentValidation` | Update validation |
| `updateComponentFormula` | Update formula |
| `getFormHistory` | Get form version history |
| `revertFormVersion` | Rollback form version |
| `linkFieldToDeterminant` | Link field to condition |

### Determinants

| Workflow | Description |
|----------|-------------|
| `addTextDeterminant` | Create text condition |
| `addSelectDeterminant` | Create dropdown condition |
| `addRadioDeterminant` | Create radio condition |
| `addNumericDeterminant` | Create numeric condition |
| `addClassificationDeterminant` | Create catalog condition |
| `addGridDeterminant` | Create grid row condition |
| `updateTextDeterminant` | Update text determinant |

### Classifications

| Workflow | Description |
|----------|-------------|
| `listClassifications` | List all classifications |
| `searchClassifications` | Search classifications |
| `getClassificationType` | Get classification type |
| `createClassificationType` | Create classification type |
| `updateClassificationType` | Update type |
| `deleteClassificationType` | Delete type |
| `createClassificationGroup` | Create group |
| `deleteClassificationGroup` | Delete group |
| `listClassificationGroups` | List groups |
| `addClassificationField` | Add field to classification |
| `addClassificationFields` | Add multiple fields |
| `updateClassificationField` | Update field |
| `deleteClassificationField` | Delete field |
| `listClassificationFields` | List fields |
| `generateClassificationKeys` | Generate unique keys |
| `addSubcatalogs` | Add subcatalogs |
| `copyClassification` | Copy classification |
| `getServiceClassifications` | Get service classifications |

### Institutions

| Workflow | Description |
|----------|-------------|
| `completeInstitutionSetup` | Full institution setup |
| `assignRegistrationInstitution` | Assign to registration |
| `getRegistrationInstitution` | Get assignment |
| `removeRegistrationInstitution` | Remove assignment |
| `listRegistrationsByInstitution` | List by institution |

### Payments & Costs

| Workflow | Description |
|----------|-------------|
| `addFixedCost` | Add fixed fee |
| `addFormulaCost` | Add formula cost |
| `configureCompletePayments` | Full payment setup |
| `configureTieredPricing` | Tiered pricing rules |

### Documents

| Workflow | Description |
|----------|-------------|
| `addDocumentRequirement` | Add required document |

### Bots

| Workflow | Description |
|----------|-------------|
| `addBot` | Add automation bot |
| `updateBot` | Update bot |

### Notifications & Messages

| Workflow | Description |
|----------|-------------|
| `createServiceNotification` | Create notification |
| `updateNotification` | Update notification |
| `getNotification` | Get notification details |
| `listServiceNotifications` | List notifications |
| `sortServiceNotifications` | Reorder notifications |
| `createMessage` | Create message template |
| `getMessage` | Get message |
| `updateMessage` | Update message |
| `deleteMessage` | Delete message |
| `listMessages` | List messages |
| `updateFileStatus` | Update file status message |
| `updateFileValidatedStatusMessage` | Update validated message |
| `updateFileDeclineStatusMessage` | Update decline message |
| `updateFilePendingStatusMessage` | Update pending message |
| `updateFileRejectStatusMessage` | Update reject message |

### Debugging

| Workflow | Description |
|----------|-------------|
| `scanService` | Scan for issues |
| `planFixes` | Generate fix plan |
| `verifyFixes` | Verify fixes applied |

## License

Copyright (c) 2025-2026
UN for Trade & Development (UNCTAD)
Division on Investment and Enterprise (DIAE)
Business Facilitation Section

All rights reserved. See [LICENSE](LICENSE).

---

Part of [eRegistrations](https://businessfacilitation.org)
