Интеграция MCP и внешних AI-инструментов

PolyApiIDE не запускает отдельный MCP-сервер. Вместо этого внешний AI-инструмент отправляет патч коллекции через простой REST API, а пользователь видит его во «Входящих патчах» внутри IDE и сам решает — применить или отклонить. Ниже — как получить доступ и что именно отправлять. Доступно на любом платном тарифе (Месяц, Год, Lifetime).

Как это устроено

Отдельного MCP-сервера в продукте нет. «Патчи от ассистента» — это очередь JSON-документов на стороне polyapiclient.ru: внешний инструмент кладёт туда патч коллекции, расширение периодически проверяет очередь и показывает пользователю карточку с диффом. Применяет или отклоняет патч только сам пользователь в IDE — внешний инструмент не может изменить коллекцию напрямую.

1. Получить client_id / client_secret

Это технический API-клиент того же типа, что использует сам IDE для AI-чатов и бэкапов — отдельной формы регистрации на сайте для сторонних инструментов нет (это защита от абьюза email-подтверждения).

Откройте PolyApiIDE → Настройки → Интеграции и нажмите «Показать данные для интеграции». Скопируйте client_id и client_secret — секрет показывается по клику, храните его как пароль. Раздел доступен, только если на аккаунте активен платный тариф.

Если секрет скомпрометирован — повторно пройдите привязку по email в расширении: сервер перевыпустит секрет для того же client_id.

2. Авторизация запросов

Официальный способ для сторонних инструментов — простые заголовки:

X-Client-Id: <client_id>
X-Client-Secret: <client_secret>

Заголовки передаются только по HTTPS. Не кладите client_id/client_secret в тело запроса или в query — сервер отклонит такой запрос (401 client_auth_plaintext_forbidden).

Само расширение PolyApiIDE использует более закрытый sealed-протокол (RSA-OAEP + AES, заголовок X-Client-Auth) — он не требуется внешним интеграторам и не документируется отдельно как публичный API.

3. Эндпоинты

  • POST https://polyapiclient.ru/api/v1/collections/patches — создать патч. Тело: {"payload": {...}, "source": "my-tool"}. Ответ 201 с объектом патча (id, status=pending).
  • GET https://polyapiclient.ru/api/v1/collections/patches?status=pending — проверить статус ранее отправленных патчей (pending/applied/rejected). Не обязателен для базовой интеграции.

Подтверждает применение (ack) только сам IDE после того, как пользователь нажал «Применить»/«Отклонить» — внешнему инструменту вызывать этот эндпоинт не нужно.

4. Схема патча — polyapiide.collection-patch

Тело поля payload:

{
  "type": "polyapiide.collection-patch",
  "version": 1,
  "base": { "collectionId": "col_example", "collectionName": "My collection" },
  "ops": [
    { "op": "setCollectionMeta", "fields": { "name": "...", "description": "..." } },
    { "op": "upsertRequest", "request": { "id": "req_1", "name": "Ping", "method": "GET",
        "folderPath": [], "url": { "raw": "https://api.example.com/ping", "query": [] },
        "headers": [ { "key": "Accept", "value": "application/json", "disabled": false } ] } },
    { "op": "removeRequest", "requestId": "req_old" },
    { "op": "patchRequest", "requestId": "req_1", "fields": { "name": "Ping (renamed)" } }
  ]
}

Допустимые значения op: upsertRequest, removeRequest, patchRequest, setCollectionMeta. Патч без непустого ops[] или с неизвестным op отклоняется с 422. Полный рабочий пример — example-polyapiide-patch.json.

5. Лимиты

  • Размер патча — до 2 МиБ (сериализованный JSON).
  • Число операций в патче — до 2000.
  • Патч живёт в очереди 7 дней, затем истекает.
  • До 20 необработанных патчей в очереди на клиента одновременно.

При превышении сервер отвечает 422 с reason: payload_too_large, too_many_ops или pending_limit.

6. Требования к тарифу

Функция доступна на любом платном тарифе — Месяц, Год или Lifetime (не только Lifetime). Если у client_id нет активной платной/демо-лицензии, любой запрос к /collections/patches вернёт 403 feature_required.

7. Секреты в патче

Сервер эвристически сканирует payload на признаки секретов (токены, пароли, ключи) и помечает патч флагом contains_possible_secret — это только предупреждение для пользователя в IDE перед применением, запрос не блокируется.

Пример: curl

curl -X POST https://polyapiclient.ru/api/v1/collections/patches \
  -H "X-Client-Id: $CLIENT_ID" \
  -H "X-Client-Secret: $CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d @example-polyapiide-patch.json

(поле верхнего уровня — сам патч; сервер также принимает обёртку {"payload": {...}}).

Пример: Python

import os, json, urllib.request

