Connect over MCP
Get an agent’s MCP client talking to a Kairos deployment: one streamable-HTTP session
against /mcp, authenticated, resolved to the right tenant, with the eighty-four
tools available.
Before you start: you need a bearer token for a principal that is a member of the tenant. For an unattended client that means an API key — see Give an agent machine access. A human’s OIDC access token works identically for interactive use.
If your client speaks MCP streamable HTTP already, point it at
https://<host>/mcp with that bearer and skip to
Tenant resolution. The rest of this page is for wiring a
client by hand.
The handshake
Section titled “The handshake”Three requests. All are POST /mcp; the transport is JSON-RPC over HTTP with
SSE-framed responses.
Send these headers on every request:
Authorization: Bearer <token>Accept: application/json, text/event-streamContent-Type: application/jsonAdd X-Tenant: <slug> to that set now if this deployment resolves tenants by
header — check Tenant resolution before you send
initialize, because getting it wrong fails at the first request rather than at
the first tool call.
1. initialize
Section titled “1. initialize”{"jsonrpc":"2.0","id":0,"method":"initialize","params":{ "protocolVersion":"2025-06-18", "capabilities":{}, "clientInfo":{"name":"my-agent","version":"1.0.0"}}}The server keeps no sessions. The response has no Mcp-Session-Id header.
When a client sends that header, the server ignores it. Each request stands
alone, thus a restart of the server or a long idle time does not break the
connection. The result’s
serverInfo.name is kairos and serverInfo.version is the deployment’s
version — a useful assertion that you are talking to what you think you are.
Responses may arrive as plain JSON or as SSE framing (data: lines, with
priming events that carry no JSON-RPC payload). Parse both; do not assume one.
2. notifications/initialized
Section titled “2. notifications/initialized”{"jsonrpc":"2.0","method":"notifications/initialized"}This answers 202, not 200, and has no body. A client that insists on 200 will stall here.
3. tools/call
Section titled “3. tools/call”{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{ "name":"whoami","arguments":{}}}Tool output is text, in result.content[] entries of type text — short
codes, key: value lines, compact listings. It is not JSON to deserialize.
whoami returning your principal is the check that the whole chain works.
tools/list returns one profile of the eighty-four tools, frozen by name and
shape. Each one’s arguments, defaults and refusals are in
MCP tools.
/mcp lists the work profile (52 tools). For the administration tools, add
?profile=admin to the URL, or ?profile=all for each tool. See
Profiles.
The profile changes only the list. Kairos runs a call to a tool that the profile does not list, with the usual checks of the rights. A client that calls only the listed tools needs the URL of the right profile.
uat/surfaces/mcp.ts in the repository is a complete working client in about a
hundred lines — session handling, SSE parsing and tool-error handling included.
Copy from it rather than from this page if you are writing the transport
yourself.
Tenant resolution
Section titled “Tenant resolution”There is no tenant argument on any tool. The tenant comes from the connection, and which mechanism applies depends on how the deployment was configured (Configuration → Tenant resolution):
- An API key carries its own tenant. Send nothing; it resolves itself. This is the case for most agents, and the reason a key is simpler than a token.
- Subdomain tenancy (
KAIROS_BASE_DOMAIN): connect tohttps://acme.<base-domain>/mcpand theHostheader resolves the tenant. - Single-tenant (
KAIROS_SINGLE_TENANT): the tenant is pinned and both subdomain and header resolution are skipped. Send nothing; anX-Tenantheader is ignored. - Neither variable set: send
X-Tenant: acmealongside the bearer. This is the only case where the header does anything.
Errors the client must handle
Section titled “Errors the client must handle”Two levels, and they are easy to conflate:
Transport and auth errors are HTTP statuses on the POST:
| Status | Meaning |
|---|---|
401 |
No token, or an invalid one. The response carries an RFC 9728 WWW-Authenticate challenge whose resource_metadata= points at /.well-known/oauth-protected-resource/mcp, which an OAuth-capable client can follow to discover the issuer. |
403 |
Authenticated, but not a member of the resolved tenant — MEMBERSHIP_REQUIRED. Authenticating is not the same as belonging; add the principal to the organization. |
/mcp sits behind the same auth and tenant middleware as /api, so these are
the same failures with the same causes.
Tool refusals come back as 200 with result.isError set and the reason in
the text content. Treat those as data, not as transport failures — the text
carries the same stable codes the REST API uses (FORBIDDEN naming the missing
capability, INVALID_TRANSITION enumerating the allowed columns,
RESTORE_BLOCKED, and the rest). An agent that
retries a FORBIDDEN forever is the failure mode to design against; the
refusals are listed in MCP tools → Refusal
codes and
Errors.
Expect a live agent to meet FORBIDDEN on work it can see: a capability lost
to a reorg leaves the queue query working and every write refused
(Move work between boards).
Open each session with whoami
Section titled “Open each session with whoami”Call whoami and my_boards at the start of every session, and do not cache
the result across runs — capabilities change underneath a long-lived agent. Then
scope the work with list_repositories and
board_items {board, repository}. With the board of the agent’s team, that is
the queue for one checkout
(Repositories as execution
scope).
The result of board_items has 200 items at most. A result can be a part of
the board. Then its first lines give the offset of the next part. Call the
tool again with that offset.
Related
Section titled “Related”- MCP tools — all eighty-four, with arguments and refusals
- Give an agent machine access
- Connect the Claude Desktop app — the same endpoint from the Desktop app, with a connector or a bridge
- Capabilities and access
- Capabilities