Complete markdown documentation
This commit is contained in:
@@ -264,6 +264,9 @@ npx playwright test
|
||||
- [Веб-интерфейс](docs/ui.md)
|
||||
- [MCP-интерфейс](docs/mcp-interface.md)
|
||||
- [Admin API](docs/admin-api.md)
|
||||
- [Практические API-примеры](docs/api-examples.md)
|
||||
- [Production checklist](docs/production-checklist.md)
|
||||
- [Troubleshooting](docs/troubleshooting.md)
|
||||
- [Настройки запуска](docs/runtime-config.md)
|
||||
- [Английский README](docs/en/README.md)
|
||||
|
||||
|
||||
+5
-2
@@ -2,7 +2,7 @@
|
||||
|
||||
Crank превращает REST API endpoint-ы в MCP-инструменты, которые можно подключать к AI-агентам и MCP-клиентам.
|
||||
|
||||
Эта документация подготовлена как основа для будущего сайта. Сейчас файлы лежат в `docs/`, позже их можно перенести в Docusaurus без изменения структуры тем.
|
||||
Документация хранится в Markdown-файлах внутри `docs/` и читается прямо из репозитория.
|
||||
|
||||
## Начать
|
||||
|
||||
@@ -10,6 +10,7 @@ Crank превращает REST API endpoint-ы в MCP-инструменты,
|
||||
- [Установка](./installation.md)
|
||||
- [Первый инструмент](./quickstart.md)
|
||||
- [Подключение MCP-клиента](./mcp-interface.md)
|
||||
- [Практические API-примеры](./api-examples.md)
|
||||
|
||||
## Возможности
|
||||
|
||||
@@ -17,13 +18,15 @@ Crank превращает REST API endpoint-ы в MCP-инструменты,
|
||||
- [REST-инструменты](./protocols/rest.md)
|
||||
- [Секреты и профили авторизации](./secrets-and-auth.md)
|
||||
- [Журналы и использование](./observability.md)
|
||||
- [Проектирование MCP-инструментов](./tool-design.md)
|
||||
|
||||
## Справочник
|
||||
|
||||
- [Настройки окружения](./runtime-config.md)
|
||||
- [Admin API](./admin-api.md)
|
||||
- [Развертывание](./deployment.md)
|
||||
- [Production checklist](./production-checklist.md)
|
||||
- [Troubleshooting](./troubleshooting.md)
|
||||
- [Архитектура](./architecture.md)
|
||||
- [Модель данных](./data-model.md)
|
||||
- [Тестирование](./testing-strategy.md)
|
||||
|
||||
|
||||
+159
-19
@@ -1,6 +1,6 @@
|
||||
# Admin API
|
||||
|
||||
Admin API используется UI для управления Crank Community.
|
||||
Admin API используется веб-интерфейсом Crank. Его можно использовать и напрямую для автоматизации настройки.
|
||||
|
||||
Base path:
|
||||
|
||||
@@ -8,7 +8,33 @@ Base path:
|
||||
/api/admin
|
||||
```
|
||||
|
||||
## Auth
|
||||
Auth path:
|
||||
|
||||
```text
|
||||
/api/auth
|
||||
```
|
||||
|
||||
## Авторизация
|
||||
|
||||
Администратор входит по email и паролю. После входа сервер устанавливает HttpOnly session cookie.
|
||||
|
||||
```bash
|
||||
curl -i https://crank.example.com/api/auth/login \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"email": "owner@example.com",
|
||||
"password": "change-me"
|
||||
}'
|
||||
```
|
||||
|
||||
Дальше используйте cookie из ответа:
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/auth/session \
|
||||
-b 'crank_session=<cookie_value>'
|
||||
```
|
||||
|
||||
Endpoints:
|
||||
|
||||
- `POST /api/auth/login`
|
||||
- `POST /api/auth/logout`
|
||||
@@ -17,30 +43,60 @@ Base path:
|
||||
- `PATCH /api/auth/profile`
|
||||
- `POST /api/auth/password`
|
||||
|
||||
Авторизация основана на email/password и HttpOnly session cookie.
|
||||
|
||||
## Capabilities
|
||||
|
||||
- `GET /api/admin/capabilities`
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/capabilities \
|
||||
-b 'crank_session=<cookie_value>'
|
||||
```
|
||||
|
||||
Community capabilities:
|
||||
|
||||
- supported protocol: `rest`
|
||||
- supported security level: `standard`
|
||||
- machine access mode: static agent key
|
||||
- protocol: `rest`;
|
||||
- operation security level: `standard`;
|
||||
- machine access: static agent API keys.
|
||||
|
||||
## Workspaces
|
||||
|
||||
Community работает с одним workspace.
|
||||
|
||||
- `GET /api/admin/workspaces`
|
||||
- `GET /api/admin/workspaces/{workspace_id}`
|
||||
- `PATCH /api/admin/workspaces/{workspace_id}`
|
||||
|
||||
Community работает с одним bootstrap workspace. API не поддерживает создание
|
||||
дополнительных workspace-ов, переключение текущего workspace-а, приглашения
|
||||
пользователей и управление ролями.
|
||||
Пример:
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces \
|
||||
-b 'crank_session=<cookie_value>'
|
||||
```
|
||||
|
||||
## Upstreams
|
||||
|
||||
Upstream хранит базовый URL внешнего REST API и необязательные статические заголовки.
|
||||
|
||||
- `GET /api/admin/workspaces/{workspace_id}/upstreams`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/upstreams`
|
||||
- `PATCH /api/admin/workspaces/{workspace_id}/upstreams/{upstream_id}`
|
||||
|
||||
Пример создания:
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces/ws_default/upstreams \
|
||||
-b 'crank_session=<cookie_value>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"name": "Frankfurter",
|
||||
"base_url": "https://api.frankfurter.dev",
|
||||
"static_headers": {},
|
||||
"auth_profile_id": null
|
||||
}'
|
||||
```
|
||||
|
||||
## Operations
|
||||
|
||||
Операция описывает один REST endpoint как MCP-инструмент.
|
||||
|
||||
- `GET /api/admin/workspaces/{workspace_id}/operations`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/operations`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/operations/analyze-quality`
|
||||
@@ -53,8 +109,33 @@ Community работает с одним bootstrap workspace. API не подд
|
||||
- `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/archive`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/test-runs`
|
||||
- `GET /api/admin/workspaces/{workspace_id}/operations/{operation_id}/export`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/operations/import`
|
||||
|
||||
`analyze-quality` принимает такой же draft payload, как создание операции, и возвращает отчет:
|
||||
Пример тестового запуска:
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces/ws_default/operations/<operation_id>/test-runs \
|
||||
-b 'crank_session=<cookie_value>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"version": 1,
|
||||
"input": {
|
||||
"base": "USD",
|
||||
"quote": "EUR"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
Пример публикации:
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces/ws_default/operations/<operation_id>/publish \
|
||||
-b 'crank_session=<cookie_value>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data '{ "version": 1 }'
|
||||
```
|
||||
|
||||
`analyze-quality` принимает payload операции и возвращает рекомендации:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -70,9 +151,6 @@ Community работает с одним bootstrap workspace. API не подд
|
||||
]
|
||||
}
|
||||
```
|
||||
- `POST /api/admin/workspaces/{workspace_id}/operations/import`
|
||||
|
||||
Community принимает только `protocol = rest`.
|
||||
|
||||
## Samples
|
||||
|
||||
@@ -80,6 +158,8 @@ Community принимает только `protocol = rest`.
|
||||
- `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/samples/output-json`
|
||||
- `POST /api/admin/workspaces/{workspace_id}/operations/{operation_id}/drafts/generate`
|
||||
|
||||
Samples используются для генерации схемы, стартового маппинга и сохранения тестовых примеров wizard-а.
|
||||
|
||||
## Secrets
|
||||
|
||||
- `GET /api/admin/workspaces/{workspace_id}/secrets`
|
||||
@@ -88,8 +168,20 @@ Community принимает только `protocol = rest`.
|
||||
- `POST /api/admin/workspaces/{workspace_id}/secrets/{secret_id}/rotate`
|
||||
- `DELETE /api/admin/workspaces/{workspace_id}/secrets/{secret_id}`
|
||||
|
||||
Create-response может вернуть plaintext secret только один раз. List/read endpoints
|
||||
возвращают только metadata.
|
||||
Пример создания token secret:
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces/ws_default/secrets \
|
||||
-b 'crank_session=<cookie_value>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"name": "production-api-token",
|
||||
"kind": "token",
|
||||
"value": "secret-token-value"
|
||||
}'
|
||||
```
|
||||
|
||||
После создания или ротации API возвращает только metadata. Значение секрета нельзя прочитать повторно.
|
||||
|
||||
## Auth profiles
|
||||
|
||||
@@ -99,7 +191,7 @@ Create-response может вернуть plaintext secret только один
|
||||
- `PATCH /api/admin/workspaces/{workspace_id}/auth-profiles/{auth_profile_id}`
|
||||
- `DELETE /api/admin/workspaces/{workspace_id}/auth-profiles/{auth_profile_id}`
|
||||
|
||||
Auth profile хранит ссылки на secrets и способ применения credential к REST request.
|
||||
Auth profile хранит ссылки на secrets и способ применения секрета к REST-запросу.
|
||||
|
||||
## Agents
|
||||
|
||||
@@ -116,6 +208,21 @@ Auth profile хранит ссылки на secrets и способ примен
|
||||
- `POST /api/admin/workspaces/{workspace_id}/agents/{agent_id}/bindings`
|
||||
- `DELETE /api/admin/workspaces/{workspace_id}/agents/{agent_id}/bindings/{operation_id}`
|
||||
|
||||
Пример создания агента:
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces/ws_default/agents \
|
||||
-b 'crank_session=<cookie_value>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"slug": "currency-rates",
|
||||
"display_name": "Курсы валют",
|
||||
"description": "Агент с инструментами для получения курсов валют.",
|
||||
"instructions": {},
|
||||
"tool_selection_policy": {}
|
||||
}'
|
||||
```
|
||||
|
||||
## Agent API keys
|
||||
|
||||
- `GET /api/admin/workspaces/{workspace_id}/agents/{agent_id}/platform-api-keys`
|
||||
@@ -123,9 +230,42 @@ Auth profile хранит ссылки на secrets и способ примен
|
||||
- `POST /api/admin/workspaces/{workspace_id}/agents/{agent_id}/platform-api-keys/{key_id}/revoke`
|
||||
- `DELETE /api/admin/workspaces/{workspace_id}/agents/{agent_id}/platform-api-keys/{key_id}`
|
||||
|
||||
Полное значение ключа доступно только в create-response.
|
||||
Пример создания ключа:
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces/ws_default/agents/<agent_id>/platform-api-keys \
|
||||
-b 'crank_session=<cookie_value>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"name": "Demo MCP client",
|
||||
"scopes": ["read", "write"]
|
||||
}'
|
||||
```
|
||||
|
||||
Полное значение ключа доступно только в create response.
|
||||
|
||||
## Logs и usage
|
||||
|
||||
- `GET /api/admin/workspaces/{workspace_id}/logs`
|
||||
- `GET /api/admin/workspaces/{workspace_id}/usage`
|
||||
|
||||
Пример:
|
||||
|
||||
```bash
|
||||
curl 'https://crank.example.com/api/admin/workspaces/ws_default/logs?limit=20' \
|
||||
-b 'crank_session=<cookie_value>'
|
||||
```
|
||||
|
||||
## Ошибки
|
||||
|
||||
Admin API возвращает JSON-ошибки с человекочитаемым сообщением и контекстом, если он доступен.
|
||||
|
||||
Частые HTTP-коды:
|
||||
|
||||
- `400` - неверный payload;
|
||||
- `401` - нет сессии;
|
||||
- `403` - действие запрещено;
|
||||
- `404` - сущность не найдена;
|
||||
- `409` - конфликт состояния;
|
||||
- `429` - rate limit;
|
||||
- `500` - внутренняя ошибка.
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
# Практические API-примеры
|
||||
|
||||
Здесь собраны минимальные запросы для проверки Crank без веб-интерфейса.
|
||||
|
||||
В примерах используется:
|
||||
|
||||
```text
|
||||
https://crank.example.com
|
||||
```
|
||||
|
||||
Замените адрес на свой.
|
||||
|
||||
## Вход
|
||||
|
||||
```bash
|
||||
curl -i https://crank.example.com/api/auth/login \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"email": "owner@example.com",
|
||||
"password": "change-me"
|
||||
}'
|
||||
```
|
||||
|
||||
Сохраните cookie `crank_session`.
|
||||
|
||||
## Получить workspace
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces \
|
||||
-b 'crank_session=<cookie_value>'
|
||||
```
|
||||
|
||||
Для стандартной установки workspace id:
|
||||
|
||||
```text
|
||||
ws_default
|
||||
```
|
||||
|
||||
## Получить операции
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces/ws_default/operations \
|
||||
-b 'crank_session=<cookie_value>'
|
||||
```
|
||||
|
||||
После demo seed ожидается операция:
|
||||
|
||||
```text
|
||||
frankfurter_latest_rate
|
||||
```
|
||||
|
||||
## Запустить тест операции
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces/ws_default/operations/<operation_id>/test-runs \
|
||||
-b 'crank_session=<cookie_value>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"version": 1,
|
||||
"input": {
|
||||
"base": "USD",
|
||||
"quote": "EUR"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
## Получить агентов
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces/ws_default/agents \
|
||||
-b 'crank_session=<cookie_value>'
|
||||
```
|
||||
|
||||
После demo seed ожидается агент:
|
||||
|
||||
```text
|
||||
currency-rates
|
||||
```
|
||||
|
||||
## Создать API-ключ агента
|
||||
|
||||
```bash
|
||||
curl https://crank.example.com/api/admin/workspaces/ws_default/agents/<agent_id>/platform-api-keys \
|
||||
-b 'crank_session=<cookie_value>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"name": "Manual MCP test",
|
||||
"scopes": ["read", "write"]
|
||||
}'
|
||||
```
|
||||
|
||||
Сохраните поле `secret`. Оно не будет показано повторно.
|
||||
|
||||
## Проверить MCP initialize
|
||||
|
||||
```bash
|
||||
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` из заголовков ответа.
|
||||
|
||||
## Вызвать инструмент
|
||||
|
||||
```bash
|
||||
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/call",
|
||||
"params": {
|
||||
"name": "frankfurter_latest_rate",
|
||||
"arguments": {
|
||||
"base": "USD",
|
||||
"quote": "EUR"
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
+29
-37
@@ -1,52 +1,44 @@
|
||||
# Crank
|
||||
|
||||
Crank Community is a self-hosted platform for publishing REST APIs as MCP tools.
|
||||
Crank is a self-hosted platform for turning REST API endpoints into MCP tools.
|
||||
|
||||
It lets operators describe an upstream REST endpoint, test it, publish it, and
|
||||
expose it to LLM clients through MCP without writing a custom MCP server for
|
||||
each integration.
|
||||
The product provides a web UI for describing an upstream REST endpoint, testing it, publishing it as a tool, and exposing it to MCP clients through an agent-scoped endpoint.
|
||||
|
||||
## Features
|
||||
## What Crank Does
|
||||
|
||||
- REST operation creation from the web UI or YAML.
|
||||
- MCP input mapping into REST query, body, and header fields.
|
||||
- REST response mapping into structured MCP tool output.
|
||||
- Agent-scoped MCP endpoints with curated tool catalogs.
|
||||
- Operation drafts, versions, samples, mappings, logs, and usage in PostgreSQL.
|
||||
- Simple admin authentication with a bootstrap admin user.
|
||||
- PostgreSQL-backed secrets and auth profiles for upstream REST APIs.
|
||||
- Docker Compose deployment.
|
||||
- Creates REST tools from the web UI or YAML.
|
||||
- Maps MCP input into REST path, query, headers, or JSON body.
|
||||
- Maps REST responses into structured tool output.
|
||||
- Publishes selected tools through a specific agent.
|
||||
- Issues static API keys for MCP clients.
|
||||
- Stores operations, versions, samples, secrets, logs, and usage in PostgreSQL.
|
||||
- Runs with Docker Compose.
|
||||
|
||||
## Community Scope
|
||||
|
||||
This repository contains only the Community feature set:
|
||||
This repository contains the Community version:
|
||||
|
||||
- REST protocol only.
|
||||
- Single self-hosted deployment.
|
||||
- Simple admin authentication.
|
||||
- Static agent API keys for MCP access.
|
||||
- PostgreSQL as the system database.
|
||||
- Optional Valkey/Redis cache for runtime coordination.
|
||||
- Gitea Actions CI/CD.
|
||||
- one workspace;
|
||||
- one admin user;
|
||||
- unlimited agents;
|
||||
- REST protocol;
|
||||
- MCP Streamable HTTP;
|
||||
- static agent API keys;
|
||||
- PostgreSQL database;
|
||||
- optional Valkey or Redis for temporary coordination state.
|
||||
|
||||
The repository is focused only on the scope listed above.
|
||||
## Documentation
|
||||
|
||||
## Architecture
|
||||
The main documentation is currently maintained in Russian:
|
||||
|
||||
Core concepts:
|
||||
|
||||
- `Workspace` is the data boundary for operations, agents, secrets, and logs.
|
||||
- `Operation` is a versioned REST integration contract.
|
||||
- `Agent` is an MCP surface that exposes a curated set of operations.
|
||||
|
||||
Runtime flow:
|
||||
|
||||
1. An operator creates or imports a REST operation.
|
||||
2. Crank validates the schema and mapping.
|
||||
3. The operator runs a test call against the upstream REST API.
|
||||
4. The operation is published.
|
||||
5. An agent exposes the published operation as an MCP tool.
|
||||
6. MCP clients call the tool through `mcp-server`.
|
||||
- [Documentation index](../README.md)
|
||||
- [Introduction](../intro.md)
|
||||
- [Installation](../installation.md)
|
||||
- [Quickstart](../quickstart.md)
|
||||
- [MCP interface](../mcp-interface.md)
|
||||
- [Admin API](../admin-api.md)
|
||||
- [Runtime configuration](../runtime-config.md)
|
||||
- [Troubleshooting](../troubleshooting.md)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -75,3 +75,6 @@ docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Следующий шаг
|
||||
|
||||
После установки пройдите [первый инструмент](./quickstart.md). Если что-то не запускается, используйте [troubleshooting](./troubleshooting.md).
|
||||
|
||||
+146
-75
@@ -1,106 +1,177 @@
|
||||
# MCP Interface
|
||||
# MCP-интерфейс
|
||||
|
||||
Crank Community публикует REST operations как MCP tools поверх Streamable HTTP.
|
||||
Crank публикует REST-операции как MCP-инструменты через Streamable HTTP.
|
||||
|
||||
## Transport
|
||||
## Endpoint агента
|
||||
|
||||
MCP server запускается отдельным приложением `mcp-server`.
|
||||
|
||||
Поддерживается:
|
||||
|
||||
- MCP Streamable HTTP;
|
||||
- JSON-RPC requests через `POST`;
|
||||
- optional server-to-client stream через `GET`;
|
||||
- explicit session close через `DELETE`.
|
||||
|
||||
`stdio` не входит в Community deployment.
|
||||
|
||||
## Endpoint model
|
||||
|
||||
Canonical endpoint:
|
||||
Каждый агент имеет собственный MCP endpoint:
|
||||
|
||||
```text
|
||||
/mcp/v1/{workspace_slug}/{agent_slug}
|
||||
```
|
||||
|
||||
Endpoint определяет:
|
||||
Для demo seed:
|
||||
|
||||
- workspace;
|
||||
- published agent;
|
||||
- curated tool catalog агента;
|
||||
- labels для logs и usage.
|
||||
```text
|
||||
/mcp/v1/default/currency-rates
|
||||
```
|
||||
|
||||
## Authentication
|
||||
Полный URL зависит от вашего домена:
|
||||
|
||||
Community использует static agent API keys.
|
||||
```text
|
||||
https://crank.example.com/mcp/v1/default/currency-rates
|
||||
```
|
||||
|
||||
Правила:
|
||||
## Авторизация
|
||||
|
||||
- каждый published agent может иметь собственные API keys;
|
||||
- key принадлежит одному workspace и одному agent;
|
||||
- `mcp-server` показывает только tools, привязанные к этому agent;
|
||||
- unsupported token issuance modes отклоняются.
|
||||
MCP-клиент должен передавать API-ключ агента:
|
||||
|
||||
## Tool catalog
|
||||
```http
|
||||
Authorization: Bearer <agent_api_key>
|
||||
```
|
||||
|
||||
Одна published REST operation становится одним MCP tool.
|
||||
Ключ выдается в разделе **API ключи**. Полное значение показывается только один раз при создании.
|
||||
|
||||
Tool definition строится из:
|
||||
|
||||
- operation name или binding-level tool name;
|
||||
- tool title и description;
|
||||
- input schema;
|
||||
- published operation version.
|
||||
|
||||
Draft operations никогда не публикуются через MCP.
|
||||
|
||||
## Supported methods
|
||||
## Поддерживаемые методы
|
||||
|
||||
MCP methods:
|
||||
|
||||
- `initialize`
|
||||
- `notifications/initialized`
|
||||
- `ping`
|
||||
- `tools/list`
|
||||
- `tools/call`
|
||||
- `initialize`;
|
||||
- `notifications/initialized`;
|
||||
- `ping`;
|
||||
- `tools/list`;
|
||||
- `tools/call`.
|
||||
|
||||
Transport endpoints:
|
||||
HTTP transport:
|
||||
|
||||
- `POST /mcp/v1/{workspace_slug}/{agent_slug}`
|
||||
- `GET /mcp/v1/{workspace_slug}/{agent_slug}`
|
||||
- `DELETE /mcp/v1/{workspace_slug}/{agent_slug}`
|
||||
- `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}` - закрытие сессии.
|
||||
|
||||
## `tools/list`
|
||||
## Обязательные заголовки
|
||||
|
||||
1. Client authenticates через agent API key.
|
||||
2. `mcp-server` resolves workspace и agent из path.
|
||||
3. Server loads published agent catalog.
|
||||
4. Server returns only tools bound to that agent.
|
||||
Для `POST`:
|
||||
|
||||
## `tools/call`
|
||||
```http
|
||||
Authorization: Bearer <agent_api_key>
|
||||
Content-Type: application/json
|
||||
Accept: application/json, text/event-stream
|
||||
```
|
||||
|
||||
1. Client вызывает tool.
|
||||
2. `mcp-server` валидирует input по tool schema.
|
||||
3. Runtime maps MCP input в REST request.
|
||||
4. REST adapter вызывает upstream API.
|
||||
5. Runtime maps REST response в tool output.
|
||||
6. `mcp-server` возвращает normalized result.
|
||||
Для `GET`:
|
||||
|
||||
## Refresh
|
||||
```http
|
||||
Authorization: Bearer <agent_api_key>
|
||||
Accept: text/event-stream
|
||||
MCP-Session-Id: <session_id>
|
||||
```
|
||||
|
||||
Published catalog refresh управляется `CRANK_MCP_REFRESH_MS`.
|
||||
После `initialize` сервер возвращает заголовок:
|
||||
|
||||
После публикации operation или agent `mcp-server` подхватывает новый catalog без
|
||||
restart.
|
||||
```http
|
||||
MCP-Session-Id: <session_id>
|
||||
```
|
||||
|
||||
## Error categories
|
||||
Если клиент передает `MCP-Protocol-Version`, он должен совпадать с версией, согласованной при инициализации.
|
||||
|
||||
MCP responses различают:
|
||||
## Пример `initialize`
|
||||
|
||||
- authentication errors;
|
||||
- missing workspace или agent;
|
||||
- missing tool;
|
||||
- schema validation errors;
|
||||
- mapping errors;
|
||||
- upstream REST errors;
|
||||
- internal runtime errors.
|
||||
```bash
|
||||
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`
|
||||
|
||||
```bash
|
||||
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 содержит инструмент:
|
||||
|
||||
```text
|
||||
frankfurter_latest_rate
|
||||
```
|
||||
|
||||
## Пример `tools/call`
|
||||
|
||||
```bash
|
||||
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-запрос:
|
||||
|
||||
```text
|
||||
GET https://api.frankfurter.dev/v1/latest?base=USD&symbols=EUR
|
||||
```
|
||||
|
||||
## Как формируется каталог инструментов
|
||||
|
||||
MCP-клиент видит только опубликованные операции, которые привязаны к опубликованному агенту.
|
||||
|
||||
Черновики операций не попадают в MCP-каталог. Если два пользователя работают в одном workspace, один может редактировать черновик, а второй публиковать агента. В опубликованный каталог попадут только опубликованные версии операций.
|
||||
|
||||
## Обновление каталога
|
||||
|
||||
`mcp-server` периодически обновляет опубликованный каталог. Интервал задается:
|
||||
|
||||
```env
|
||||
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`.
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# Production checklist
|
||||
|
||||
Этот список помогает подготовить Crank к постоянной работе на сервере.
|
||||
|
||||
## Перед запуском
|
||||
|
||||
- Сгенерирован сильный `CRANK_MASTER_KEY`.
|
||||
- Сгенерирован сильный `CRANK_SESSION_SECRET`.
|
||||
- Сгенерирован сильный `CRANK_PASSWORD_PEPPER`.
|
||||
- Задан надежный `CRANK_BOOTSTRAP_ADMIN_PASSWORD`.
|
||||
- `CRANK_BASE_URL` указывает на публичный HTTPS URL.
|
||||
- PostgreSQL доступен с host, где запускаются контейнеры.
|
||||
- Для PostgreSQL настроены бэкапы.
|
||||
- Reverse proxy проксирует `/`, `/api/admin/` и `/mcp/`.
|
||||
- Для `/mcp/` отключено proxy buffering.
|
||||
- Порты опубликованы только там, где нужно: `127.0.0.1` или `0.0.0.0`.
|
||||
|
||||
## После запуска
|
||||
|
||||
- `curl /health` для `admin-api` возвращает `ok`.
|
||||
- `curl /health` для `mcp-server` возвращает `ok`.
|
||||
- UI открывается по публичному домену.
|
||||
- Вход под bootstrap admin работает.
|
||||
- Demo seed создал Frankfurter-пример, если `CRANK_DEMO_SEED=true`.
|
||||
- Тест операции `frankfurter_latest_rate` проходит.
|
||||
- MCP-клиент видит инструмент через агента `currency-rates`.
|
||||
|
||||
## Безопасность
|
||||
|
||||
- Не храните `.env` в Git.
|
||||
- Не передавайте API-ключи агентов в чатах и тикетах.
|
||||
- Выдавайте отдельный ключ на каждого MCP-клиента.
|
||||
- Удаляйте или отзывайте ключи, которые больше не используются.
|
||||
- Используйте secrets/auth profiles для токенов внешних API.
|
||||
- Не вставляйте реальные токены в статические заголовки операции.
|
||||
|
||||
## Эксплуатация
|
||||
|
||||
- Включите мониторинг контейнеров.
|
||||
- Следите за свободным местом на диске.
|
||||
- Проверяйте размер PostgreSQL и директории artifact storage.
|
||||
- Храните бэкапы PostgreSQL отдельно от application host.
|
||||
- Перед обновлением фиксируйте текущие image tags.
|
||||
- После обновления проверяйте UI, Admin API и MCP endpoint.
|
||||
|
||||
@@ -79,3 +79,4 @@ https://your-crank-host/mcp/v1/default/currency-rates
|
||||
|
||||
Клиент должен передавать API-ключ агента в заголовке авторизации.
|
||||
|
||||
Подробные HTTP-примеры для `initialize`, `tools/list` и `tools/call` находятся в [MCP-интерфейсе](./mcp-interface.md) и [практических API-примерах](./api-examples.md).
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
- проверять доменную модель отдельно от транспорта;
|
||||
- ловить регрессии в mapping;
|
||||
- не дать адаптерам начать вести себя по-разному;
|
||||
- обеспечить воспроизводимость для дипломной демонстрации.
|
||||
- обеспечить воспроизводимость для демонстрации и регрессионных проверок.
|
||||
|
||||
## 2. Уровни тестов
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
- unit tests для form helpers и schema rendering;
|
||||
- integration tests для critical user flows;
|
||||
- отдельная проверка mapping editor и sample upload flows.
|
||||
- отдельный regression checklist для post-integration smoke pass: [manual-regression-checklist.md](/home/a.tolmachev/code/rust/mcpaas/docs/manual-regression-checklist.md).
|
||||
- отдельный regression checklist для post-integration smoke pass: [manual-regression-checklist.md](manual-regression-checklist.md).
|
||||
|
||||
## 6. Что нельзя оставлять без тестов
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
# Troubleshooting
|
||||
|
||||
Этот документ помогает быстро проверить типовые проблемы при запуске и работе Crank.
|
||||
|
||||
## Веб-интерфейс открывается, но данные не загружаются
|
||||
|
||||
Проверьте `admin-api`:
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:3001/health
|
||||
docker compose logs -f admin-api
|
||||
```
|
||||
|
||||
Типовые причины:
|
||||
|
||||
- `admin-api` не подключился к PostgreSQL;
|
||||
- неверные `POSTGRES_HOST`, `POSTGRES_PORT`, `POSTGRES_USER`, `POSTGRES_PASSWORD`;
|
||||
- reverse proxy не проксирует `/api/admin/`;
|
||||
- браузерная сессия истекла.
|
||||
|
||||
## `502 Bad Gateway` через nginx
|
||||
|
||||
Проверьте, на каком адресе опубликованы контейнеры:
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
Если nginx работает на другом host, в `.env` нужно:
|
||||
|
||||
```env
|
||||
CRANK_PUBLISH_BIND=0.0.0.0
|
||||
```
|
||||
|
||||
Если nginx работает на том же host, обычно достаточно:
|
||||
|
||||
```env
|
||||
CRANK_PUBLISH_BIND=127.0.0.1
|
||||
```
|
||||
|
||||
## MCP-клиент получает `401 Unauthorized`
|
||||
|
||||
Проверьте:
|
||||
|
||||
- API-ключ создан именно для нужного агента;
|
||||
- ключ передается как `Authorization: Bearer <key>`;
|
||||
- ключ не был удален или отозван;
|
||||
- MCP URL содержит правильные `workspace_slug` и `agent_slug`.
|
||||
|
||||
## MCP-клиент не видит инструмент
|
||||
|
||||
Проверьте:
|
||||
|
||||
- операция опубликована;
|
||||
- операция привязана к агенту;
|
||||
- агент опубликован;
|
||||
- ключ выдан на этого агента;
|
||||
- прошел интервал `CRANK_MCP_REFRESH_MS`.
|
||||
|
||||
Для demo seed ожидаемый инструмент:
|
||||
|
||||
```text
|
||||
frankfurter_latest_rate
|
||||
```
|
||||
|
||||
## Тест операции возвращает ошибку внешнего API
|
||||
|
||||
Откройте preview запроса в wizard-е и проверьте:
|
||||
|
||||
- `base_url`;
|
||||
- `path_template`;
|
||||
- HTTP method;
|
||||
- query/path/body mapping;
|
||||
- auth profile;
|
||||
- статические заголовки.
|
||||
|
||||
Для Frankfurter рабочий запрос:
|
||||
|
||||
```text
|
||||
GET https://api.frankfurter.dev/v1/latest?base=USD&symbols=EUR
|
||||
```
|
||||
|
||||
## Секрет не виден после создания
|
||||
|
||||
Это ожидаемое поведение. Crank шифрует секрет и больше не возвращает его значение через UI или API.
|
||||
|
||||
Если значение нужно заменить, используйте **Ротировать**.
|
||||
|
||||
## После обновления не появился demo-пример
|
||||
|
||||
Проверьте:
|
||||
|
||||
```env
|
||||
CRANK_DEMO_SEED=true
|
||||
```
|
||||
|
||||
Затем перезапустите `admin-api`:
|
||||
|
||||
```bash
|
||||
docker compose up -d admin-api
|
||||
```
|
||||
|
||||
Seed идемпотентный: он не создает дубликаты, но поддерживает Frankfurter-пример.
|
||||
|
||||
## Контейнеры не стартуют из-за занятых портов
|
||||
|
||||
Проверьте, кто занимает порт:
|
||||
|
||||
```bash
|
||||
docker ps --format 'table {{.Names}}\t{{.Ports}}'
|
||||
sudo ss -ltnp
|
||||
```
|
||||
|
||||
Чаще всего конфликтуют:
|
||||
|
||||
- `3000` - UI;
|
||||
- `3001` - Admin API;
|
||||
- `3002` - MCP server;
|
||||
- `5432` - PostgreSQL, если включен profile `local-db`.
|
||||
|
||||
## PostgreSQL недоступен
|
||||
|
||||
Проверьте доступность из контейнера:
|
||||
|
||||
```bash
|
||||
docker compose exec admin-api sh -lc 'nc -vz "$POSTGRES_HOST" "$POSTGRES_PORT"'
|
||||
```
|
||||
|
||||
Проверьте переменные:
|
||||
|
||||
```bash
|
||||
docker compose exec admin-api env | grep POSTGRES
|
||||
```
|
||||
|
||||
## Где смотреть логи
|
||||
|
||||
```bash
|
||||
docker compose logs -f admin-api
|
||||
docker compose logs -f mcp-server
|
||||
docker compose logs -f ui
|
||||
```
|
||||
|
||||
Для подробных логов временно укажите:
|
||||
|
||||
```env
|
||||
CRANK_LOG_LEVEL=debug
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user