/ документация / разработчикам / подключение

Подключение

Реестр — это обычный MCP-сервер по HTTP. Отдельный клиент ставить не нужно, авторизации сейчас нет. Ниже — что он отдаёт, в каком виде и как ведёт себя, когда магазин недоступен.

Подключение

Транспорт — Streamable HTTP, режим без состояния: сессия не привязана к процессу, заголовок Mcp-Session-Id не используется. Достаточно указать адрес в конфигурации клиента.

{
  "mcpServers": {
    "e-suppy": { "url": "https://mcp.e-suppy.com/mcp" }
  }
}

Проверить доступность можно рукопожатием, ничего не устанавливая — ответ придёт либо чистым JSON, либо кадром SSE, в зависимости от заголовка Accept.

curl -sX POST https://mcp.e-suppy.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Инструменты

Наружу отдаются мета-инструменты, а не проброс ручек магазинов: у каждой площадки свои имена и форматы, и несколько источников по два десятка инструментов переполнят контекст модели. Аргумент server во всех вызовах необязателен — без него берётся магазин по умолчанию из list_servers.

list_serversчтениеКакие магазины подключены и что каждый умеет. Вызывать первым
search_productsчтениеПоиск: query, необязательные server и limit (1–20)
product_detailsчтениеБренд, цена и фасовка по product_id
find_by_barcodeчтениеПоиск по EAN-13, ровно 13 цифр
list_discountsчтениеАкции: kind — card или quantity, limit до 20
create_cartзаписьСсылка на корзину: до 20 позиций, количество 0.01–40

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

Успешный ответ всегда содержит ok: true. Цена — число в рублях, а не строка. У каждого товара есть as_of: цена — это состояние на момент наблюдения, и агент должен видеть её возраст. Текстовые поля магазина обрезаются до 300 символов: их пишет третья сторона, и в контекст модели они попадают как данные, а не как инструкция.

{
  "ok": true,
  "server": "vkusvill",
  "query": "сметана 15%",
  "count": 2,
  "products": [
    {
      "product_id": "14526",
      "title": "Сметана 15%, 250 г",
      "price": 98.0,
      "currency": "RUB",
      "quantity": { "value": 0.25, "unit": "кг" },
      "url": "https://vkusvill.ru/goods/smetana-15-14526/",
      "as_of": "2026-08-31T09:15:41+00:00"
    }
  ]
}

Ошибки

Ошибка возвращается данными внутри обычного ответа, а не кодом HTTP и не исключением протокола. Так агент отличает «магазин недоступен» от «товара нет» и не подставляет вместо цены выдумку. Признак retryable появляется только там, где повтор осмыслен.

{
  "ok": false,
  "error": "источник недоступен: vkusvill: таймаут",
  "server": "vkusvill",
  "retryable": true
}
источник недоступенretryableМагазин не ответил или разомкнут размыкатель. Повтор осмыслен
товар не найден—Запрос корректен, совпадений нет. Повтор не поможет
нет такого сервера—Неизвестный id в аргументе server; список даёт list_servers
сервер не умеет …—У магазина нет такой возможности; проверяйте capabilities
штрихкод должен быть 13 цифрами—Аргумент не прошёл проверку — исправьте и повторите

Лимиты и поведение

Ограничения на число запросов сейчас нет. Значения ниже — то, как роутер ведёт себя при обращении к магазинам; они заданы в коде и меняются вместе с ним.

бюджет опроса6 сНе уложившийся магазин выпадает, ответ приходит частичным
таймаут к магазину20 сНа один запрос к внешнему MCP
повторы2С экспоненциальной задержкой, только на сетевых сбоях
размыкатель3 / 60 сПосле трёх ошибок магазин выпадает из опроса на минуту
кэш цен300 сОтвет магазина переиспользуется; возраст виден в as_of
одновременно к магазину2Вежливость к чужому серверу, а не наша квота

Границы

Роутер не принимает оплату и не подтверждает заказ за пользователя: create_cart возвращает ссылку, а оплата и подтверждение состава происходят в магазине. Показывайте состав корзины человеку до того, как отдавать ссылку.