MCPを悩ませてきたステートフルという罠
MCPの初期プロトコルには、本質的なステートフル性という重大なアーキテクチャ上の制約がありました。以前は、クライアントがMCPエンドポイントに対して「initialize」リクエストを送ることでやり取りを開始していました。サーバーはそこで一意の「session ID」を発行して返却し、このトークンはそれ以降のすべてのクライアント・サーバー間通信において不可欠なものとなっていました。すべての後続リクエストには、この識別子を含める必要があったのです。
この設計は、スケーラブルなデプロイメントにおいて根本的な欠陥を生んでいました。必須の「session ID」により、クライアントは最初に「initialize」呼び出しを処理した特定のサーバーインスタンスに固定されてしまったのです。これは標準的なロードバランシングのパラダイムを破壊しました。例えばラウンドロビン方式のルーターが後続のリクエストを別のインスタンスに振り分けた場合、そのサーバーにはセッションの記録がないため、400 "session not found" エラーが発生し、クライアントの操作が停止してしまいました。同様に、インスタンスがクラッシュすれば、そのアクティブなセッション状態はすべて即座に失われ、クライアントのリクエスト失敗を招いていました。
開発者は、これらの問題を緩和するために複雑で非効率な回避策を強いられてきました。一般的な解決策には、クライアントが常に同じサーバーインスタンスに接続するようにする「スティッキーセッション」の実装がありました。また、Redisインスタンスのような共有ステートストアを導入し、すべてのサーバー間でセッションデータを一元化・同期させる手法も取られていました。どちらの方法も不必要な運用オーバーヘッドを招き、ネットワーク遅延を増大させ、インフラコストを大幅に引き上げる要因となっていました。これらは選択肢ではなく、プロトコルによって押し付けられた負担だったのです。
デフォルトでステートレスに:生まれ変わったプロトコル
MCPの新しい仕様「2026-07-28」は、根本的な転換をもたらします。2つの重要な提案であるSEP-2575とSEP-2567が、プロトコルの核心を再定義しました。SEP-2575は「initialize」および「initialized」ハンドシェイクを廃止し、SEP-2567は「MCP-Session-Id」ヘッダーとそれに関連するプロトコルレベルの「session」を削除しました。
これらの変更により、複数ステップを要したツール呼び出しが、単一の完結したHTTPリクエストへと変貌しました。以前はコンテキストが断片化されていましたが、現在は必要なすべての情報がJSONボディ内の「meta」フィールドに含まれるようになっています。この設計により、すべてのリクエストが独立したものとなり、ステートレスなHTTP原則に準拠するようになりました。
標準的なHTTPインフラとの親和性も完璧です。新しいヘッダーである「MCP-Method」および「MCP-Name」が、重要なルーティング情報を担うようになりました。これにより、ゲートウェイ、ファイアウォール、レートリミッターなどのネットワークコンポーネントが、JSONペイロードを解析することなく判断を下せるようになります。このような効率性は、特にCloudflare上でのパフォーマンスにおいて極めて重要です。
プロトコルはMCPを扱うためにDurable Objectsを必要としなくなり、デプロイメントが簡素化されました。サービスはアイドル時にゼロまでスケールダウンできるため、運用コストが大幅に削減され、デプロイメントの選択肢が広がります。この移行により、スティッキーセッションや共有Redisインスタンスといった悩みが解消され、MCPはデフォルトで真にステートレスなものとなりました。
よりスマートなインフラとアプリケーションステート
ステートレス化は、デプロイメントに大きな利点をもたらします。Cloudflare WorkersやGoogle Cloud Runのようなサーバーレスプラットフォームは、アイドル時にゼロまでスケールするようになり、「運用コスト」を劇的に削減します。サーバーは永続的な接続を維持する必要がなくなり、セッション状態を保持するために常時稼働するインスタンスが不要になります。これはインフラプロビジョニングのあり方を根本から変えるものです。
Protocolはもはや状態管理の負担にはなりません。代わりに、状態はアプリケーションレベルの懸念事項となります。ツールはbasket_idやbrowser_idといった明示的なハンドルを発行できます。モデルは、その後のツール呼び出しにおいて、この識別子を通常の引数として返します。これにより、開発者はプロトコルで強制されたパターンに従うのではなく、必要に応じて正確に状態を管理できるという、より高い柔軟性を得ることができます。
MCPは、クライアント側の効率を高めるためにHTTPに着想を得たキャッシングを採用しています。新しいtime to live(有効期間)およびcache scope(キャッシュスコープ)のヒントにより、クライアントはツール、プロンプト、リソースリストの鮮度を把握できます。これにより、クライアントは自信を持って応答をキャッシュでき、更新のために永続的な接続を維持する必要がなくなります。堅牢なステートレスAPI設計に関する詳細な読み物については、Statelessness in API Design: Understanding & Examples - Unkeyをご覧ください。これらのヒントにより、クライアントはデータがユーザー間でどのくらいの期間有効であるかを正確に把握できます。
この記事が気に入ったら、毎朝同じようなものをメールで受け取れます。
1日1通 · 2クリックで解除 · サードパーティのトラッキングなし
複雑なインタラクションのための新しいパターン
複雑なインタラクションは、明確なクライアント主導のパターンに従うようになりました。以前は、サーバーが一方的にフォローアップの質問を送信していましたが、これはセキュリティ上のリスク(セキュリティ・フットガン)となっていました。新しい仕様ではこれを防止します。複数ターンのインタラクションの場合、サーバーはinput_required結果を返します。
この結果には、保留中のアクションに必要なすべてのコンテキストをカプセル化したシリアル化されたrequest_stateペイロードが含まれます。クライアントはinput_requiredを受け取ると、ユーザーにプロンプトを表示し(例:「よろしいですか?」)、その後、元のリクエストを再開します。クライアントはユーザーの応答を添付し、request_stateをエコーバックします。これにより、クライアントが常にインタラクションを主導することが保証されます。どのサーバーインスタンスでも再開されたリクエストを処理できるため、ステートレス性が強化されます。
長時間実行される操作には、正式版となった「tasks」拡張機能を活用します。この機能は実験的ステータスから昇格しました。返金処理のようなタスクの場合、サーバーはリクエストを即座に受け付けます。ジョブが実行中であることを示す応答を返すことで、接続のブロックを防ぎます。
クライアントはその後、非同期で進捗を追跡します。tasks/getを使用してポーリングするか、subscriptions/listenを介してサブスクライブできます。これにより、長時間実行されるタスクが完了した際に最終結果を取得できます。この設計により、長時間の計算中に永続的な接続を維持する必要がなくなり、プロトコルの効率と回復力が向上します。
よくある質問
従来のステートフルなMCPの主な問題は何でしたか?
従来のプロトコルでは、クライアントを特定のサーバーインスタンスに固定するセッションIDが必要でした。これにより負荷分散が困難になり、スティッキーセッションやRedisのような複雑な回避策が必要となり、サーバーの再起動でセッション状態が失われる可能性があるため、システムが脆弱になっていました。
新しいステートレスなMCPは、これらの問題をどのように解決しますか?
セッションのハンドシェイクとIDを完全に排除しました(仕様 2026-07-28)。すべてのリクエストは自己完結型であり、標準的なラウンドロビン負荷分散が可能になり、回復力が向上し、サーバーをゼロまでスケールダウンしてコストを削減できるようになりました。
プロトコルがステートレスである場合、新しいMCPでは状態はどのように管理されますか?
状態はプロトコルレベルではなく、アプリケーションレベルで管理されるようになりました。開発者はツールを使用して明示的なハンドル(例:'browser_id')を作成し、モデルが後続の呼び出しでそれを返すようにできます。これは標準的なHTTP APIで一般的な柔軟なパターンです。
永続的な接続がない場合、長時間実行されるツール呼び出しはどうなりますか?
新しい仕様では、「tasks」拡張機能が正式な機能に昇格しました。長時間実行されるジョブの場合、サーバーは即座にタスクIDを返すことができ、クライアントはそのタスクをポーリングまたはサブスクライブして、進捗状況の更新と最終結果を非同期で取得できます。

