Глава 15

Для удаленного MCP проектируйте Streamable HTTP

Когда MCP уходит за пределы одной машины, на смену stdio приходит Streamable HTTP. У него один MCP-endpoint: каждый запрос отправляется отдельным POST, а ответ может быть либо JSON, либо request-scoped SSE-поток. Важно сразу зафиксировать, чем это не является: это HTTP-транспорт для JSON-RPC, а не произвольный REST API, где tool-имена превратились в URL-пути.

Вот как выглядит удалённый tools/call на уровне провода - с заголовками редакции и роутинга.

POST /mcp HTTP/1.1
Host: tools.example.com
Content-Type: application/json
Accept: application/json, text/event-stream
Authorization: Bearer …
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: review_release

{
  "jsonrpc": "2.0",
  "id": "call-42",
  "method": "tools/call",
  "params": { … modern _meta … }
}

А вот логика роутинга на стороне сервера - это схема поведения, а не готовый файл.

SQL
POST /mcp
  validate Origin + authentication
  validate version/method/name headers against body
  parse one JSON-RPC request
  authorize capability + arguments
  return application/json
  or request-scoped text/event-stream

POST /mcp method=subscriptions/listen
  long-lived SSE stream for opted-in change notifications

GET /mcp and DELETE /mcp
  405 Method Not Allowed in 2026-07-28

Ключевой сдвиг здесь в том, что современный транспорт не связывает списки, вызовы и результаты с TCP-соединением. Значит кэш и состояние приложения должны быть явными. Для быстрого результата подходит обычный JSON-ответ - его проще проксировать, наблюдать и повторять. Request-scoped SSE нужен там, где во время конкретного запроса идут progress и связанные notifications. Для долгой работы используйте task-extension или доменный job id, а не надежду, что следующий запрос придёт на тот же pod.

Broken stream не возобновляется автоматически. Редакция 2026-07-28 убрала SSE-redelivery через Last-Event-ID. Потерянный in-flight запрос повторяется новым request id только если операция допускает безопасный retry. Проектируйте idempotency заранее, а не после первого потерянного соединения.

Транспорт выбран - но production-клиент обязан управлять не только счастливым путём. Добавим ему прогресс, отмену, notifications и кэш.

Ссылки