Учебник

Что такое Stateless MCP? Stateless-архитектура 2026, JSON-RPC и Remote Server

Spec MCP 2026-07-28 делает протокольный слой stateless: каждый JSON-RPC-запрос несёт версию и capabilities; Remote Server работает за обычным HTTP-балансировщиком. Аргументы инструментов — всё ещё JSON; в проде нужна локальная проверка.

Model Context Protocol (MCP) даёт AI-клиентам обнаруживать инструменты, ресурсы и промпты и подключать их к контексту модели. Главный архитектурный сдвиг 2026 — от двунаправленного stateful-протокола «сначала handshake, потом Session ID» к stateless JSON-RPC, где каждый запрос самоописывается и маршрутизируется отдельно. Если вы уже зовёте Remote MCP Server из Claude Desktop, Cursor или своего Agent, это бьёт по деплою, масштабированию и rate limit на шлюзе. После прочтения вы отделите stateless протокола от stateful приложения — и поймёте, что JSON аргументов всё равно нужно проверять локально.

Что решают MCP и statelessness

MCP отвечает на вопрос «как модель безопасно и обнаружимо вызывает внешние возможности». Клиентам (Claude, ChatGPT, IDE Agent) нужен стандарт для списка инструментов, чтения ресурсов и шаблонов промптов; серверам (GitHub, БД, внутренние API через MCP-адаптер) — стандарт для экспорта без кастомного плагина на каждый клиент.

Ранний MCP хранил сессии на транспорте: клиент сначала шлёт initialize, сервер возвращает capabilities, дальнейшие запросы несут Mcp-Session-Id, прибивая трафик к одному инстансу или shared Session Store. Для локального stdio норм; когда Remote Server нужно масштабировать, крутить на Cloud Run / Lambda или лимитировать по инструментам через API-шлюз, sticky session становится узким местом.

Spec 2026-07-28 (Release Candidate) делает протокольный слой stateless: метаданные для любого запроса — в самом запросе; любой инстанс за обычным round-robin балансировщиком может принять. Официально: анонс spec MCP 2026-07-28 и раздел Statelessness.

Что осталось от эры stateful

В старом потоке клиент Streamable HTTP обычно сначала делал handshake:

  1. Отправить initialize — обмен версией протокола и client/server capabilities.
  2. Получить initialized notification; сервер отдаёт заголовок Mcp-Session-Id.
  3. Дальше tools/call и resources/read должны нести один Session ID, иначе шлюз или память инстанса не найдут контекст.

Типичные цены в проде: sticky session на балансировщике; Redis для Session между репликами; после cold start Serverless старые Session мертвы; популярные серверы вроде GitHub MCP держали Redis. Google в Scaling AI Agent Infrastructure называет это «крупнейшим изменением spec с запуска MCP» — суть: убрать управление сессией на транспорте.

Измерение Эра stateful (2025 и раньше) Ядро stateless (2026-07-28)
Handshake initialize / initializedОбязательно Снято; опциональноserver/discover
Идентификатор сессии Mcp-Session-Id response header Удалено (SEP-2567)
Согласование capabilities Один раз при установке соединения В каждом запросе _meta несёт их
Горизонтальное масштабирование Sticky routing + shared Session Store Достаточно обычного round-robin

Ядро stateless 2026-07-28

Определение «stateless» жёсткое: сервер не должен опираться на прошлые запросы того же соединения для версии протокола, identity клиента или capabilities; каждый запрос должен нести это в _meta. Запросы разных задач, потоков или диалогов могут чередоваться на одном транспорте; соединение или stdio-процесс не граница сессии.

Клиент кладёт в каждый запрос в params._meta (или эквивалент):

  • io.modelcontextprotocol/protocolVersion — обязательно, напр. 2026-07-28.
  • io.modelcontextprotocol/clientCapabilities — обязательно; пустой объект = нет опциональных capabilities.
  • io.modelcontextprotocol/clientInfo — рекомендуется для логов и отладки (сервер не для security-решений).

Чтобы узнать capabilities сервера заранее, клиент может вызвать новый server/discover RPC, но это не обязательно — любой запрос может быть первым на любом инстансе. Сервер может добавить tools/list к ответам вроде ttlMs, чтобы клиент кэшировал список инструментов в TTL.

Бизнес-состояние через несколько вызовов (корзина, браузерная сессия, черновик тикета) не прячьте в transport Session. Как обычный HTTP API: инструмент возвращает явный handle (basket_id и draft_id), модель передаёт его в последующих tools/call argument JSON. Модель видит handle — проще отлаживать, чем black-box Session.

Как JSON-RPC работает в MCP

Сообщения MCP — всегда JSON-RPC 2.0: у запроса есть jsonrpc и id и method и params; ответ несёт result или error; у notification нет id. Та же форма «имя инструмента + объект аргументов», что в статье Apple Agent — MCP стандартизирует имя метода в tools/call, с name и arguments.

Типичный stateless tools/call выглядит так (HTTP-заголовки в следующем разделе):

POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: searchInvoices

{
  "jsonrpc": "2.0",
  "id": 42,
  "method": "tools/call",
  "params": {
    "name": "searchInvoices",
    "arguments": {
      "status": "unpaid",
      "limit": 10
    },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {},
      "io.modelcontextprotocol/clientInfo": {
        "name": "jsonvue-demo",
        "version": "1.0.0"
      }
    }
  }
}

При успехе result обычно содержит content массив вывода инструмента (часто type: text JSON-строка или структурированный блок). При ошибке JSON-RPC error несёт code и message; при Streamable HTTP, если HTTP-заголовки и method/name в body расходятся, spec требует ошибку -32020 класса header mismatch.

