リモートMCPサーバーをレプリカ3台に増やした途端、リクエストが時々失敗しはじめる。心当たりのある人は多いはずだ。原因はたいてい同じで、最初の initialize で握った状態が特定のインスタンスにだけ残り、ロードバランサが別のインスタンスへ振ると「そんなセッションは知らない」と弾かれる。だから結局スティッキーセッションを設定するか、Redis あたりに共有セッションストアを立てて逃げる。この面倒が、MCP の次期仕様でまるごと不要になる。
Model Context Protocol(LLM に外部ツールやデータを接続するための標準プロトコル)は、2026年7月28日に公開予定の新リビジョン 2026-07-28 で、プロトコルのコアをステートレスに作り直す。リリース候補(RC)は5月21日に確定済みで、6月29日には主要4言語のベータ SDK も出た。方針を一言で言えば、接続にひもづく状態を全部やめる。
どこがステートフルだったのか 🔌
これまでの MCP は、クライアントがまず initialize を投げ、サーバーが Mcp-Session-Id ヘッダーを発行し、以降のリクエストはそのセッション ID を持ち回る、という接続指向の設計だった。HTTP の上には乗っているが、中身は事実上ステートフルなコネクションで、水平スケールと相性が悪い。どのインスタンスがどのセッションを持っているかを気にしないといけない時点で、素の HTTP のうまみが半分死んでいる。
新仕様はこのハンドシェイクを丸ごと削除する。Mcp-Session-Id も無くなる。代わりに、プロトコルのバージョン・クライアント情報・ケイパビリティを毎リクエストの _meta に載せて運ぶ。概念を示すとこういう形だ。
{
"method": "tools/call",
"params": { "name": "search", "arguments": { "q": "mcp" } },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": { "name": "my-client", "version": "1.0" },
"io.modelcontextprotocol/clientCapabilities": {}
}
}
サーバー側の能力は、新設の server/discover メソッドで必要なときに取りに行く。結果として、どのリクエストも単体で自己完結し、どのインスタンスに届いても処理できる。「セッションをどこに置くか」という問いそのものが消える、というのがこの変更の本質だ。
素の HTTP インフラにそのまま乗る
変わりどころを現行仕様と並べるとわかりやすい。
| 2025-11-25(現行) | 2026-07-28(新) | |
|---|---|---|
| セッション |
Mcp-Session-Id を発行 |
廃止 |
| 初期化 |
initialize / initialized
|
廃止。_meta で毎回送る |
| 能力取得 |
initialize の応答 |
server/discover |
| 水平スケール | スティッキー必須 | ラウンドロビンで可 |
トランスポート層も手が入った。Streamable HTTP の POST には Mcp-Method と Mcp-Name ヘッダーが必須になり(SEP-2243)、ゲートウェイはリクエストボディを覗かずにこのヘッダーだけでルーティングやレート制限をかけられる。一覧・読み取り系(tools/list など)のレスポンスには鮮度ヒント ttlMs と cacheScope(public / private)が付き、クライアント側でキャッシュしてポーリングを減らせる。認可まわりも OAuth 2.0 / OpenID Connect の実運用に寄せて固められ、認可レスポンスの iss 検証(RFC 9207 準拠)が必須化された。単一クライアントが多数のサーバーに繋ぐ MCP の構造では、この種のミックスアップ攻撃が効きやすいので妥当な補強だ。
移行のことも一応考えられている。新旧が混在しても壊れない。
Clients that speak
2026-07-28fall back to theinitializehandshake when they reach a server on2025-11-25or earlier, so old servers and new clients keep interoperating.
新しいクライアントは、古いサーバーに当たったら旧来の initialize ハンドシェイクに自動でフォールバックする。逆に v2 のサーバーは、1つのエンドポイントで新旧どちらのリビジョンにも応答できる。段階移行の逃げ道は用意されている。
触ってみる
ベータ SDK は Python・TypeScript・Go・C# の4本。Python なら現行の安定版を壊さずに試せる。
uv add "mcp[cli]==2.0.0b1"
# または
pip install "mcp[cli]==2.0.0b1"
TypeScript はパッケージが分割され、@modelcontextprotocol/server@beta と @modelcontextprotocol/client@beta を入れる形になった。Go は go get github.com/modelcontextprotocol/go-sdk@v1.7.0-pre.1、C# は dotnet add package ModelContextProtocol --prerelease。SDK の詳細とフィードバック方法は公式の告知にまとまっている。
タダではない移行コスト
ステートレス化と同時に、Roots・Sampling・Logging と旧 HTTP+SSE トランスポートが非推奨に落ちる。ここで新設の機能ライフサイクル(Active → Deprecated → Removed、非推奨から削除まで最低12か月)が効く。すぐ動かなくなるわけではないが、Sampling でサーバーからクライアント側の LLM を呼び返す実装などはいずれ作り直しが要る。なお参照する SEP 番号は解説記事ごとに食い違う(セッション削除とハンドシェイク廃止を別 SEP に割り当てる記述もある)ので、番号は最終仕様で確認したほうがいい。
同じリビジョンでは拡張の仕組みも入り、対話 UI をサンドボックス化した iframe で返す MCP Apps や、tools/call がタスクハンドルを返し tasks/get などで長時間処理を回す Tasks 拡張が加わる。本体を薄いステートレスなコアに保ちつつ、重い機能は拡張へ切り出す設計判断で、方向性としては素直だ。
面白いのは、サーバーに状態を持たせて会話を継続させる流れが LLM の API 側で目立つなか、MCP はあえて逆に振ったことだ。ツール接続層はインフラに近い。ならば「状態を外に出したステートレスなプロセス」に寄せるほうが、CDN・ロードバランサ・レート制限といった既存の HTTP スタックにそのまま乗る。7月28日の確定を待たず、リモートサーバーを運用している人はベータで自分のデプロイ構成を一度当ててみる価値がある。スティッキーセッションを消せるかどうかは、触ればすぐわかる。