MCP がステートレスになった — リモートサーバを運用する側から見て何が変わるか
MCP の新しい仕様 2026-07-28 が出ました。告知の一文が「MCP is now stateless, making it easier to deploy and scale remote servers」です(@ClaudeDevs、2026-07-29 取得)。 リモート MCP サーバを自分で運用する側から読むと、これは仕様の話というより配置の話でした。実際に最小のサーバを書いて確かめたので、その結果まで書きます。 何が変わったか ステートレス化は3層にまたがっている changelog(2026-07-29 取得)を読むと、「ステートレス」が指しているものは1か所ではありませんでした。 セッション管理 — Mcp-Session-Id ヘッダがプロトコルレベルで削除されました。さらに initialize / notifications/initialized のハンドシェイク自体が無くなり、各リクエストが _meta に自分でプロトコル版とクライアント capability を載せます(io.modelcontextprotocol/protocolVersion、io.modelcontextprotocol/clientCapabilities)。 トランスポート — GET のストリームエンドポイントが削除されました。サーバが公開するのは POST を受ける単一エンドポイントだけです。SSE は「そのリクエストにスコープされたストリーム」としてのみ残り、Last-Event-ID による再開機能も削除されています。切れたら新しい request ID で送り直す、という規定になりました。 双方向性 — roots/list や sampling/createMessage のようなサーバ起点のリクエストは Multi Round-Trip Requests(MRTR)に置き換わりました。サーバは resultType: "input_required" を返し、クライアントが元のリクエストをリトライする際に応答を添えます。常時開いた双方向ストリームが要らなくなる、という形です。 かわりに server/discover が追加され、こちらはサーバの実装が MUST です。 図にするとこうです。左が従来、右が 2026-07-28 です。 従来(〜2025-11-25) 2026-07-28 クライアント サーバ initialize / initialized Mcp-Session-Id を発行 以後の全リクエストに Session-Id GET の常時 SSE ストリーム サーバ起点の要求(sampling 等) 両端が「どのセッションか」を 覚えている必要がある クライアント サーバ POST(単一エンドポイント) _meta に版と capability を自己記述 resultType: complete resultType: input_required 元リクエストをリトライ+応答添付 (MRTR: サーバ起点の代替) 接続をまたいで覚えるものがない。 SSE はリクエスト内のみ ハンドシェイク・セッション・GET ストリームがある 各リクエストが自己完結する ステートレス化「だけ」ではない ここが読み違えていたところです。changelog の major change は9件あって、破壊的なものが並んでいます。 ...