Model Context Protocol(MCP)の最新仕様「2026-07-28リリース候補」が、プロトコルレベルでの完全なステートレス化を実現した。Microsoftの公式ブログ「Apps on Azure」でその詳細と移行ガイドが公開され、Azure App Service上でMCPサーバーをスケールアウトする際の複雑さが根本的に解消されることになる。
MCPがステートレスになるとは何か
これまでのMCP仕様(2025-11-25)では、クライアントが最初にinitializeリクエストを送り、サーバーからMcp-Session-Idを受け取る「ハンドシェイク」が必須だった。このセッションIDはその後のすべてのリクエストに付与され、事実上「どのインスタンスが応答したか」を固定する役割を果たしていた。
水平スケーリング環境では、このセッションの「スティッキー性」が障害になる。インスタンスをまたいでセッション状態を共有するにはAzure Cache for Redisのような外部ストアが必要で、ARRアフィニティの無効化と合わせて手順が増えていた。
2026-07-28仕様では、この構造そのものが削除された。
削除されたもの
仕様変更の中心は2つのSEP(Spec Enhancement Proposal)だ。
- SEP-2575:
initialize/initializedハンドシェイクの廃止。プロトコルバージョンやクライアント情報は_metaフィールドでリクエストごとに送る - SEP-2567:
Mcp-Session-Idヘッダーとプロトコルレベルのセッション管理の廃止
結果として、すべてのMCPリクエストはどのインスタンスでも処理できる自己完結型のメッセージになった。
// 2026年仕様でのtool call(セッションID不要) { “jsonrpc”: “2.0”, “id”: 1, “method”: “tools/call”, “params”: { “name”: “search”, “arguments”: {“q”: “otters”}, “_meta”: { “io.modelcontextprotocol/clientInfo”: {“name”: “my-app”, “version”: “1.0”} } } }
追加されたもの
ステートレス化と同時に、インフラ層との親和性を高める3つの改善も加わった。
- ルーティング可能なヘッダー(SEP-2243):
Mcp-MethodとMcp-Nameヘッダーの必須化。ロードバランサーやAPIゲートウェイがリクエストボディを解析せずに操作単位でルーティング・レート制限できる - キャッシュ可能なリスト(SEP-2549):
tools/listの結果にttlMsとcacheScopeが付与され、HTTPCache-Controlと同様のキャッシュ制御が可能に - 分散トレーシング(SEP-414): W3C Trace Context(
traceparent等)が_meta内で標準化。Application InsightsなどOpenTelemetry対応バックエンドで、クライアントSDKからMCPサーバー、その下流まで一本のスパンツリーとして可視化できる
App Serviceでの変化:何がどう楽になったか
App Serviceのビルトインロードバランサーはもともとラウンドロビンで動作させたいが、これまでのMCPはプロトコル自身がセッションアフィニティを持っていたため干渉していた。2026仕様でその干渉がなくなった。
| 項目 | 2025年仕様 | 2026年仕様 |
|---|---|---|
| ARRアフィニティ無効化 | 必須 + Redisでセッション共有が必要 | 必須(プロトコルとの競合はない) |
| Redis の用途 | プロトコルセッション状態の共有 | アプリ固有の状態管理のみ |
| インスタンス追加時 | セッション共有の設定変更が必要 | スケールアウトするだけ |
「普通のステートレスWebアプリをスケールアウトする」感覚でMCPサーバーを運用できるようになる、というのが今回の変化の本質だ。
「ステートレスプロトコル」はアプリがステートレスになるわけではない
ここは誤解しやすいポイントなので明確にしておく。プロトコルのステートレス化は、アプリケーションが状態を持てなくなることを意味しない。
アプリが複数のリクエストにまたがる状態を保持したい場合は、「エクスプリシットハンドル」パターンを使う。ツールが返すbasket_idなどの識別子をモデルが次のリクエストで引数として渡す方式だ。
// 1. 作成:ハンドルを返す {“name”: “create_basket”, “arguments”: {}} // -> { “basket_id”: “b_12345” }
// 2. 以降:ハンドルを引数として渡す {“name”: “add_item”, “arguments”: {“basket_id”: “b_12345”, “sku”: “ABC”}}
セッションIDとの違いは、モデルがハンドルを「見える」形で扱える点だ。モデルは複数ツール間でハンドルを組み合わせたり引き渡したりできる。トランスポートのメタデータに隠れていたセッション状態とは根本的に違う設計思想だ。
Redisが不要になるわけでもない。バスケットb_12345の実データを保持するのはRedisやCosmos DBの役割であり、「アプリの状態管理」として引き続き重要だ。プロトコルの配管役から解放された、という話である。
移行の実務チェックリスト
既存のMCPサーバーを2026仕様に移行する場合のポイントを整理する。
App Service設定(ほぼ変更不要)
clientAffinityEnabled: falseは継続- Application Insights + OpenTelemetryは継続(新しいTrace Contextキー名を活用)
- インスタンス数の変更なし
プロトコル層(本丸の作業)
2026-07-28対応SDKへのアップデート_metaからプロトコルバージョン・クライアント情報を読む処理の実装tools/listにttlMs/cacheScopeを付与Mcp-Method/Mcp-Nameヘッダーの検証ロジック追加Mcp-Session-Idベースの状態管理をエクスプリシットハンドルパターンに書き換え
破壊的変更の確認
tasks/listの廃止- Roots/Sampling/Loggingの非推奨化
- 「リソース未発見」エラーコードが
-32002→-32602に変更
タイミング注意: 2026-07-28はあくまでリリース候補(RC)。正式リリースは2026年7月28日の予定で、破壊的変更を含む。今日から全リライトするのではなく「準備フェーズ」と位置づけよう。
筆者の見解
MCPのステートレス化は、設計思想として正しい方向への前進だと思う。ステートフルなプロトコルはスケールの敵であり、状態はアプリケーション層で明示的に管理するほうが追跡・デバッグ・水平展開のすべてにおいて有利だ。「プロトコルが状態を隠し持つ」設計は便利に見えて、後で必ず痛みを伴う。
Azure App Service上での利便性という観点では、今回の仕様変更はMicrosoftのサービスと噛み合いが良くなった形だ。もともとステートレスなWebワークロードを得意とするApp Serviceの強みが、MCPサーバーにもそのまま活きるようになった。
W3C Trace Contextの標準化も地味に重要だ。エージェントシステムは「どのツールを呼んで、どのインスタンスが処理して、何ミリ秒かかったか」が見えないと運用が成立しない。Application Insightsで一本のスパンツリーとして追える設計が標準仕様に入ったことで、本番投入のハードルが下がる。
MCPエコシステムはまだ動きが速く、今後も仕様変更は続くだろう。重要なのは「変更に振り回されない設計」を選ぶことで、今回の明示的ハンドルパターンはその意味で覚えておく価値がある。状態をリクエストの引数として明示的に渡す習慣は、MCPに限らずAIエージェント設計全般のベストプラクティスになっていくはずだ。
出典: この記事は MCP Just Went Stateless — What the 2026 Spec Changes About Scaling on App Service の内容をもとに、筆者の見解を加えて独自に執筆したものです。