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

# Model Context Protocol

> Reach your agents over MCP from Claude Code, Claude Desktop, Cursor, VS Code and any MCP client: the OAuth 2.1 sign-in every edition requires, the client configuration, what the endpoint exposes, and the self-hosted specifics.

The `api` service serves an MCP endpoint at `/mcp/`. It is the xpander API itself, control plane and data plane, exposed over MCP: a connected client lists and runs agents, reads tasks and threads, reaches skills and their operations, custom functions, workspace files, schedules and usage. It is not an agent; each operation is one API call. To talk to Omni, the built-in agent, use its own endpoint (see the note below). Every edition authenticates this endpoint with OAuth 2.1: xpander cloud, Hybrid and Air-Gapped alike. An `x-api-key` header is not accepted here. The server answers `401` to it, as to any request without a bearer token.

<Note>
  Omni, the built-in agent, has its own endpoint: `https://omni.xpander.ai/mcp` on xpander cloud, `/omni-mcp/` on a self-hosted install. On a self-hosted install it answers `404` until the chart sets `global.mcp.publicUrl`. Setup per client is on [Omni in your MCP client](/guides/deploy/omni-mcp). This page is about the agents endpoint.
</Note>

## The endpoint

| Edition | Address |
| - | - |
| xpander cloud | `https://api.xpander.ai/mcp/` |
| Hybrid and Air-Gapped | `https://api.<your domain>/mcp/`, on the install's API host |

The transport is HTTP. Keep the trailing slash.

## How a client signs in

1. The client posts to `/mcp/` without a token. The server answers `401` with `WWW-Authenticate: Bearer resource_metadata=<API host>/.well-known/oauth-protected-resource`.
2. The client reads that metadata and registers itself at `/oauth/register`.
3. It opens `/oauth/authorize` in your browser with a PKCE challenge. You sign in to xpander. A consent page names the client, your organization, your account and the address the code returns to. Click **Approve**.
4. The client exchanges the code at `/oauth/token`.
5. Every call to `/mcp/` from then on carries `Authorization: Bearer <token>`. `initialize` answers with `serverInfo.name` set to `xpander.ai MCP`.

Every call runs as the person who approved and, where systems allow, with that person's permissions. Clients that support remote MCP OAuth discover the whole flow from the address alone. Nothing else goes into the client configuration.

<Frame caption="The consent page a client's sign-in opens: the client's name, the organization, the signed-in account and the address the code returns to. Shown with sample data.">
  <img src="https://mintcdn.com/xpanderai-099931d1/OdLxX9OyFVicAV0l/images/verify/lab-mcp-oauth-consent.png?fit=max&auto=format&n=OdLxX9OyFVicAV0l&q=85&s=8f0605be1759a73b0ea10d311a08f13a" alt="Consent page reading 'docs-lab headless claude wants to connect', with Organization, Signed in as and Returns to rows, and Deny and Approve buttons" width="1440" height="900" data-path="images/verify/lab-mcp-oauth-consent.png" />
</Frame>

Check the challenge yourself:

```bash theme={"dark"}
curl -si -X POST https://api.xpander.ai/mcp/ -H "Content-Type: application/json" -d '{}'
```

The answer is a `401` whose `WWW-Authenticate` header points at the resource metadata. The same call with `Authorization: Bearer <token>` reaches the endpoint.

## Claude Code

```bash theme={"dark"}
claude mcp add --transport http xpander https://api.xpander.ai/mcp/
```

Then run `/mcp` inside Claude Code, pick **xpander** and complete the browser sign-in. On a self-hosted install replace the address with your API host.

A headless run has no browser. Pass a token you already hold, obtained through the flow above, and add the server at user scope:

```bash theme={"dark"}
claude mcp add --transport http xpander https://api.xpander.ai/mcp/ \
  --header "Authorization: Bearer <token>" -s user
claude -p "List my agents and their ids"
```

Claude Code reports the server as **Connected**. A prompt that names one of your agents runs it through `invoke_agent` and returns the agent's answer with the task id.

## Claude Desktop, Cursor and VS Code

No key goes into any of these files. The client opens the sign-in in the browser the first time and keeps the token.

