10 KiB
MCP-интерфейс
Crank публикует REST-операции как MCP-инструменты через Streamable HTTP.
Endpoint агента
Каждый агент имеет собственный MCP endpoint:
/mcp/v1/{workspace_slug}/{agent_slug}
Для demo seed:
/mcp/v1/default/currency-rates
Полный URL зависит от вашего домена:
https://crank.example.com/mcp/v1/default/currency-rates
Авторизация
MCP-клиент должен передавать API-ключ агента:
Authorization: Bearer <agent_api_key>
Ключ выдается в разделе API ключи. Полное значение показывается только один раз при создании.
Для операций с подтверждением человеком нужен отдельный ключ подтверждения. Его тоже выдают в разделе API ключи, но в режиме Подтверждения. Такой ключ нельзя передавать LLM или MCP-клиенту. Он нужен только вашему внешнему интерфейсу, где пользователь нажимает «Подтвердить» или «Отклонить».
Поддерживаемые методы
MCP methods:
initialize;notifications/initialized;ping;tools/list;tools/call.
HTTP transport:
POST /mcp/v1/{workspace_slug}/{agent_slug}- JSON-RPC запросы;GET /mcp/v1/{workspace_slug}/{agent_slug}- server-to-client stream;DELETE /mcp/v1/{workspace_slug}/{agent_slug}- закрытие сессии.
Обязательные заголовки
Для POST:
Authorization: Bearer <agent_api_key>
Content-Type: application/json
Accept: application/json, text/event-stream
Для GET:
Authorization: Bearer <agent_api_key>
Accept: text/event-stream
MCP-Session-Id: <session_id>
После initialize сервер возвращает заголовок:
MCP-Session-Id: <session_id>
Если клиент передает MCP-Protocol-Version, он должен совпадать с версией, согласованной при инициализации.
Пример initialize
curl -i https://crank.example.com/mcp/v1/default/currency-rates \
-H 'Authorization: Bearer <agent_api_key>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": {
"name": "curl",
"version": "1.0.0"
}
}
}'
Сохраните MCP-Session-Id из ответа.
Пример tools/list
curl https://crank.example.com/mcp/v1/default/currency-rates \
-H 'Authorization: Bearer <agent_api_key>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'MCP-Session-Id: <session_id>' \
--data '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}'
Ожидаемый результат для demo seed содержит инструмент:
frankfurter_latest_rate
Пример tools/call
curl https://crank.example.com/mcp/v1/default/currency-rates \
-H 'Authorization: Bearer <agent_api_key>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'MCP-Session-Id: <session_id>' \
--data '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "frankfurter_latest_rate",
"arguments": {
"base": "USD",
"quote": "EUR"
}
}
}'
Crank выполнит REST-запрос:
GET https://api.frankfurter.dev/v1/latest?base=USD&symbols=EUR
Операции с подтверждением человеком
Если в мастере операции включено Подтверждение человеком, первый tools/call не выполняет REST-запрос сразу. Вместо этого Crank создает ожидающий запрос на подтверждение и возвращает MCP-клиенту структурированный результат:
{
"status": "approval_required",
"approval_id": "approval_...",
"approval_url": "/v1/default/sales/approvals/approval_...",
"approve": {
"method": "POST",
"url": "/v1/default/sales/approvals/approval_.../approve",
"body": { "approve": "yes" }
},
"deny": {
"method": "POST",
"url": "/v1/default/sales/approvals/approval_.../deny",
"body": { "approve": "no" }
}
}
approval_url в ответе является путем на MCP-сервере. Если вы публикуете MCP через префикс /mcp, внешний URL будет начинаться с /mcp/v1/....
Внешний интерфейс подтверждения работает отдельным ключом подтверждения:
curl https://crank.example.com/mcp/v1/default/sales/approvals \
-H 'Authorization: Bearer <approval_api_key>'
Статус конкретного запроса:
curl https://crank.example.com/mcp/v1/default/sales/approvals/<approval_id> \
-H 'Authorization: Bearer <approval_api_key>'
Подтверждение:
curl https://crank.example.com/mcp/v1/default/sales/approvals/<approval_id>/approve \
-H 'Authorization: Bearer <approval_api_key>' \
-H 'Content-Type: application/json' \
--data '{ "approve": "yes", "note": "Пользователь подтвердил действие" }'
После подтверждения Crank выполняет исходный REST-запрос с тем payload, который был сохранен при первом tools/call. Если запрос прошел успешно, заявка получает статус completed, а результат сохраняется в response_payload. Если upstream вернул ошибку, заявка получает статус failed, а в response_payload сохраняется код и текст ошибки.
Перед обращением к upstream заявка атомарно переходит в статус executing. Если
mcp-server завершился во время выполнения, другой рабочий цикл повторно захватит
заявку после истечения аренды. Для изменяющих операций рекомендуется настроить
execution_config.idempotency и передавать поддерживаемый upstream заголовок
идемпотентности: универсальный HTTP-клиент не может гарантировать ровно одно внешнее
побочное действие при падении процесса между ответом upstream и записью результата.
Повторный tools/call с теми же агентом, операцией, версией и JSON-аргументами
возвращает уже существующую активную заявку вместо создания дубликата.
Отклонение:
curl https://crank.example.com/mcp/v1/default/sales/approvals/<approval_id>/deny \
-H 'Authorization: Bearer <approval_api_key>' \
-H 'Content-Type: application/json' \
--data '{ "approve": "no", "note": "Пользователь отклонил действие" }'
Ключ MCP-клиента не подходит для этих endpoints. Ключ подтверждения, наоборот, не подходит для initialize, tools/list и tools/call.
Текущая реализация возвращает approval_required сразу и не держит исходный tools/call открытым до решения пользователя. Поэтому внешний интерфейс может восстановить результат через GET /approvals/<approval_id>. Долгое ожидание через Streamable HTTP/SSE запланировано отдельно.
Как формируется каталог инструментов
MCP-клиент видит только опубликованные операции, которые привязаны к опубликованному агенту.
Черновики операций не попадают в MCP-каталог. Если два пользователя работают в одном workspace, один может редактировать черновик, а второй публиковать агента. В опубликованный каталог попадут только опубликованные версии операций.
Обновление каталога
mcp-server периодически обновляет опубликованный каталог. Интервал задается:
CRANK_MCP_REFRESH_MS=5000
После публикации операции или агента подождите один интервал обновления или перезапустите mcp-server.
Ошибки
Частые причины ошибок:
401 Unauthorized- отсутствует или неверен API-ключ агента.403 Forbidden- ключ не имеет нужного доступа.404 Not Found- workspace, агент или инструмент не опубликованы.400 Bad Request- неверный MCP-заголовок, session id или JSON-RPC payload.429 Too Many Requests- сработал rate limit.
Runtime-ошибки инструмента возвращаются как структурированный MCP tool error с кодом, сообщением и request_id.