Учебник
Что такое 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:
- Отправить
initialize— обмен версией протокола и client/server capabilities. - Получить
initializednotification; сервер отдаёт заголовокMcp-Session-Id. - Дальше
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— должен совпадать с_metaprotocolVersion, иначе 400.Mcp-Method— соответствует JSON-RPCmethod, напр.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.
Рекомендуемый паттерн:
- Первый вызов инструмента создаёт ресурс, возвращает
{ "draftId": "dr_8k2", ... }. - В описании инструмента: дальнейшие шаги должны передавать
draftId. - Сервер ищет
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.