Skip to content
CalabDocs

MCP server for LLM clients

POST /api/mcp — a Model Context Protocol endpoint on a bot token — six tools, JSON-RPC examples, errors, limits and what is not supported.

What it is

POST /api/mcp is a Model Context Protocol server built into the Calab API. An LLM client (an assistant, an IDE agent) needs only a URL and a bot token to find tasks and rooms, read them, create tasks, comment and write to rooms.

Every tool calls the ordinary REST routes of the server with the same token, so a tool gives the bot nothing its token does not already give: roles, route table, limits and moderation apply exactly as to the bot's own REST call. A refusal is final: the tool returns it as an error and does not look for a way around.

Connecting

  1. Create a bot and copy its token (Quickstart, Token and permissions): “Workspace settings → Bots”, the token is shown once.
  2. Give the bot a role in the workspaces it should see (Permissions).
  3. Point the client at https://<your Calab host>/api/mcp and send the header Authorization: Bearer calab_bot_…. The token goes only into the header, never into the URL.

The transport is Streamable HTTP: a JSON-RPC 2.0 request in the POST body, one JSON object in the answer.

Methods

MethodWhat it does
initializeHandshake. The answer repeats the client's protocolVersion if it is one of 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, otherwise the newest; capabilities — tools only
pingAn empty result
tools/listThe list of tools with JSON schemas
tools/callCalls a tool: params = {"name": "…", "arguments": {…}}
notifications (notifications/initialized, …)A request without id: answer 202, no action

Tools

ToolArguments (required in bold)Result
findq (words; for rooms and boards a name part, empty = all), kind (tasks · messages · rooms · boards; default all), workspace (id; default all the bot's workspaces), limit (per kind, 1–20, default 10)Ids for the other tools: tasks, messages (including task comments), rooms, boards; nothing found — {"found": 0}. q is required for tasks and messages
readtask (id or key ABC-12) or room (id; a task's comments are in its room), limit (messages, 1–50, default 20), before (message id: older history), full (true — the whole API object)A task with its board's statuses, subtasks and assignees; or a room and its recent messages (oldest first, more — there is older history)
create_taskboard (id), title (1–200 characters), description (markdown), status (name or id; default the board's)id, key, room, status
comment_tasktask (id or key), text (markdown)id, room of the new comment
set_task_statustask, status (a name or id of a status of that task's board)key, status. An unknown status is an error listing the board's statuses
send_messageroom (id; a DM works too), text (markdown, up to 4000 characters), reply_to (message id)id, room

Answers are compact: empty fields are left out. The usual flow: find → ids → read → an action.

Example

bash
curl -sS https://$HOST/api/mcp \
  -H "Authorization: Bearer $CALAB_BOT_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"set_task_status","arguments":{"task":"WEB-12","status":"Done"}}}'
JSON
{"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"{\"key\":\"WEB-12\",\"status\":\"Done\"}"}]}}

A tool result is a content array whose text holds a JSON string. A failed tool call is not a protocol error: the HTTP status is 200, the result has "isError": true and the text starts with the REST status and code, for example 404 NOT_FOUND: … — the model can fix the arguments or stop.

Errors

WhereWhatWhy
HTTP 401UNAUTHENTICATEDno or wrong token
HTTP 403FORBIDDENthe token is a person's or a session; Calab-On-Behalf is closed on this endpoint
HTTP 405Allow: POSTGET / DELETE — there is no stream and no sessions
HTTP 400JSON-RPC -32700 / -32600invalid JSON; not a JSON-RPC 2.0 request; a batch (array)
HTTP 413JSON-RPC -32600body over 1 MiB
JSON-RPC -32601method not foundan unknown method
JSON-RPC -32602unknown tool …, invalid paramsa wrong tool name or params
result with isError404 NOT_FOUND, 403, 409 PLAN_LIMIT, 429, validationthe REST call inside the tool was refused

Limits

A tool call costs one request of the bot's limit plus its REST calls (Errors and limits: 30 requests per second, 20 messages per minute). find without workspace walks all the bot's workspaces (rooms and boards), so for a bot in many workspaces name the workspace. When the limit is hit, the tool returns 429 as an error with isError.

Not supported

  • Streaming: no SSE answers, no GET stream, no resumption.
  • Sessions (Mcp-Session-Id) — every request stands alone.
  • JSON-RPC batches, MCP resources and prompts, structuredContent.
  • OAuth authorization of MCP: the bot token is set statically in the client.
  • “On behalf of” the owner or a member (Token and permissions).

Testing the endpoint

The repository has a curl script tools/mcp-smoke.sh (initialize → tools/list → find; it reads the token from CALAB_BOT_TOKEN and never prints it). The same by hand:

bash
export HOST=app.example.com CALAB_BOT_TOKEN=calab_bot_…
call() { curl -sS "https://$HOST/api/mcp" -H "Authorization: Bearer $CALAB_BOT_TOKEN" -H 'Content-Type: application/json' -d "$1"; echo; }
call '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'
call '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
call '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"find","arguments":{"q":"","kind":"boards"}}}'

Expected: initialize returns serverInfo.name = "calab", tools/list six tools, find a boards list (or {"found":0} if the bot sees no boards). Check the refusals: without the header — 401; with a person's token — 403.

To connect an MCP client (MCP Inspector, Claude Desktop or another one), choose the Streamable HTTP transport (the setting is named differently in different clients), set the URL https://<host>/api/mcp and the header Authorization: Bearer <bot token>; after connecting, the client must show six tools. Where exactly a client keeps its settings is in that client's own documentation.