Перейти к содержимому
Выберите тему

Транспорты MCP

Как сообщения MCP передаются в редакции 2026-07-28 - stdio и Streamable HTTP, обязательные заголовки, статусы ответов, отмена запроса и статус устаревшего HTTP+SSE

описана редакция 2026-07-28, сверено со спецификацией 4 октября 2026

Транспорт Статус Где описан
stdio действует stdio
Streamable HTTP в форме 2026-07-28 действует Streamable HTTP
Streamable HTTP в форме 2025-03-26 - 2025-11-25 (сессии, поток по GET) Legacy: описан в своих редакциях, в текущую не входит раздел Backward Compatibility той же страницы
HTTP+SSE из редакции 2024-11-05 устарел с 2025-03-26, не удалён реестр устаревшего
свой транспорт разрешён обзор транспортов

Транспорта на WebSocket в спецификации 2026-07-28 нет.

Свой транспорт обязан сохранить формат JSON-RPC, шаблоны обмена и поля _meta. Если он работает поверх надёжного потока байтов (сокет Unix, TCP), спецификация рекомендует взять правила stdio: одно сообщение на строку.

Клиент запускает сервер как дочерний процесс и общается с ним через стандартные потоки.

  • Сервер читает сообщения из stdin и пишет в stdout.
  • Одно сообщение - одна строка. Переводов строки внутри сообщения быть не должно.
  • В stdout сервер не должен писать ничего, кроме сообщений MCP.
  • В stderr сервер может писать что угодно: журнал, отладку, ошибки. Клиенту не следует считать вывод в stderr признаком сбоя.
  • Сервер не отправляет запросы. Клиент не отправляет ответы.
Две строки обмена по stdio
{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}
{"jsonrpc":"2.0","id":1,"result":{"resultType":"complete","tools":[],"ttlMs":0,"cacheScope":"private"}}

Отмена. Клиент отправляет уведомление notifications/cancelled с номером запроса. Серверу следует остановить работу как можно скорее. Присылать по этому запросу новые сообщения он не должен.

Завершение. Клиенту следует закрыть stdin сервера и подождать выхода процесса. Если процесс не вышел за разумное время, клиент завершает его принудительно: в POSIX это обычно SIGTERM, затем SIGKILL. Серверу следует выходить сразу, как только stdin закрыт.

Сбой процесса. Клиенту следует перезапустить сервер. Незавершённые запросы теряются, их можно повторить.

Сервер работает как отдельный сервис и даёт один адрес, например https://example.com/mcp. Этот адрес принимает POST.

  • Каждое сообщение клиента - отдельный POST.
  • Клиент обязан указать в Accept оба типа: application/json и text/event-stream.
  • На запрос сервер отвечает либо одним объектом JSON, либо потоком SSE, привязанным к этому запросу. Клиент обязан понимать оба варианта.
  • В потоке сервер может прислать уведомления по этому запросу, например о ходе выполнения, а затем итоговый ответ.
  • Сервер не отправляет по потоку собственные запросы.
СерверКлиентСерверКлиентalt[короткий ответ][ответ потоком]POST /mcp (запрос)200, application/json200, text/event-streamуведомления по этому запросуитоговый ответ, поток закрыт
Заголовок Откуда значение Когда нужен
MCP-Protocol-Version версия из _meta запроса в каждом POST
Mcp-Method поле method в каждом запросе
Mcp-Name params.name или params.uri для tools/call, resources/read, prompts/get
Mcp-Param-{имя} аргумент инструмента, помеченный в схеме свойством x-mcp-header когда сервер так пометил параметр

Заголовки повторяют тело запроса, чтобы балансировщики и шлюзы могли направлять запросы, не разбирая JSON. Источником истины остаётся тело.

Вызов инструмента по HTTP
POST /mcp HTTP/1.1
Content-Type: application/json
Accept: application/json, text/event-stream
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: get_weather
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": { "location": "Seattle, WA" },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}

Если значение нельзя записать обычными символами ASCII (например, в нём кириллица), клиент обязан закодировать его в Base64 и обернуть так: =?base64?ЗНАЧЕНИЕ?=. Правило действует для Mcp-Name и Mcp-Param-{имя}.

Ситуация Статус HTTP Ошибка JSON-RPC
заголовок не совпал с телом, отсутствует или содержит недопустимые символы 400 -32020 HeaderMismatch
сервер не поддерживает запрошенную версию 400 -32022 UnsupportedProtocolVersion
клиент не объявил нужную возможность 400 -32021 MissingRequiredClientCapability
сервер не знает такого метода 404 -32601
заголовок Origin есть и он недопустим 403 необязательно
принято уведомление 202 тела нет

Клиент отменяет запрос, закрывая поток ответа. Отдельное уведомление на HTTP не нужно.

Возобновить оборванный поток нельзя: заголовок Last-Event-ID не поддерживается. Клиент отправляет запрос заново с новым id.

Открывая поток SSE, серверу следует добавлять заголовок X-Accel-Buffering: no, чтобы обратный прокси не задерживал события. Для долгих потоков спецификация советует время от времени присылать строку-комментарий SSE, чтобы соединение не закрылось по простою.

Три требования из раздела Security & Endpoint.

  1. Сервер обязан проверять заголовок Origin во всех входящих соединениях. Это защита от подмены DNS (DNS rebinding).
  2. Локально запущенному серверу следует слушать только 127.0.0.1, а не все интерфейсы.
  3. Серверу следует проверять подлинность всех соединений. Как устроена авторизация, описано в разделе «Модель авторизации».

Авторизация из спецификации относится к HTTP. На stdio учётные данные берутся из окружения процесса.

Что отвечает новый сервер старому клиенту

Заголовок раздела «Что отвечает новый сервер старому клиенту»

Серверу, который поддерживает только 2026-07-28, спецификация рекомендует:

  • на GET и DELETE по своему адресу отвечать 405;
  • заголовок Mcp-Session-Id игнорировать и номера сессий не выдавать;
  • заголовок Last-Event-ID игнорировать.

Срок в реестре - это момент, с которого функцию можно удалить, а не дата удаления. Само удаление - отдельное решение ведущих разработчиков при подготовке очередной редакции. Новым реализациям HTTP+SSE использовать не следует, существующим следует перейти на Streamable HTTP.

Как клиенту работать и со старым, и с новым сервером, спецификация описывает так: отправить POST с новым набором заголовков; если пришёл ответ 400, 404 или 405 и в теле нет распознанной ошибки Modern, отправить GET и ждать событие endpoint - это признак сервера на HTTP+SSE.