Claude Media
MCPのセッションID(Mcp-Session-Id)はなぜ廃止されたのか

MCPのセッションID(Mcp-Session-Id)はなぜ廃止されたのか

MCPのMcp-Session-Idヘッダーは2026-07-28の仕様改訂で削除されました。狙いはステートレス化によるサーバーの水平スケール対応です。

MCPのセッションID(Mcp-Session-Id)はなぜ廃止されたのか

2026-07-28のMCP仕様改訂(SEP-2567)で、Streamable HTTPトランスポートのプロトコルレベルのセッションとMcp-Session-Idヘッダーが削除されました。狙いは一言で言うと、MCPをステートレスなプロトコルに作り直すことです。サーバーが接続ごとに状態を抱え続ける前提を外し、どのプロセスがリクエストを処理しても結果が変わらない設計へ寄せています。

Mcp-Session-Idとは、サーバーが接続に割り当てるセッション識別子を運ぶHTTPヘッダーです。2025-03-26から2025-11-25までのStreamable HTTP仕様で使われていました。2026-07-28のリビジョンでは、このヘッダーの仕組みごと丸ごと無くなりました。

Mcp-Session-Idは何をしていたヘッダーだったのか

旧来の仕組みでは、サーバーがMcp-Session-Idヘッダーでクライアントにセッションを割り当て、そのセッションはHTTP DELETEで明示的に終了させる形でした。クライアントはHTTP GETで独立したSSEストリームを開き、サーバー主導のメッセージを受け取ることができました。サーバーはそのストリーム上でJSON-RPCリクエストを送ることもでき、ストリームはLast-Event-IDヘッダーで再開可能でした。

このモデルには、tools/listresources/listprompts/listのようなリスト系エンドポイントの応答が接続(セッション)ごとに変わり得るという前提も組み込まれていました。2026-07-28ではこれらのメカニズムがすべて仕様から姿を消しています。リスト系エンドポイントの応答は、接続によって変わらないものとして扱われます。

ステートレス化はどんな問題を解決するのか

セッションが接続に紐づくということは、そのセッションに関わるやり取りは常に同じサーバープロセスへ届かなければならないということです。ロードバランサーの背後にサーバーを複数並べる構成では、セッションIDでリクエストを固定的に振り分けるセッションアフィニティか、インスタンス間で状態を共有するストレージ層のどちらかが必要になります。MCPのMRTRの記事で扱ったサーバー主導リクエストの置き換えも、根はこれと同じ問題です。往復のあいだ状態をサーバー側に持たせず、必要な文脈をクライアントに持ち帰らせることで、この制約そのものを外しています。

たとえばKubernetesのPodやサーバーレス関数のようにインスタンスが頻繁に入れ替わる環境では、セッションを特定インスタンスに固定する運用そのものが不安定要因になります。Podが再起動すればセッションは失われ、クライアントは接続をやり直す羽目になっていました。セッション廃止はこの流れの一部にすぎません。2026-07-28ではinitialize/notifications/initializedという、接続の最初に一度だけ行うハンドシェイクそのものも削除されました。プロトコルバージョンとクライアントのケーパビリティは、以後すべてのリクエストに毎回乗せる形に変わりました。乗せる先はリクエストの_meta(io.modelcontextprotocol/protocolVersionio.modelcontextprotocol/clientCapabilities)です。接続の最初だけ特別扱いする状態がプロトコルから一つずつ消えていったのが、この改訂の一貫した方向性です。

セッション相当の状態はどう引き継ぐのか — サーバー発行ハンドル方式

複数のツール呼び出しをまたいで状態を持ち回りたいサーバーは、プロトコルレベルのセッションに頼る代わりに、サーバーが発行するハンドルを普通のツール引数として受け渡す形に切り替えます。たとえば、あるツール呼び出しの結果にサーバーが発行したトークンや識別子を含め、次のツール呼び出しではクライアントがそれを引数として渡す、という設計です。

この方式のポイントは、状態がプロトコルの外側にあるアプリケーションレベルのデータとして扱われることです。ロードバランサーやトランスポート層はこのハンドルの中身を意識する必要がなく、どのサーバーインスタンスが処理してもハンドルさえ持っていれば処理を続行できます。セッションアフィニティという運用上の制約を、サーバー実装側の設計判断に置き換えたと言えます。

同じ発想は、同じ2026-07-28リビジョンでコア仕様から拡張機能へ切り出されたMCP Tasksにも表れています。長時間かかる処理の結果を接続を張ったまま待つブロッキング方式をやめ、持続的なタスクIDをハンドルとしてポーリングする設計に置き換えられました。

後方互換はどう動くか — 古いクライアントとMcp-Session-Idヘッダー

2026-07-28のリビジョンだけに対応するサーバーが、旧いクライアントから2025-03-26〜2025-11-25世代のトラフィックを受け取った場合の挙動も仕様に定められています。MCPエンドポイントへのHTTP GETまたはDELETEには405 Method Not Allowedを返します。リクエストにMcp-Session-Idヘッダーが付いていても無視し、セッションIDを新たに発行したりエコーバックしたりしません。Last-Event-IDヘッダーも無視し、ストリームの再開には応じません。

