> ## Documentation Index
> Fetch the complete documentation index at: https://docs.conduit.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Server

> Connect Claude Desktop, Claude Code, Cursor, VS Code, Codex, or any Model Context Protocol client to your Conduit workspace.

<Warning>
  Conduit's MCP server is available on the **v3 plan**. Contact [support@conduit.ai](mailto:support@conduit.ai) to enable it for your workspace.
</Warning>

## Overview

The [Model Context Protocol](https://modelcontextprotocol.io) is an open standard that lets AI assistants connect to external systems. Conduit's MCP server exposes your contacts, conversations, tickets, calls, knowledge base, and agents as tools any MCP-compatible client can call.

Once connected, your AI client can:

* Look up contacts, conversations, tickets, calls, reservations, and appointments
* Search the knowledge base and read knowledge nodes
* Send messages on a conversation or ticket, or to a contact on a specific channel
* Create and manage agents, skills, custom code tools, and contact custom attributes
* Manage the Operator's skills (`operatorSettings.skills`), separate from regular agent skills
* List workspaces your token has access to

The server implements the MCP specification revision `2025-06-18` over **streamable HTTP**.

## Endpoint

```text theme={null}
https://api.conduit.ai/v1/mcp
```

Every request includes an `Authorization: Bearer <token>` header. Workspace-scoped tools (most of them) also require a `workspace_id` argument.

## Authentication

Two token types are accepted. Pick the one that matches the client.

<CardGroup cols={2}>
  <Card title="OAuth 2.1" icon="shield-check">
    Interactive clients that want a user-consent flow, for example Claude Desktop, Cursor, VS Code, Claude Code, or Codex. Supports Dynamic Client Registration, so no pre-provisioning is needed.
  </Card>

  <Card title="API token" icon="key">
    Server-to-server, CI, or CLI use. Generate a `capi_...` token under **Workspace menu > API** (click your workspace name in the top-left of the sidebar) and paste it into the client's bearer-token field.
  </Card>
</CardGroup>

### OAuth 2.1

Conduit's MCP server advertises itself as an OAuth 2.1 protected resource per [RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728). When a client first POSTs to the MCP endpoint without a token, the server responds with `401` and a `WWW-Authenticate` header pointing at the resource metadata document. Any spec-compliant client will discover the rest automatically.

| Metadata                      | URL                                                                        |
| ----------------------------- | -------------------------------------------------------------------------- |
| Protected resource metadata   | `https://api.conduit.ai/.well-known/oauth-protected-resource/v1/mcp`       |
| Authorization server          | `https://base.conduit.ai/oauth/mcp`                                        |
| Authorization server metadata | `https://base.conduit.ai/.well-known/oauth-authorization-server/oauth/mcp` |
| Scopes                        | `mcp:read`, `mcp:write`, `offline_access`                                  |

Dynamic Client Registration ([RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591)) is enabled, so clients register themselves on first connect. You sign in with your Conduit account in the browser window the client opens, pick which workspaces to grant access to, and the client caches the resulting access and refresh tokens.

### API tokens

API tokens start with the `capi_` prefix and carry either **read-only** or **read/write** access. Write tools (`send_conversation_message`, `patch_contact`, `create_agent`, etc.) require a read/write token. Rotate or revoke tokens under **Workspace menu > API** at any time.

```bash theme={null}
curl -X POST https://api.conduit.ai/v1/mcp \
  -H "Authorization: Bearer capi_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'
```

## Connect a Client

<Tabs>
  <Tab title="Claude Desktop">
    Add Conduit as a Custom Connector.

    1. Open **Settings > Connectors** in Claude Desktop
    2. Click **Add custom connector**
    3. Name: `Conduit`, URL: `https://api.conduit.ai/v1/mcp`
    4. Click **Connect** and complete the OAuth flow in your browser

    Once connected, the Conduit tools show up under the plug icon in any chat.
  </Tab>

  <Tab title="Claude Code">
    Add the server from the CLI:

    ```bash theme={null}
    claude mcp add --transport http conduit https://api.conduit.ai/v1/mcp
    ```

    The first tool call opens a browser for OAuth. Run `/mcp` in any session to see status, reconnect, or list available tools.

    **Scope.** `claude mcp add` writes to your local config by default. Use `--scope user` to make Conduit available across every project, or `--scope project` to commit a `.mcp.json` your teammates share (each teammate still goes through their own OAuth):

    ```bash theme={null}
    claude mcp add --transport http --scope project conduit https://api.conduit.ai/v1/mcp
    ```

    **API token instead of OAuth.** For headless agents or CI, pass the token as a header:

    ```bash theme={null}
    claude mcp add --transport http conduit https://api.conduit.ai/v1/mcp \
      --header "Authorization: Bearer capi_YOUR_TOKEN"
    ```

    **Pre-approve read-only tools.** Approval prompts on every read get noisy. Allow-list the safe ones in `~/.claude/settings.json` (or `.claude/settings.json` in the project):

    ```json theme={null}
    {
      "permissions": {
        "allow": [
          "mcp__conduit__list_workspaces",
          "mcp__conduit__list_contacts",
          "mcp__conduit__get_contact",
          "mcp__conduit__search_contacts",
          "mcp__conduit__list_conversations",
          "mcp__conduit__list_conversation_messages",
          "mcp__conduit__list_tickets",
          "mcp__conduit__get_ticket",
          "mcp__conduit__list_ticket_messages",
          "mcp__conduit__search_knowledge",
          "mcp__conduit__get_knowledge_node"
        ]
      }
    }
    ```

    Never allow-list write tools (`send_*`, `patch_*`, `create_*`, `update_*`, `delete_*`). Keep approval prompts on for those.
  </Tab>

  <Tab title="Codex">
    Add the server from the CLI:

    ```bash theme={null}
    codex mcp add conduit --url https://api.conduit.ai/v1/mcp
    codex mcp login --scopes mcp:read,mcp:write,offline_access conduit
    ```

    `codex mcp login` opens a browser for OAuth and caches the tokens locally. Restart Codex after adding the server if the tools do not appear in your current session.

    For API-token auth, point Codex at an environment variable that contains your token:

    ```bash theme={null}
    export CONDUIT_API_TOKEN=capi_YOUR_TOKEN
    codex mcp add conduit --url https://api.conduit.ai/v1/mcp --bearer-token-env-var CONDUIT_API_TOKEN
    ```
  </Tab>

  <Tab title="Cursor">
    Edit `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project) and add:

    ```json theme={null}
    {
      "mcpServers": {
        "conduit": {
          "url": "https://api.conduit.ai/v1/mcp"
        }
      }
    }
    ```

    Restart Cursor. The first tool call opens the OAuth flow in a browser window.

    For API-token auth, use the `headers` field instead of going through OAuth:

    ```json theme={null}
    {
      "mcpServers": {
        "conduit": {
          "url": "https://api.conduit.ai/v1/mcp",
          "headers": { "Authorization": "Bearer capi_YOUR_TOKEN" }
        }
      }
    }
    ```
  </Tab>

  <Tab title="VS Code">
    Press `Cmd+Shift+P` (or `Ctrl+Shift+P` on Windows/Linux) and run **MCP: Add server**. Pick **HTTP**, enter `https://api.conduit.ai/v1/mcp`, and name it `conduit`. VS Code writes the entry to `mcp.json`:

    ```json theme={null}
    {
      "servers": {
        "conduit": {
          "type": "http",
          "url": "https://api.conduit.ai/v1/mcp"
        }
      }
    }
    ```

    Sign in through the browser prompt on first use. Invoke tools with `#` in Copilot Chat.
  </Tab>

  <Tab title="Other clients">
    Any client that supports MCP streamable HTTP works. Point it at `https://api.conduit.ai/v1/mcp` and either let it walk the OAuth discovery chain or configure an `Authorization: Bearer capi_...` header.

    For stdio-only clients, use `npx -y mcp-remote https://api.conduit.ai/v1/mcp` as the command.
  </Tab>
</Tabs>

## Production Setup

Four practices that keep MCP usage safe and predictable in real workflows.

### Pin a workspace at the start of each session

Almost every tool requires a `workspace_id`. Open each session by anchoring the model to one workspace:

```text theme={null}
Use list_workspaces and operate on the "acme-hotels" workspace for the rest of this conversation.
```

The model holds onto that ID in context. Subsequent prompts don't need to repeat it. Without this anchor, the model may guess at workspace IDs or call `list_workspaces` repeatedly.

### Keep approvals on for write tools

Read tools are safe to pre-approve in clients that support it. Write tools — anything starting with `send_`, `patch_`, `create_`, `update_`, or `delete_` — should always prompt. Each Conduit tool advertises a `destructiveHint` annotation; well-behaved clients surface it on the approval dialog.

A misfired model decision against an allow-listed `send_conversation_message` ships a real message to a real customer. Don't allow-list it.

### Pass an idempotency key on every send

Every write tool accepts an `idempotency_key` input (or `Idempotency-Key` HTTP header). Pass a stable UUID per logical send. Clients retry on transient failures, and without a key a retry double-sends.

```json theme={null}
{
  "name": "send_conversation_message",
  "arguments": {
    "workspace_id": "wp_...",
    "conversation_id": "cv_...",
    "body": "Hi! Quick update on your booking.",
    "idempotency_key": "9f2c3d1a-..."
  }
}
```

Either tell the model to generate one per send, or set it as a project rule that gets injected into every session.

### Use least-privilege API tokens

For non-interactive use cases (CI, server-to-server, scripts), generate a **read-only** `capi_` token and use it everywhere reads are sufficient. Only generate a `read_write` token for the specific session that needs writes, and rotate it after. Tokens are revoked under **Workspace menu > API** and take effect immediately.

## Example Prompts

Generic starting points that work in any MCP-enabled client. Swap names and IDs for your own.

<AccordionGroup>
  <Accordion title="Triage open tickets">
    ```text theme={null}
    For the acme-hotels workspace, list every open helpdesk ticket touched in the last 24 hours,
    group them by inferred topic, and tell me the three most urgent ones with the customer name
    and a one-line summary.
    ```

    Uses `list_helpdesk_tickets`, `get_helpdesk_ticket`, `list_ticket_messages`. All read-only — no approval prompts if those tools are pre-approved.
  </Accordion>

  <Accordion title="Reproduce a customer report">
    ```text theme={null}
    Search the acme-hotels workspace for any conversation where the contact mentioned
    "double charge" in the last week. Pull the full message thread for the most recent
    one and show me the timestamps.
    ```

    Useful in terminal-based clients (Claude Code, Codex) where you can immediately jump from the conversation into the relevant code path.
  </Accordion>

  <Accordion title="Draft a reply with full context">
    ```text theme={null}
    Pull conversation cv_abc on the acme-hotels workspace. Read the last twenty messages.
    Draft a reply that addresses the refund question, matches the tone of our previous
    responses, and cites our refund policy from the knowledge base. Don't send it — just print it.
    ```

    The "don't send" constraint is the safety belt while iterating. Drop it when you're ready and the model will call `send_conversation_message`, which prompts for approval before anything ships.
  </Accordion>

  <Accordion title="Audit a knowledge base section">
    ```text theme={null}
    Search the knowledge base for any node that mentions our old cancellation policy
    ("48 hours"). For each match, show me the node title, the path, and the sentence
    that contains the phrase.
    ```

    Pair with a follow-up that calls `update_knowledge_node` (write tool, prompts for approval) once you've reviewed the list.
  </Accordion>
</AccordionGroup>

## Rate Limits and Errors

By default, MCP tool calls are limited to **120 requests per minute per workspace** and share the same workspace-level budget as REST API requests. A `429` response includes a `Retry-After` header. Error responses follow the MCP spec: `content[0].text` holds the error message and `isError: true` is set on tool results.

See [Rate Limits](/rate-limits) for details.

| Status | Meaning                                                                                       |
| ------ | --------------------------------------------------------------------------------------------- |
| 401    | Missing, expired, or revoked token                                                            |
| 403    | Token does not have access to the requested workspace, or lacks `read_write` for a write tool |
| 404    | Resource not found in the given workspace                                                     |
| 429    | Rate limit exceeded                                                                           |

## Tool Reference

The tool list is authoritative inside the server itself. A client that has completed `initialize` and `tools/list` will receive every tool, its input schema, and its annotations (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`).

Common tools, grouped by surface:

| Surface               | Examples                                                                                                                                                              |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Workspaces            | `list_workspaces`, `list_workspace_users`, `search_workspace_users`, `list_workspace_senders`, `list_workspace_whatsapp_templates`                                    |
| Contacts              | `list_contacts`, `get_contact`, `search_contacts`, `patch_contact`, `create_contact`, `send_contact_message`                                                          |
| Custom attributes     | `list_custom_attributes`, `get_contact_custom_attributes`, `patch_contact_custom_attributes`                                                                          |
| Conversations         | `list_conversations`, `get_conversation`, `search_conversations`, `list_conversation_messages`, `send_conversation_message`                                           |
| Tickets               | `list_tickets`, `get_ticket`, `search_tickets`, `list_ticket_messages`, `send_ticket_message`                                                                         |
| Calls & appointments  | `list_calls`, `get_call`, `list_appointments`, `get_appointment`                                                                                                      |
| Knowledge             | `search_knowledge`, `search_knowledge_nodes`, `list_knowledge_nodes`, `get_knowledge_node`, `create_knowledge_node`, `update_knowledge_node`, `delete_knowledge_node` |
| Agents & skills       | `list_agents`, `get_agent`, `create_agent`, `patch_agent`, `delete_agent`, `run_agent`, `list_skills`, `create_skill`, `patch_skill`, `delete_skill`                  |
| Operator              | `list_operator_skills`, `create_operator_skill`, `patch_operator_skill`, `delete_operator_skill`                                                                      |
| Custom tools          | `list_custom_tool_runtimes`, `list_custom_tools`, `get_custom_tool`, `create_custom_tool`, `update_custom_tool`, `delete_custom_tool`                                 |
| Per-agent tools       | `list_agent_tools`, `set_agent_tool_access`                                                                                                                           |
| Per-agent connections | `list_agent_connections`                                                                                                                                              |
| Inbox types           | `list_inbox_types`                                                                                                                                                    |
| Workflows             | `list_workflows`, `get_workflow`, `get_workflow_schema`, `create_workflow`, `update_workflow`, `list_workflow_executions`, `list_workflow_execution_events`           |
| Insights              | `get_automation_rate`                                                                                                                                                 |

The `operator_*` tools manage the **Operator's** skills (the knowledge cards the Operator assistant uses), which are separate from the regular agent skills managed by `*_skill`. They read and write `operatorSettings.skills` with the same workspace scoping and `Manage AI Settings` permission as the Operator settings screen in the app, and they are MCP-only (there is no matching REST route). Every `operator_*` tool takes a required `workspace_id`; writes need a read/write token and the `Manage AI Settings` permission.

See the [REST API reference](/api-reference/introduction) for the underlying resource shapes. MCP tools share the same schemas.

To author a custom tool over MCP, call `list_custom_tool_runtimes` first. It returns the entrypoint signature, required return shape, and available dependencies for Python and JavaScript, so the model writes `code` that passes validation on the first try. See the [Custom Tools overview](/api-reference/custom-tools/overview) for the full contract.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Client says Unauthorized after working for a while">
    The OAuth access token expired and the client does not have a refresh token. Disconnect and reconnect the server. If you're using an API token, it may have been rotated or revoked. Check **Workspace menu > API**.
  </Accordion>

  <Accordion title="list_workspaces returns an empty array">
    The token is valid but not scoped to any workspace. For OAuth, remove the Conduit connector in your client and reconnect, making sure to grant at least one workspace during consent. For API tokens, confirm the token is attached to the right workspace.
  </Accordion>

  <Accordion title="Write tool returns 403">
    API tokens default to read-only. Create a new token with read/write access, or use an OAuth client where you consented to the `mcp:write` scope.
  </Accordion>

  <Accordion title="Client cannot discover the OAuth server">
    Some clients do not support Dynamic Client Registration or do not follow the `WWW-Authenticate` resource metadata pointer. In that case, use an API token instead, or point the client directly at the authorization server URLs in the [Authentication](#authentication) section.
  </Accordion>

  <Accordion title="No tools showing up after connecting">
    The connection succeeded but the client hasn't refreshed its tool list. Disconnect and reconnect, or restart the client. In Claude Code, run `/mcp` to force a reconnect.
  </Accordion>
</AccordionGroup>

## Related

* [Model Context Protocol specification](https://modelcontextprotocol.io)
* [REST API reference](/api-reference/introduction)
* [Authorization flow (MCP docs)](https://modelcontextprotocol.io/docs/tutorials/security/authorization)
