MCP: протокол для разработчиков клиентов
> Кратко. POST /mcp — сервер Model Context Protocol (JSON-RPC 2.0 поверх HTTP, без потоков и сессий). Здесь — то, что нужно, чтобы написать свой клиент или агента: методы, формат ответов и ошибок, список инструментов с аргументами, токен. Как подключить готовый клиент (Claude Desktop, Claude Code, Cursor) и выдать токен в кабинете — на странице MCP-сервер для ИИ-клиентов.
Транспорт
- Один адрес:
POST <API>/mcp(у API нескольких городов —/city/<код>/mcp, за nginx —/tgid/<город>/map-api/mcp). Ответ — всегдаapplication/json;GETиDELETE— 405 (потока событий и сессий нет,Mcp-Session-Idне выдаётся). - Заголовок
MCP-Protocol-Version:2025-06-18,2025-03-26или2024-11-05; другая версия — 400. Вinitializeсервер отвечает версией клиента, если знает её, иначе последней. - Пакет (массив сообщений, как в 2025-03-26) — от 1 до 10 сообщений; уведомления ответа не получают (только уведомления в запросе — HTTP 202 без тела).
- Тело — не больше 1 МБ (413). Заголовок
Originне изCORS_ALLOWED_ORIGINS— 403 (защита от DNS rebinding). - Вход:
Authorization: Bearer <токен>— токен ИИ-клиента (scope: mcp) или токен входа веба. Нет токена, истёк, пароль сменён — 401 сWWW-Authenticate: Bearer. Токен MCP на других адресах API не принимается (401), а ключи ArcGIS и API v2 не принимаются здесь. MCP_ENABLED=false— 404.
Методы
| Метод | Ответ |
|---|---|
initialize |
protocolVersion, capabilities: {"tools": {"listChanged": false}}, serverInfo (name: "tgid"), instructions — подсказка модели о сервере |
ping |
{} |
tools/list |
все 19 инструментов: name, title, description, inputSchema (JSON Schema из pydantic), annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) |
tools/call |
{"name": "…", "arguments": {…}} → результат инструмента |
| другие | ошибка JSON-RPC −32601 «Метод не поддерживается» |
Подписок на ресурсы, подсказок (prompts) и notifications/tools/list_changed нет.
Результат и ошибки
Успех: {"content": [{"type": "text", "text": "<JSON>"}], "structuredContent": {…}, "isError": false} —
ответ инструмента одной текстовой частью и тем же объектом в structuredContent. Геометрия из ответов убирается,
списки обрезаются до 200 элементов, очень длинный ответ — с пометкой «ответ обрезан — сузьте запрос».
Ошибка инструмента (неверный аргумент, нет права, нет расчёта, превышена частота) — не ошибка JSON-RPC, а
результат isError: true с текстом причины: модель видит её и может исправить вызов. Ошибки JSON-RPC — только
у самого протокола: −32700 (не JSON), −32600 (не сообщение JSON-RPC, неверный пакет), −32601 (метод),
−32602 (нет такого инструмента, arguments — не объект).
Персональные данные в ответах маскируются, если у пользователя токена нет права «Персональные данные».
Вызовы пишутся в журнал действий (MCP).
Ограничения: 60 вызовов инструментов в минуту на пользователя (RATE_LIMIT); run_calculation —
5 запусков за 10 минут (CALC_RATE_LIMIT) и право «Запуск расчётов». Счётчики — в памяти процесса API.
Инструменты
Список на копии Алматы (tools/list, 19 инструментов). Все, кроме run_calculation, только читают.
| Инструмент | Аргументы (обязательные — жирным) |
|---|---|
list_fragments |
— |
search_network |
kind (node, line, source, consumer), text, text2, fragment_id |
select_network |
target (lines, nodes), conditions, match (all, any), near, near_poi, in_view, fragment_ids, order_by, order_desc, limit |
network_trace |
trace_type (connected, upstream, downstream, subnetwork), config_id, stop_at (valves, pumpstations, setpress, sources), start_node_ids, start_line_ids, barrier_node_ids, barrier_line_ids |
list_trace_configs |
— |
valve_isolation |
line_id, node_id, failed_valve_ids |
network_statistics |
query (length, volume, length_by_diameter, length_by_diameter_laying, heat_consumption, closed_consumers), fragment_ids |
regime_analysis |
fragment_id, kind (negative_dp, airlock, low_temperature, closed_sections, hydrostatic_zones), calculation_id |
thematic_summary |
theme, fragment_ids, top |
wear_priorities |
fragment_id, min_category, limit |
similar_defects |
text, lon, lat, radius_m, limit |
failure_hotspots |
years |
data_quality |
fragment_id |
run_calculation |
fragment_ids, mode (plan, emergency), tn, name |
task_status |
task_id |
list_calculations |
fragment_ids, limit |
list_scenarios |
include_archived |
scenario_diff |
scenario_id, limit |
scenario_compare |
scenario_id, base_calculation_id, scenario_calculation_id, limit |
Точные типы, границы и описания аргументов — в inputSchema ответа tools/list. Девять инструментов (в том числе
run_calculation) доступны и как процессы OGC API — Processes с теми же аргументами.
Пример
H='Content-Type: application/json'; A="Authorization: Bearer $MCP_TOKEN"
curl -s -X POST "$API/mcp" -H "$H" -H "$A" -H "MCP-Protocol-Version: 2025-06-18" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"my-agent","version":"1"}}}'
curl -s -X POST "$API/mcp" -H "$H" -H "$A" -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
curl -s -X POST "$API/mcp" -H "$H" -H "$A" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"network_statistics","arguments":{"query":"length","fragment_ids":[74]}}}'
Ответ на копии Алматы:
{"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"{\"query\": \"length\", …}"}],"isError":false,
"structuredContent":{"query":"length","title":"Длина теплопроводов, м","fragment_ids":[74],
"length_supply_m":197263.2,"length_return_m":197576.4,"length_total_m":394839.6}}}
Неизвестный метод: {"jsonrpc":"2.0","id":4,"error":{"code":-32601,"message":"Метод не поддерживается: nope"}}.
Запрос с Origin: https://evil.example — 403 {"detail":"Origin не разрешён"}.
task_status отвечает тем же, что GET /api/v1/task/{task_id}: состояние задания и, когда оно готово, итог
расчёта. Так агент следит за расчётом, который сам запустил через run_calculation.
Токен
POST /api/v1/mcp/token с токеном входа → {"token", "expires_at", "days", "path": "/mcp"}. Срок —
MCP_TOKEN_DAYS (по умолчанию 30, не больше 90). Токен — JWT с scope: mcp и отпечатком пароля (pwf);
отозвать его по одному нельзя — только сменой пароля или блокировкой учётной записи. GET /api/v1/mcp/info —
включён ли сервер, срок токена и инструменты (name, title, permission).
На стенде с AUTH_DISABLED=true /mcp принимает вызовы без токена от имени администратора.
Для разработчика
- API:
routers/mcp.py(транспорт, Origin, токен),tgid_mcp/protocol.py(JSON-RPC,PROTOCOL_VERSIONS),tgid_mcp/tools.py(реестрTOOLS,describe_tools,RATE_LIMIT,MAX_LIST_ITEMS). Новый инструмент — pydantic-модель параметров, функцияrun, право и пометкаread_onlyв реестре; он сразу появится у MCP, у помощника ИИ и (если добавить вPROCESSES) в OGC Processes. - Тесты: API —
tests/test_mcp.py; e2e —e2e/functions/ai.spec.ts,e2e/functions/developer-api.spec.ts.