<Tabs>
  <Tab title="Claude Desktop">
    Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) and restart Claude Desktop:

    ```json theme={"dark"}
    {
      "mcpServers": {
        "xpander": {
          "command": "npx",
          "args": ["-y", "mcp-remote@latest", "https://api.xpander.ai/mcp/"]
        }
      }
    }
    ```
  </Tab>

  <Tab title="Cursor">
    `~/.cursor/mcp.json`, or `.cursor/mcp.json` inside a project:

    ```json theme={"dark"}
    {
      "mcpServers": {
        "xpander": { "url": "https://api.xpander.ai/mcp/" }
      }
    }
    ```
  </Tab>

  <Tab title="VS Code">
    `.vscode/mcp.json`:

    ```json theme={"dark"}
    {
      "servers": {
        "xpander": { "type": "http", "url": "https://api.xpander.ai/mcp/" }
      }
    }
    ```
  </Tab>
</Tabs>

## What the endpoint exposes

After `initialize`, `tools/list` returns these operations:

| Group | Operations |
| - | - |
| Agents | `list_agents`, `invoke_agent`, `xpander_discover_agents`, `xpander_get_agent`, `xpander_get_agent_skills`, `xpander_build_agent` |
| Tasks and threads | `create_task`, `get_task`, `get_agent_threads`, `get_thread_messages`, `xpander_schedule_agent_task`, `xpander_list_agent_tasks`, `xpander_get_task`, `xpander_get_task_llm_usage` |
| Agent files | `xpander_list_agent_files`, `xpander_read_agent_file`, `xpander_upload_agent_file`, `xpander_share_agent_file` |
| Workspace | `xpander_workspace_bash`, `xpander_list_workspace_skills`, `xpander_install_workspace_skill` |
| Custom functions | `xpander_list_custom_functions`, `xpander_get_custom_function` |
| Toolkits | `xpander_list_toolkits`, `xpander_get_toolkit_tools`, `xpander_invoke_toolkit_tool` |
| Skills catalog | `xpander_list_connectors`, `xpander_search_connectors`, `xpander_list_connector_operations`, `xpander_search_connector_operations`, `xpander_get_connector_operation_schema`, `xpander_invoke_connector_operation` |

A run started with `invoke_agent` is a task like any other. It appears in the Task Manager and in `GET /v1/tasks/{task_id}`.

## Skills your agents reach over MCP

The other direction, an agent calling an MCP endpoint as a skill, is set up under **Settings > MCP registry** or from an agent's **Add skill** panel. See [Add a skill](/connectors/add-a-skill) and [MCP gateway](/run/integrations/mcp-gateway). There is no per-agent MCP address to configure.

## Self-hosted installs

The endpoint is `https://api.<your domain>/mcp/` on the install's API host. The Omni surface `/omni-mcp/` answers `404` until `global.mcp.publicUrl` is set.

The `/oauth/authorize` step redirects the browser to `${APP_URL}/oauth_login`, read from the `api` service's environment. `APP_URL` must be the UI origin. When it resolves to the API host instead, the browser lands on `{"detail":"Not Found"}` in place of the sign-in page. Set the value in the chart and upgrade the release:

```yaml theme={"dark"}
api:
  env:
    APP_URL: https://<app-host>        # the UI origin; /oauth/authorize sends the browser here
    NEW_APP_URL: https://<app-host>
```

The values file's comment that MCP OAuth is unsupported on Air-Gapped describes this condition. Until the value is set, a person can finish a sign-in by hand: open `https://<app-host>/oauth_login?<the query string the redirect carried>`. The UI serves that route, shows the consent page and returns the code to the client.

## Next steps

<CardGroup cols={3}>
  <Card title="Omni in your MCP client" icon="sparkles" href="/guides/deploy/omni-mcp">
    Ask the built-in agent for anything it can do
  </Card>

  <Card title="MCP gateway" icon="plug" href="/run/integrations/mcp-gateway">
    Both directions on a self-hosted install
  </Card>

  <Card title="REST API" icon="globe" href="/api-reference/rest-api">
    The same agents over HTTP with an API key
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.