MCP 2026-07-28:セッションを消し、プロトコルを再びステートレスに
MCP の新リビジョンは initialize ハンドシェイクと Mcp-Session-Id ヘッダを削除し、呼び出しをまたぐ状態を明示的なサーバ発行ハンドルに変えた。何が変わり、なぜか、既存のサーバ実装にとって何を意味するか。
MCP の新しいリビジョン(2026-07-28)は引き算です。前の版は 2025-11-25 で、最大の違いは一文で言えます。
プロトコル層にセッションがなくなった。
削除されたもの:
- Streamable HTTP トランスポートのプロトコルレベルセッションと
Mcp-Session-Idヘッダ initialize/notifications/initializedハンドシェイクping、logging/setLevel、notifications/roots/list_changed- 従来の HTTP GET エンドポイント、および
resources/subscribe/resources/unsubscribe
なぜ削除したか
セッションは状態であり、HTTP 上のステートフルなプロトコルには古くからの問題があります。リクエストが別のマシンに届いた瞬間、文脈は失われます。スティッキーセッションか共有ストレージか。どちらも高くつき、どちらも「水平スケール」をスローガンに変えてしまいます。
以前の方式は接続ごとに Mcp-Session-Id を発行し、以後の全リクエストに載せていました。開発機では何の問題もなく、本番では惨めです。
新リビジョンは状態をデータに降格します:
- 各リクエストがプロトコルバージョンとクライアント能力を
_metaに載せる(io.modelcontextprotocol/protocolVersion、io.modelcontextprotocol/clientCapabilities) - クライアントは各リクエストで自己を識別すべき(
io.modelcontextprotocol/clientInfo)、サーバは各結果の_metaで自己を識別すべき(io.modelcontextprotocol/serverInfo) - 呼び出しをまたぐ状態が必要なら、サーバが発行する明示的なハンドルを通常のツール引数として渡す(SEP-2567)
最後の点がこの変更の核心です。状態は消されたのではなく、「プロトコルが黙って覚えているもの」から「目に見え、保存でき、失効させられ、取り消せる文字列」へ移りました。
バージョン交渉も移動した
従来はハンドシェイク時に一度だけ交渉していました。交渉するハンドシェイクがもう無いので:
- バージョン不一致は
UnsupportedProtocolVersionErrorを返す(SEP-2575) - 新しい
server/discoverRPC が追加され、サーバはこれを実装しなければならない。対応するプロトコルバージョン、能力、身元を告知する - クライアントは他のどのリクエストよりも前に呼んで事前のバージョン選択に使えるし、STDIO では後方互換の探査にも使える
購読は一つのストリームになった
以前、サーバからクライアントへの変更通知は HTTP GET エンドポイント(長命接続)と resources/subscribe を経由していました。今は subscriptions/listen に一本化され、長命な POST-response ストリーム一つになります。クライアントは関心のある種別(toolsListChanged、promptsListChanged、resourcesListChanged、resourceSubscriptions)を明示的に購読し、サーバは確認して各通知に io.modelcontextprotocol/subscriptionId を付けます。
見落としやすい点が一つ。notifications/progress や notifications/message のようなリクエストスコープの通知は、今もそれが属するリクエストのレスポンスストリームを流れ、subscriptions/listen には乗りません。両者を混ぜると「この進捗は誰のものか」が答えられなくなります。
ログも同じ理屈です。レベルはリクエストごと(_meta の io.modelcontextprotocol/logLevel)になり、このフィールドを含まないリクエストに対してサーバは notifications/message を出してはならない。この一つの制約が「静かなクライアントがログに溺れる」問題を仕様レベルで潰しています。
もう一つ:tasks はコアを出た
実験的な tasks は公式拡張 io.modelcontextprotocol/tasks に移りました。健全なことです。コアプロトコルが実験的機能をいつまでも抱えるべきではなく、拡張は独自に進化し独自に廃止できます。
すでにサーバを書いた人にとって
2025-11-25 に合わせて実装したなら:
- セッションストアを削除する。 最大の利益であり、今回の改版の主な動機です。
server/discoverを実装する。 MUST です。無いと新しいクライアントがバージョン選択をできません。- 呼び出しをまたぐ状態をハンドルに変える。 セッションに置いていたもの(ユーザー身元、一時的な文脈、ページングカーソル)はすべて明示的なツール引数になります。
- ログを見直す。
logging/setLevelはかつて全体スイッチでした。今はリクエスト単位で、付けなければ「黙れ」を意味します。
私の結論
この改版は便利に見える設計を冗長に見える設計と交換し、その見返りは具体的です。どのマシンでもどのリクエストを処理できる。スティッキーセッションも共有セッションストアも要りません。
代価はリクエストごとに数十バイトの _meta です。HTTP においてこの取引はほぼ常に割に合います。ステートレス性こそ HTTP が今も生きている理由であり、MCP はその肩に乗りながら横にもう一つ車輪を付けていたのでした。

コメント
…