MCP-сервер для LLM-клиентов
POST /api/mcp — эндпоинт Model Context Protocol на токене бота — шесть инструментов, примеры JSON-RPC, ошибки, лимиты и что не поддержано.
Что это
POST /api/mcp — сервер Model Context Protocol, встроенный в API Calab. LLM-клиенту (ассистенту, агенту в IDE) достаточно адреса и токена бота, чтобы искать задачи и комнаты, читать их, создавать задачи, комментировать и писать в комнаты.
Каждый инструмент вызывает обычные маршруты REST сервера тем же токеном, поэтому инструмент не даёт боту больше, чем его токен: роли, таблица маршрутов, лимиты и модерация применяются так же, как к собственному REST-вызову бота. Отказ окончателен: инструмент возвращает его как ошибку и не ищет обходных путей.
Подключение
- Создайте бота и скопируйте токен (Быстрый старт, Токен и права): «Настройки пространства → Боты», токен показывается один раз.
- Дайте боту роль в пространствах, которые он должен видеть (Права).
- Укажите клиенту адрес
https://<ваш хост Calab>/api/mcpи заголовокAuthorization: Bearer calab_bot_…. Токен — только в заголовке, не в URL.
Транспорт — Streamable HTTP: запрос JSON-RPC 2.0 в теле POST, ответ — один JSON-объект.
Методы
| Метод | Что делает |
|---|---|
initialize | Рукопожатие. В ответе версия клиента protocolVersion, если она одна из 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, иначе новейшая; возможности — только tools |
ping | Пустой результат |
tools/list | Список инструментов с JSON-схемами |
tools/call | Вызов инструмента: params = {"name": "…", "arguments": {…}} |
уведомления (notifications/initialized, …) | Запрос без id: ответ 202, без действий |
Инструменты
| Инструмент | Аргументы (обязательные выделены) | Результат |
|---|---|---|
find | q (слова; для комнат и досок — часть названия, пусто = все), kind (tasks · messages · rooms · boards; по умолчанию все), workspace (id; по умолчанию все пространства бота), limit (на каждый вид, 1–20, по умолчанию 10) | Идентификаторы для других инструментов: tasks, messages (включая комментарии задач), rooms, boards; ничего нет — {"found": 0}. q обязателен для tasks и messages |
read | task (id или ключ ABC-12) или room (id; комментарии задачи — в её комнате), limit (сообщений, 1–50, по умолчанию 20), before (id сообщения: более старая история), full (true — объект API целиком) | Задача со статусами её доски, подзадачами и исполнителями; или комната и последние сообщения (старые первыми, more — есть ещё более старые) |
create_task | board (id), title (1–200 символов), description (markdown), status (имя или id; по умолчанию статус доски) | id, key, room, status |
comment_task | task (id или ключ), text (markdown) | id, room нового комментария |
set_task_status | task, status (имя или id статуса доски этой задачи) | key, status. Неизвестный статус — ошибка со списком статусов доски |
send_message | room (id; подойдёт и DM), text (markdown, до 4000 символов), reply_to (id сообщения) | id, room |
Ответы компактные: пустые поля опускаются. Обычный путь: find → id → read → действие.
Пример
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"}}}'{"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"{\"key\":\"WEB-12\",\"status\":\"Done\"}"}]}}Результат инструмента — массив content, в text лежит строка JSON. Неудачный вызов инструмента не ошибка протокола: HTTP-статус 200, в результате "isError": true, а текст начинается со статуса и кода REST, например 404 NOT_FOUND: … — модель может исправить аргументы или остановиться.
Ошибки
| Где | Что | Почему |
|---|---|---|
HTTP 401 | UNAUTHENTICATED | нет токена или он неверный |
HTTP 403 | FORBIDDEN | токен человека или сессия; Calab-On-Behalf на этом эндпоинте закрыт |
HTTP 405 | Allow: POST | GET / DELETE — потока и сессий нет |
HTTP 400 | JSON-RPC -32700 / -32600 | невалидный JSON; это не запрос JSON-RPC 2.0; пакет (массив) |
HTTP 413 | JSON-RPC -32600 | тело больше 1 МиБ |
JSON-RPC -32601 | method not found | неизвестный метод |
JSON-RPC -32602 | unknown tool …, invalid params | неверное имя инструмента или params |
результат с isError | 404 NOT_FOUND, 403, 409 PLAN_LIMIT, 429, валидация | REST-вызов внутри инструмента отклонён |
Лимиты
Вызов инструмента стоит один запрос из лимита бота плюс его вызовы REST (Ошибки и лимиты: 30 запросов в секунду, 20 сообщений в минуту). find без workspace обходит все пространства бота (комнаты и доски), поэтому боту во многих пространствах лучше указывать workspace. При упоре в лимит инструмент возвращает 429 как ошибку с isError.
Не поддержано
- Стриминг: нет SSE-ответов,
GET-потока и возобновления. - Сессии (
Mcp-Session-Id) — каждый запрос самостоятельный. - Пакеты JSON-RPC, ресурсы и промпты MCP,
structuredContent. - OAuth-авторизация MCP: токен бота задаётся в клиенте статически.
- «От имени» владельца или участника (Токен и права).
Проверка эндпоинта
В репозитории есть скрипт tools/mcp-smoke.sh (initialize → tools/list → find; токен берёт из CALAB_BOT_TOKEN и не печатает). То же вручную:
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"}}}'Ожидаемо: initialize отвечает serverInfo.name = "calab", tools/list — шесть инструментов, find — список boards (или {"found":0}, если бот не видит досок). Проверьте отказы: без заголовка — 401, с токеном человека — 403.
Чтобы подключить MCP-клиент (MCP Inspector, Claude Desktop или другой), выберите транспорт Streamable HTTP (название настройки у клиентов разное), укажите адрес https://<хост>/api/mcp и заголовок Authorization: Bearer <токен бота>; после подключения клиент должен показать шесть инструментов. Где именно клиент хранит настройки — в его собственной документации.