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

# Orbit-as-MCP: hosted server handshake and scoped tool catalog

> Exposes Orbit itself as a hosted MCP server over JSON-RPC — understand the initialize handshake, the scope-gated tools/list catalog, and the dashboard test surface.

# Orbit-as-MCP: hosted server handshake

Devotel Orbit can be exposed **as an MCP server** at `POST/GET /api/v1/mcp`, so an
external MCP client — Claude, ChatGPT, or an IDE agent — operates *your* tenant
through a curated tool catalog. This page documents that inbound surface: the
JSON-RPC handshake, the scoped catalog, and the dashboard page that exercises it
without any client setup.

## Inbound vs outbound MCP

MCP comes up in two directions on the platform, and they are separate features:

* **Inbound (this page):** Orbit acts as the *server*. An external MCP client
  calls the hosted endpoint and drives your tenant through tool methods such as
  `list_campaigns`, `send_sms`, or `list_numbers`.

* **Outbound:** your Orbit *agents* register third-party MCP servers and call
  their tools. Those registrations are managed under the Agents section; the
  [Probe MCP Server](/api-reference/agents) endpoint dry-runs a registration
  before it is saved.

Nothing here depends on a local `npx` process — the inbound server is hosted
behind the API gateway. The [Claude / Cursor client setup guide](/guides/mcp-claude-cursor)
covers connecting specific clients; this page is the protocol reference for the
surface they (and the dashboard) talk to.

## The JSON-RPC handshake

The endpoint is a single JSON-RPC 2.0 service (`POST /api/v1/mcp`) that always
replies with a plain JSON body — it never upgrades to an SSE stream. A
`GET /api/v1/mcp` probe returns the same capability descriptor without a body
of methods.

The first call is `initialize`:

```bash Request theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/mcp \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize"
  }'
```

```json Response theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": { "tools": {} },
    "serverInfo": { "name": "orbit", "version": "1.0.0" }
  }
}
```

Authentication is the platform's normal API-key bearer — the same
`X-API-Key` or `Authorization: Bearer` header every other route accepts.
There is no OAuth handshake or MCP-specific credential.

## Fetching the scoped tool catalog

Call `tools/list` to read the catalog your API key is scoped for:

```bash Request theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/mcp \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/list"
  }'
```

```json Response theme={null}
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "send_sms",
        "description": "Send an SMS on any registered number",
        "inputSchema": {
          "type": "object",
          "properties": {
            "to": { "type": "string" },
            "body": { "type": "string" }
          },
          "required": ["to", "body"]
        }
      }
    ]
  }
}
```

Each `tools[]` row carries `name`, an optional `description`, and an optional
`inputSchema`. The full catalog is listed under **Available tools** in the
[client setup guide](/guides/mcp-claude-cursor).

## How the dashboard page uses it

Open **Dashboard → Developer → MCP Server**. The page is the no-client path for
validating all of this from the browser:

1. **Test connection** fires the `initialize` request above and, on success,
   marks the session connected (it renders the server name, protocol version,
   transport, and server version as badges).
2. Only once connected does the page issue `tools/list` — the catalog fetch is
   gated on the connected flag, so a failed probe never renders stale rows.
3. The two raw request bodies the client island sends are exactly the
   `curl` payloads shown in the previous two sections — run them in a terminal
   to debug outside the page.

If `tools/list` returns an empty `tools` array, the page says so explicitly and
points you at the scopes fix (below) rather than hanging on an empty list.

## Scoping the catalog

The catalog is **scoped per API key**: each tool is gated by a matching
OAuth-style scope on the key (for example `messages:read`, `campaigns:read`,
`voice:write`). A key with narrower scopes sees fewer tools, and a tool your key
lacks scope for is indistinguishable from a tool that doesn't exist — the
response gives no hint either way.

Grant or revoke scopes under **Dashboard → Settings → API Keys**, then re-run
Test connection to refresh the catalog.

## Security notes

Because the inbound surface reuses the platform's API-key bearer auth:

* Revoking or rotating the key in **Settings → API Keys** governs access — an
  MCP client goes dark the same moment a REST integration would.
* Every `tools/call` is audit-logged and rate-limited per tenant, on top of the
  underlying route's own checks.

## See also

* [Connect Orbit to your AI coding assistant via MCP](/guides/mcp-claude-cursor) — per-client setup walkthroughs (Claude Desktop, Cursor, Claude Code, VS Code, Windsurf, Cline, Zed, Continue).
* [Probe MCP Server](/api-reference/agents) — the outbound side: dry-run a third-party registration your Orbit agent will consume.
* [Developer Portal](/guides/developer-portal) — the dashboard pillar that hosts Developer → MCP Server.
