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

# Hosted MCP Endpoint

> Stateless JSON-RPC over HTTP that exposes the KaireonAI tool surface to remote agents, tenant-pinned and governed.

`POST /api/v1/mcp` is a hosted [Model Context Protocol](https://modelcontextprotocol.io) endpoint.
It lets a remote agent use the exact same tool surface as the local stdio MCP server
(`npm run mcp`) without running a local process — every call is a single request/response over
HTTP JSON-RPC. There is **no SSE / streaming**; the endpoint implements the streamable-HTTP basics
an agent needs: `initialize`, `ping`, `tools/list`, and `tools/call`.

## POST /api/v1/mcp

Single endpoint, JSON-RPC 2.0. The HTTP method is always `POST`; the JSON-RPC `method` field
selects the operation.

### Authentication

Two things are required:

1. **RBAC** — the caller must resolve to role `editor` or `admin` (otherwise `403`).
2. **Credential** — the request must carry either an `X-API-Key` header **or** be an
   internal-service call (`x-user-id: system`, set by middleware). A pure session cookie is
   **rejected** with `403` — this surface is for agents holding server credentials, because
   nested tool calls run with elevated privileges that a session role must not inherit.

```
X-API-Key: <your-api-key>
X-Tenant-Id: <your-tenant-id>
Content-Type: application/json
```

<Warning>
  **Tenant pinning.** The authenticated tenant is forced into every `tools/call` — any
  client-supplied `tenantId` argument is overwritten before the tool runs. A key scoped to
  tenant A can never reach tenant B's data.
</Warning>

<Note>
  **Governance.** The tool registry is built with `governed = true`. Playbook tools that would
  mutate data instead queue an `AiRecommendation` for admin / four-eyes approval rather than
  writing directly. See [Approvals](./approvals).
</Note>

### Rate limit

60 requests per 60 seconds per caller (fail-closed — a `429` is returned when the limiter cannot
be reached).

### JSON-RPC envelope

Request:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}
```

Successful response:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": { "...": "method-specific" }
}
```

Error response:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": { "code": -32601, "message": "Method not found: foo" }
}
```

### Methods

#### initialize

Returns the server's protocol version and capabilities.

```json theme={null}
// → result
{
  "protocolVersion": "2025-03-26",
  "capabilities": { "tools": { "listChanged": false } },
  "serverInfo": { "name": "kaireonai", "version": "1.0.0" }
}
```

#### ping

Liveness check. Returns an empty object.

```json theme={null}
// → result
{}
```

#### tools/list

Lists every registered tool with its JSON-Schema input.

```json theme={null}
// → result
{
  "tools": [
    {
      "name": "list_offers",
      "description": "List offers for the tenant",
      "inputSchema": { "type": "object", "properties": { "...": {} } }
    }
  ]
}
```

#### tools/call

Invokes a tool by name. `params.name` selects the tool; `params.arguments` carries its inputs.
The authenticated `tenantId` is injected automatically.

```json theme={null}
// params
{
  "name": "list_offers",
  "arguments": { "limit": 10 }
}
```

On success the `result` is the tool's own MCP content payload. A handler that throws returns a
`result` with `isError: true` (not a JSON-RPC error):

```json theme={null}
// → result (handler error)
{
  "content": [{ "type": "text", "text": "{\"error\":\"...\"}" }],
  "isError": true
}
```

`notifications/initialized` is accepted and answered with `202 No Content` (no body).

### Tool surface

The registry reuses the same registration functions as the stdio server, grouped by module:
data, studio, algorithm, operations, AI, and flow tools, plus governed **playbooks**. Call
`tools/list` for the live, tenant-scoped catalog — it always reflects what the calling key can do.

### Error codes

| Code     | Meaning                                                              | HTTP status |
| -------- | -------------------------------------------------------------------- | ----------- |
| `-32700` | Parse error (body was not valid JSON)                                | `400`       |
| `-32600` | Invalid Request (not a valid JSON-RPC 2.0 envelope)                  | `400`       |
| `-32601` | Method not found                                                     | `200`       |
| `-32602` | Invalid params (unknown tool, or arguments failed the tool's schema) | `200`       |

RBAC and credential failures are returned as plain (non-JSON-RPC) `403` responses **before**
JSON-RPC dispatch.

### Example

```bash theme={null}
curl -X POST https://playground.kaireonai.com/api/v1/mcp \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <your-api-key>" \
  -H "X-Tenant-Id: my-tenant" \
  -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }'
```