Читателям JSONVue стоит смотреть на arguments: внешние Agent шлют числа строками или теряют required keys. Stateless MCP не проверит бизнес-JSON — та же разделка: Structured Output для вывода модели, MCP для вызовов инструментов. На сайте Apple AI Agent и JSON объясняет: одна доменная функция может служить App Intent, Foundation Models Tool и MCP; отличается только адаптер.

Remote Server и Streamable HTTP

Remote MCP Server — MCP endpoint по HTTPS, не локальный stdio-подпроцесс. Streamable HTTP — главный транспорт Remote: один POST завершает RPC; длинные задачи могут отдавать открытый поток уведомлений, но state scoped к запросу, не connection-level Session.

С 2026-07-28 запросы Streamable HTTP должны нести три заголовка как body (SEP-2243), чтобы шлюз, WAF и rate limiter маршрутизировали без parse JSON:

  • MCP-Protocol-Version — должен совпадать с _meta protocolVersion, иначе 400.
  • Mcp-Method — соответствует JSON-RPC method, напр. tools/call.
  • Mcp-Name — имя инструмента, prompt или ресурса, напр. searchInvoices.

Деплой упрощается: один Docker-образ, несколько реплик, ALB/nginx round-robin; Cloud Run / Cloud Functions без отдельного Redis Session для MCP; квоты QPS по Mcp-Name дешевле deep inspection body. Прод-сервисы вроде GitHub MCP Server уже переходят на stateless spec.

Локальный stdio Server работает; spec ясна: на одном stdio-процессе могут чередоваться несвязанные запросы; Server не должен считать identity процесса session ID. Локальная разработка и cloud Remote делят одну реализацию инструментов — отличается только транспортный адаптер.

Приложение может оставаться stateful

«Stateless протокол» ≠ «stateless бизнес». Корзины, многошаговые согласования, недозаполненные формы могут и должны быть stateful — но state должен быть явным, а не привязан к Mcp-Session-Id.

Рекомендуемый паттерн:

  1. Первый вызов инструмента создаёт ресурс, возвращает { "draftId": "dr_8k2", ... }.
  2. В описании инструмента: дальнейшие шаги должны передавать draftId.
  3. Сервер ищет draftId в БД/кэше; при промахе — JSON-RPC business error, не загадочный Session 404.

Для длинных задач Tasks и расширения поддерживают MRTR (Multi-Request Task Routing): инструмент может сначала вернуть status: input_required; клиент прикрепляет ответ пользователя в _meta следующих запросов. Всё ещё request/response на stateless протоколе — ответ может занять несколько раундов.

Связь со Structured Output

MCP и Structured Output решают разные слои, но JSON-формы часто встречаются в одном Agent pipeline:

Слой Механизм Что ограничивается
Вывод модели Structured Output + JSON Schema Поля и типы финального ответа или извлечения
Вызов инструмента MCP tools/call + inputSchema инструмента Объект arguments, отправляемый на Server
Бизнес API REST / GraphQL JSON body Реальная нагрузка внутри Server или downstream HTTP

Best practice: вести одну таблицу полей, генерировать inputSchema MCP, REST OpenAPI и Structured Output Schema для модели. На сайте руководстве по JSON в Gemini API про сторону модели; учебник Gemini Structured Output с облачными примерами. После stateless MCP список инструментов может кэшироваться — при смене версии Schema bump имя инструмента или версию протокола, чтобы stale cache не слал неверную форму в arguments.

Как смотреть JSON в проде

При отладке Remote MCP Server сравните три JSON: tools/call arguments клиента, HTTP body вашего доменного сервиса, result.content, возвращаемый модели. При расхождении форм виноват почти всегда адаптер, не «модель недостаточно умна».

Пройдите в браузере: Форматирование JSON — parse; Проверка JSON — trailing commas и типы; JSON Schema — общие поля inputSchema и API body; JSON DiffСравните «arguments модели» и «реальный HTTP body». Три fixture: mcp-args.valid.json и http-body.valid.json и mcp-tool-error.json — тот же Schema в CI.

Частые вопросы FAQ

Нужен ли stateless MCP долгий WebSocket?

Remote в основном Streamable HTTP: один POST завершает RPC; длинные потоки уведомлений — response stream уровня запроса, не старый «handshake и Session». Локальный stdio — long-lived процесс, но каждый запрос независим на уровне протокола.

Старые клиенты с Mcp-Session-Id подключатся к новым Server?

Server 2026-07-28 не признают protocol-level Session ID. Клиентам нужны protocolVersion и clientCapabilities в _meta каждого запроса и обязательные HTTP-заголовки. При смешанных версиях — split на шлюзе по MCP-Protocol-Version.

Нужно ли вызывать tools/list каждый раз?

Нет. Server может вернуть ttlMs; клиент кэширует в TTL. При смене инструментов/Schema — укоротить TTL или сменить имя/версию.

MCP проверяет arguments за Server?

Инструмент может объявить inputSchema, но Server обязан валидировать на сервере. Внешние Agent часто ошибаются в типах; stateless это не уменьшает. Структурированный JSON-RPC error лучше для retry модели, чем тихий 500.

Итог и следующие шаги

Stateless MCP возвращает Remote Server 2026 к обычной HTTP-эксплуатации: JSON-RPC 2.0 несёт методы, _meta — контекст протокола, Mcp-Method / Mcp-Name заголовки читаемы шлюзом. initialize и Mcp-Session-Id уходят — любой инстанс, Serverless-friendly, проще rate limit по инструментам.

Бизнес-state — явные ID в arguments; JSON-контракты проверяйте локально. Дальше: сверить Remote endpoint со spec 2026-07-28 (полные _meta и HTTP-заголовки); закрепить MCP arguments и REST body одним Schema; проверить round-trip JSON в браузере через JSONVue.