リモートのMCPサーバを2台以上に並べた瞬間に踏む地雷がある。1台目が発行したセッションIDを、ロードバランサの気まぐれで振り分けられた2台目が知らない、という問題だ。これを避けるために、みんなスティッキーセッションを効かせたり、共有のセッションストアを噛ませたり、ゲートウェイでリクエストボディを覗いて振り分けたりしてきた。本来HTTPの世界がとうに卒業したはずの苦労を、AIエージェント界隈は2年かけてもう一度やり直していた。
その前提を、今日公開された Model Context Protocol の 2026-07-28 仕様がまるごと捨てた。MCP(LLMに外部ツールやデータを繋ぐための標準プロトコル。Anthropicが主導する)にとって、ローンチ以来いちばん大きな改訂で、しかも破壊的変更を含む。核心は一言で言える。プロトコルからセッションという概念を消した。
何が消えたのか
これまでのMCPは、クライアントがまず initialize を送り、サーバが Mcp-Session-Id ヘッダを返す握手から始まっていた。以降のリクエストはそのセッションIDを持ち回り、事実上「このサーバインスタンスに固定」される。TechCrunchの取材で、エージェント基盤スタートアップArcadeのNate Barbettini氏はこの構造の痛点をこう言い当てている。
サーバ農場の各マシンが、別のマシンが配ったセッションIDを全部知っていなければならなくなる
2026-07-28版は、この initialize/initialized の握手と Mcp-Session-Id ヘッダを両方とも削除した(SEP-2567)。すべてのリクエストが自己完結する。代わりに Streamable HTTP のリクエストには新しいヘッダが必須になった。
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Mcp-Method と Mcp-Name があることで、ゲートウェイやレートリミッタは中身(JSONボディ)を開けずにヘッダだけで「どのツールのどの操作か」を判断して振り分けられる。ディープパケットインスペクションが要らない。仕様策定を主導したDavid Soria Parra氏は、独立系メディアThe Registerに対し設計思想を「状態をサーバから引き剥がしてワイヤ(通信路)の側に移す」と表現した。これはAnthropicのステートレスなMessages APIと同じ発想だ。
状態は消えたのではなく、見える場所に移った
ここで誤解しやすいのは、ステートレス化=状態を持てなくなる、ではない点だ。サーバはこれまでどおり状態を跨いで持てる。ただし持ち方が変わる。仕様の言葉を借りれば、HTTP APIが昔からやってきたことをやればいい。ツールが basket_id や browser_id といった明示的なハンドル(識別子)を返し、モデルがそれを次の呼び出しの普通の引数として渡す。
つまり create_basket が返した basket_id を、後続の add_item が引数で参照する。状態はトランスポート層のどこかに隠れるのではなく、モデルが読めて推論できる引数として表に出る。個人的にはこの一点がこの改訂でいちばん筋が良いと思う。エージェントが自分の扱っている状態を「見えない」まま操作させられる設計は、デバッグでも安全性でも扱いにくかった。状態をモデルの手のひらに戻したわけだ。
なお、リクエストメタデータの運び方については報道に食い違いがある。公式ブログはヘッダを強調する一方、The Registerはプロトコルバージョンやクライアント情報が _meta パラメータに載ると書いている。ルーティング用のヘッダと、それ以外のメタ情報の載せ替えは別の話と読むのが自然だが、SDKで実装する際は自分の使う言語のベータ実装で確認したほうがいい。
キャッシュが素直になった
セッションが消えた副産物として、tools/list のようなリスト系レスポンスに ttlMs と cacheScope が付いた。HTTPの Cache-Control を素直に持ち込んだもので、クライアントは「このツール一覧が何ミリ秒新鮮か」「ユーザ間で共有していいか」を明示的に知れる。結果として、スティッキールーティングも共有セッションストアも要らず、ただのラウンドロビンのロードバランサの後ろでMCPサーバを回せるようになる。運用コストの話として地味に効く。
消えるもの、格下げされるもの
破壊的とはいえ、いきなり動かなくなるわけではない。SEP-2577 で3つの機能が非推奨(deprecated)になったが、少なくとも今後1年間は動く。
| 機能 | 状態 | 移行先 |
|---|---|---|
| Roots | 非推奨 | ツール引数・リソースURI・サーバ設定 |
| Sampling | 非推奨 | LLMプロバイダのAPIを直接叩く |
| Logging | 非推奨 | stdioならstderr、構造化ならOpenTelemetry |
Tasks(長時間の非同期処理)はコアからExtensionへ移り、tools/call がタスクハンドルを返して tasks/get・tasks/update・tasks/cancel で駆動する形になった。tasks/list は削除された。セッションが無いと安全にスコープを切れないから、という理由がはっきり書かれている。この「セッションを消したから、セッション前提のAPIも整理する」という一貫性は好感が持てる。
新設されたExtensionsフレームワークは、逆引きDNS形式のIDを持ち、extensions マップで能力をネゴシエートする。第一号の公式Extensionが、サーバ側でUIを描く MCP Apps(SEP-1865)だ。ほかにツールスキーマがJSON Schema 2020-12対応になり、リソース不在エラーが独自の-32002からJSON-RPC標準の-32602に変わっている。地味だが既存クライアントのエラーハンドリングを壊しうるので要注意だ。
移行は軽くない
熱狂だけを伝えても誠実ではない。Parra氏自身が独自実装勢に対し「正しく直すのはかなりの労力になる」と認めている。Stacklokは後方互換が保証されない点を警告していて、2026-07-28版のサーバが古いクライアントと動かない可能性があり、フォールバックや変換層を自前で用意する必要が出る。仕様のスケジュールを見ると、リリース候補は5月21日に確定し、10週間の検証期間を経て今日7月28日が最終版という流れだ。
裏を返せば、今回の痛みは一度きりにする設計になっている。非推奨は最短12か月、そのあいだ動き続けるという正式なポリシーが入り、標準化トラックのSEPは適合性スイート(conformance suite)に対応シナリオが入るまでFinalになれなくなった。仕様側は「2026-07-28を実装しておけば、今後の改訂はトランスポートやライフサイクルのコードを書き直さずに追随できるはず」と述べている。
REST APIが十数年前に学んだ「ステートレスにすると水平に伸ばせる」という教訓を、エージェントのツール層がいま追体験している。それだけの話とも言えるが、握手とセッションIDという2つの小さな仕組みを外すだけで、MCPサーバの運用がKubernetes利用者の期待する普通のクラウドネイティブな形に寄る。もしあなたがリモートMCPサーバを運用しているなら、まず自分のツールが暗黙にセッション状態へ依存していないかを洗い出し、依存しているならハンドルを返す設計へ書き換えるのが最初の一歩になる。