# MCP-интерфейс

Crank публикует REST-операции как MCP-инструменты через Streamable HTTP.

## Endpoint агента

Каждый агент имеет собственный MCP endpoint:

```text
/mcp/v1/{workspace_slug}/{agent_slug}
```

Для demo seed:

```text
/mcp/v1/default/currency-rates
```

Полный URL зависит от вашего домена:

```text
https://crank.example.com/mcp/v1/default/currency-rates
```

## Авторизация

MCP-клиент должен передавать API-ключ агента:

```http
Authorization: Bearer <agent_api_key>
```

Ключ выдается в разделе **API ключи**. Полное значение показывается только один раз при создании.

## Поддерживаемые методы

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`:

```http
Authorization: Bearer <agent_api_key>
Content-Type: application/json
Accept: application/json, text/event-stream
```

Для `GET`:

```http
Authorization: Bearer <agent_api_key>
Accept: text/event-stream
MCP-Session-Id: <session_id>
```

После `initialize` сервер возвращает заголовок:

```http
MCP-Session-Id: <session_id>
```

Если клиент передает `MCP-Protocol-Version`, он должен совпадать с версией, согласованной при инициализации.

## Пример `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` из ответа.

## Пример `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`.