両方のプロトコル世代と相互運用する必要があるサーバーやクライアントは、旧いリビジョンで定義された挙動を別途実装する必要があります。単純に「ヘッダーを無視すれば動く」というものではなく、GET/DELETEへの応答コードまで含めて旧クライアントとの互換性を意識した実装が求められます。

クライアント側の互換判定も一段階増えました。モダンなクライアントは、まず_metaにプロトコルバージョンを乗せた新しいリクエストを送り、応答が400 Bad Requestで返ってきた場合はボディの中身を見て次の一手を決めます。既知のモダンなJSON-RPCエラーが含まれていれば、サーバーは新しいプロトコルを話していると判断し、そのまま再試行します。ボディが空か見慣れないエラーであれば、旧世代とみなしてinitializeハンドシェイクにフォールバックします。セッションの有無だけでなく、この世代判定のロジックごと古い実装からは作り替える必要があります。

セッションが無くてもロードバランサーはどう振る舞うのか

セッションIDでの振り分けが無くなった後、ロードバランサーやAPIゲートウェイのような中間者は何を手がかりにルーティングや観測をすればよいのでしょうか。2026-07-28の仕様は、JSON-RPCのボディに含まれる一部フィールドをHTTPヘッダーへ写し取るという形で答えを用意しています。

具体的には、すべてのPOSTリクエストにMCP-Protocol-Versionヘッダーでプロトコルバージョンを、Mcp-Methodヘッダーでメソッド名を必ず載せます。tools/callresources/readprompts/getのリクエストでは、対象を示すMcp-Nameヘッダーも必須です。これらはボディをパースしなくても中間者がリクエストの中身を把握できるようにするための仕組みです。ヘッダーの値とボディの値が食い違っていれば、サーバーは400 Bad Requestと専用のエラーコードで拒否します。セッションIDという単一の手がかりが無くなった代わりに、リクエストごとに素性を明示する方向へ寄せたと理解すると筋が通ります。

Claude CodeのMCP実装で何が変わるのか

Claude Codeはv2.1.232以降、既定でMCP TypeScript SDK 2.0を使うv2ランタイムに切り替わります。HTTPサーバーやclaude.aiコネクタサーバーには2026-07-28への対応を確認し、対応していればそのリビジョンで通信します。このリビジョンではプロトコルレベルのセッションが存在しません。そのためClaude Codeから接続されるサーバー側は、セッションアフィニティを前提にしたロードバランサー設定を組む必要が無くなります。

自前でセルフホスト環境にMCPサーバーを配布している場合の構成はClaude Codeセルフホスト環境にMCPサーバーを届ける3つの経路で扱っています。サーバー実装そのものの作り方はMCPサーバー自作ガイドを参照してください。Claude Code側からの接続設定はClaude Code MCP設定ガイドにまとめています。ツール呼び出しをまたぐ状態管理をハンドル方式に書き換える作業は、既存サーバーのコード量によっては小さくない変更になります。2026-07-28への対応を急ぐ前に、まず自分のサーバーがどこでセッション状態に依存しているかを洗い出しておくと、見通しが立てやすくなります。

セッション廃止の移行でつまずきやすい点

既存のセッション前提サーバーを2026-07-28へ寄せるとき、見落としがちな点が3つあります。

  • サーバー発行ハンドルを無検証で信用してしまう。ハンドルはプロトコルの外にあるただの引数なので、認可判定に使うなら署名や有効期限の検証をアプリケーション側で自前に実装する必要があります。トランスポート層が代わりに面倒を見てくれる保証はありません。
  • リスト系エンドポイントのキャッシュを接続単位のまま残してしまう。旧仕様ではtools/listなどがセッションごとに変わり得た前提でキャッシュを組んでいた実装は、接続に依存しない前提へ作り替えないと、古い一覧を返し続けるバグになります。
  • GET/DELETEへの応答を実装し忘れる。後方互換を保つ気が無くても、旧いクライアントがMCPエンドポイントへGETやDELETEを送ってくる可能性は残ります。405 Method Not Allowedを返す最低限の応答が無いと、クライアント側のフォールバック処理が期待どおりに動きません。

まとめ

Mcp-Session-Idヘッダーの廃止は、単発の仕様変更ではありません。MCPを接続単位の状態から切り離してステートレスに作り直す一連の改訂の一部です。影響を受けるのは、複数のツール呼び出しをまたいで状態を持ち回る自作MCPサーバーの開発者です。特にロードバランサー配下で複数インスタンスを運用している場合は、セッションアフィニティに頼った構成をサーバー発行ハンドル方式へ書き換えるタイミングです。Claude Codeのv2ランタイムと通信するHTTPサーバーであれば、この変更はすでに現実の接続に影響します。

この記事を共有:XはてブLinkedIn
MCP をもっと見る →