# Интеграция MCP (Model Context Protocol)

JSON-RPC 2.0-эндпоинт для подключения внешних ИИ-агентов к сервису через
Model Context Protocol. Подходит для сторонних MCP-клиентов, плагинов
редакторов кода, CLI и любых инструментов, поддерживающих `tools/call`.

## Общие сведения

- **Base URL:** `{{BASE_URL}}` (например `https://ai.wormsoft.ru`)
- **Аутентификация:** заголовок `Authorization: Bearer <API_KEY>` или JWT
  аутентифицированного агента
- **Контент:** `Content-Type: application/json`
- **Тарификация:** по кредитам. `web_search` списывает пропорционально
  количеству результатов, `web_fetch` — фиксированные 2000 кредитов за запрос.
  Списание происходит только при успешном ответе инструмента.
- **Доступность:** только на платных подписках (FREE не поддерживается).

## Эндпоинт

- `POST /api/mcp` — JSON-RPC 2.0 диспетчер (единственный поддерживаемый метод)
- `GET /api/mcp` и `DELETE /api/mcp` — вернут `405 Method Not Allowed`

## Привязка агента к аккаунту

Каждый MCP-запрос привязан к пользователю через `Authorization`. В зависимости
от клиента это может быть:

- **API-ключ** — `Authorization: Bearer YOUR_API_KEY`
- **JWT агента** — `Authorization: Bearer <agent-jwt>`, если агент
  аутентифицирован в системе

Токен определяет, под каким аккаунтом выполняются инструменты, и списываются
с баланса. Не передавайте один и тот же ключ нескольким доверенным агентам.

## Доступные инструменты

Список инструментов можно получить запросом `tools/list`. Ниже описаны три
доступных инструмента.

### `web_search`

Поиск в интернете по запросу.

```json
{
  "query": "string (обязательно)",
  "max_results": "число 1-10 (необязательно)"
}
```

### `web_fetch`

Загрузка содержимого веб-страницы по URL.

```json
{
  "url": "string (обязательно)"
}
```

### `recognize_image_content`

Распознавание текста на изображении и в PDF-документах (OCR). Модель
возвращает данные строго по переданной JSON-Schema (tool-calling).

```json
{
  "sources": [
    { "image": "data:image/png;base64,..." },
    { "pdfFile": "<base64 PDF>" }
  ],
  "prompt": "string (необязательно)",
  "responseSchema": { "type": "object", ... },
  "model": "wormsoft/vision/medium"
}
```

- `sources` — массив источников; в каждом элементе ровно один из
  `image` / `pdfFile` (base64). До 20 источников за запрос, размер одного
  источника до 25 МБ.
- `prompt` — уточняющая инструкция (добавляется в запрос к модели).
- `responseSchema` — JSON Schema ответа (передается в tool-calling).
- `model` — vision-модель провайдера с поддержкой tool-calling.

## Пример подключения

Отправьте JSON-RPC-запрос методом `tools/call`:

```bash
curl -X POST https://ai.wormsoft.ru/api/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "web_search",
      "arguments": { "query": "NestJS", "max_results": 5 }
    }
  }'
```

## Формат ответа

Успешный вызов инструмента возвращает результат в
`result.content`. Текст инструментов оформлен как JSON для удобства парсинга.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      { "type": "text", "text": "{\n  \"model\": \"wormsoft/vision/medium\",
   \"documents\": [...],
   \"usage\": { \"credits\": 100 }\n}" }
    ]
  }
}
```

## Протокол JSON-RPC 2.0

- **Одноточечный запрос** → один объект ответа
- **Пакет запросов** (массив) → массив объектов ответов
- **Уведомление** (без `id`) → `202` с пустым телом
- Поддерживаемые методы: `initialize`, `ping`, `tools/list`, `tools/call`

## Ошибки

| Code     | Описание                                             |
|----------|------------------------------------------------------|
| `-32600` | Invalid Request — повреждённый JSON-RPC-запрос       |
| `-32601` | Method not found — неизвестный метод                 |
| `-32602` | Invalid params — неверные параметры инструмента      |
| `-32000` | Server error — unsupported метод (GET/DELETE → 405)  |
| `-32603` | Internal error — ошибка на стороне сервера           |

Ошибки выполнения инструмента (например, неверный `query` или недоступный
`url`) возвращаются в `result.isError: true` с текстом сообщения.