def send_patch(payload: dict, source: str = "my-ai-tool") -> dict:
    body = json.dumps({"payload": payload, "source": source}).encode()
    req = urllib.request.Request(
        "https://polyapiclient.ru/api/v1/collections/patches",
        data=body,
        method="POST",
        headers={
            "X-Client-Id": os.environ["POLYAPIIDE_CLIENT_ID"],
            "X-Client-Secret": os.environ["POLYAPIIDE_CLIENT_SECRET"],
            "Content-Type": "application/json",
        },
    )
    with urllib.request.urlopen(req) as res:
        return json.load(res)

patch = {
    "type": "polyapiide.collection-patch",
    "version": 1,
    "base": {"collectionId": "col_example", "collectionName": "My collection"},
    "ops": [
        {"op": "upsertRequest", "request": {
            "id": "req_ping", "name": "Ping", "method": "GET",
            "folderPath": [], "url": {"raw": "https://api.example.com/ping", "query": []},
            "headers": [{"key": "Accept", "value": "application/json", "disabled": False}],
        }},
    ],
}
print(send_patch(patch))

Готовый файл — example-mcp-client.py.

Пример: JavaScript (Node.js 18+ / браузер)

Используется встроенный fetch — без внешних зависимостей. Для Node < 18 подключите любой fetch-polyfill (например, node-fetch).

async function sendPatch(payload, source = "my-ai-tool") {
  const res = await fetch("https://polyapiclient.ru/api/v1/collections/patches", {
    method: "POST",
    headers: {
      "X-Client-Id": process.env.POLYAPIIDE_CLIENT_ID,
      "X-Client-Secret": process.env.POLYAPIIDE_CLIENT_SECRET,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ payload, source }),
  });
  return res.json();
}

const patch = {
  type: "polyapiide.collection-patch",
  version: 1,
  base: { collectionId: "col_example", collectionName: "My collection" },
  ops: [
    {
      op: "upsertRequest",
      request: {
        id: "req_ping",
        name: "Ping",
        method: "GET",
        folderPath: [],
        url: { raw: "https://api.example.com/ping", query: [] },
        headers: [{ key: "Accept", value: "application/json", disabled: false }],
      },
    },
  ],
};

sendPatch(patch).then((result) => console.log(result));

Проверить статус ранее отправленных патчей:

async function listPendingPatches() {
  const res = await fetch("https://polyapiclient.ru/api/v1/collections/patches?status=pending", {
    headers: {
      "X-Client-Id": process.env.POLYAPIIDE_CLIENT_ID,
      "X-Client-Secret": process.env.POLYAPIIDE_CLIENT_SECRET,
    },
  });
  return res.json();
}

Готовый файл — example-mcp-client.js.

8. Промпт для AI-агента

Если вы пользуетесь AI-ассистентом с исполнением кода или вызовом инструментов (например, Claude с code execution, кастомный агент, LLM с function calling) — вставьте этот промпт один раз в начале диалога, затем опишите словами, что нужно добавить или изменить в коллекции. Агент сам соберёт JSON патча и отправит его, используя примеры curl/Python/JS выше.

Ты — ассистент, который поддерживает мою коллекцию запросов в PolyApiIDE
в актуальном состоянии через API патчей коллекций.

Формат патча — JSON:
{
  "type": "polyapiide.collection-patch",
  "version": 1,
  "base": { "collectionId": "<моя коллекция>", "collectionName": "<название>" },
  "ops": [ ... ]
}

Разрешённые операции в ops[] (другие типы использовать нельзя):
- upsertRequest — добавить/обновить запрос:
  { "op": "upsertRequest", "request": { "id", "name", "method", "folderPath": [],
    "url": { "raw", "query": [] }, "headers": [ { "key", "value", "disabled" } ] } }
- removeRequest — удалить запрос: { "op": "removeRequest", "requestId": "..." }
- patchRequest — точечно изменить запрос: { "op": "patchRequest", "requestId": "...", "fields": { ... } }
- setCollectionMeta — изменить название/описание коллекции:
  { "op": "setCollectionMeta", "fields": { "name", "description" } }

Правила:
1. Используй только эти 4 типа операций, не добавляй в схему ничего своего.
2. Один патч — не больше 2000 операций и 2 МиБ в виде JSON.
3. Перед отправкой покажи мне итоговый JSON патча и дождись подтверждения.
4. Отправляй патч POST-запросом на
   https://polyapiclient.ru/api/v1/collections/patches
   с телом {"payload": <патч>, "source": "<имя твоего инструмента>"}
   и заголовками X-Client-Id / X-Client-Secret — я передам их значения отдельно,
   не подставляй их сам и не выводи в чат.
5. Ничего не применяется в IDE автоматически: я сам подтвержу или отклоню
   патч во «Входящих патчах» внутри расширения.

Дальше я опишу, что изменилось в API и что нужно добавить/поправить в коллекции.

Секрет лучше не вставлять в текст диалога, если это не защищённая среда исполнения кода: если у агента есть доступ к переменным окружения (как в примерах curl/Python/JS выше), поставьте POLYAPIIDE_CLIENT_ID/POLYAPIIDE_CLIENT_SECRET туда и попросите агента брать их оттуда.