ストリーミングHTTP:3つの時代と現在のワイヤコントラクト

Built for Speed: ~10ms Latency, Even Under Load
Blazingly fast way to build, track and deploy your models!
- Handles 350+ RPS on just 1 vCPU — no tuning needed
- Production-ready with full enterprise support
MCPのリモートHTTPトランスポートは、約2年間で3つの異なるワイヤプロトコルの時代を経てきました。2024-11-05のHTTP+SSEトランスポートは、2つのエンドポイントと長時間接続のストリームを使用していましたが、2025-03-26以降は非推奨となり、将来的に削除される予定です。2025-03-26にはStreamable HTTPが導入され、エンドポイントが1つに統合されました。しかし、その初期段階では、プロトコルレベルのセッション、独立したGETストリーム、SSE上でのサーバー主導リクエスト、再開可能なストリームといった仕組みが残っていました。2026-07-28の改訂では、これらのメカニズムがすべて削除されました。現在の仕様は非常にシンプルです。クライアントのJSON-RPCメッセージはすべて個別のPOSTとして送信され、リクエストに対するレスポンスは単一のJSONオブジェクトか、そのリクエストに紐付いたSSEストリームのいずれかとなります。また、特定のリクエストメタデータがヘッダーにミラーリングされるため、仲介サーバーはボディを解析することなくトラフィックのルーティングや検査が可能になりました。この最後の設計変更こそ、深く理解しておくべき重要なポイントです。
ロードバランサーがヘッダーに基づいてルーティングを行い、サーバーがボディに基づいて実行を行う際、両者の間で不整合が生じることがあります。 これは仕様上の仮定の話ではなく、特定のバリデーションルールが存在する明確な理由となっています。2026-07-28のトランスポートは、クライアントとサーバー間の仲介者の存在を明示的に考慮しており、新しいヘッダー契約の多くは、その前提があって初めて意味を成すものです。
1. 3つの時代
2024-11-05 — HTTP+SSE 2つのエンドポイントを使用。クライアントがGETを発行してSSEストリームを開き、その最初のイベントとして endpoint イベントが送信され、クライアントにPOST先を通知していました。サーバー主導の通信はすべて、この長時間接続のストリームを通じて行われていました。機能ライフサイクルポリシーに基づき2025-03-26から非推奨となっており、新規実装での採用は推奨されません。
2025-03-26 ~ 2025-11-25 — Streamable HTTP(初期形態) MCPエンドポイントを1つに統合したことが大きな簡素化でした。しかし、以下の4つのメカニズムによりステートフルな状態が維持されていました。サーバーは Mcp-Session-Id ヘッダーを通じてセッションを割り当て、HTTP DELETEで終了させる仕組みがありました。また、クライアントはGETで独立したSSEストリームを開いてサーバー主導のメッセージを受信でき、サーバーはSSEストリーム上でJSON-RPC requests を送信可能で、ストリームは Last-Event-IDを介して再開可能でした。
2026-07-28 — 現在の形態 上記の4つのメカニズムはすべて廃止されました。改訂ノートには、GETストリームエンドポイントとプロトコルレベルのセッションが削除されたことが明記されています。また、以下のセクションで説明するように、ストリームの再開は不可能となり、サーバーがストリーム上で独立したリクエストを送信することも禁止されています。
現行リビジョンのみを実装するサーバーは、古いトラフィックに対して以下の挙動をとります。MCPエンドポイントへのGETまたはDELETEリクエストに対しては、 405 Method Not Allowedを返し、 Mcp-Session-Id ヘッダーは無視され、セッション識別子の発行やエコーバックは行われません。また、 Last-Event-ID ヘッダーも無視されます。
2. ワイヤプロトコル
サーバーは、POSTをサポートする単一のHTTPエンドポイントパス(MCPエンドポイント)を公開します。ワイヤの最適化を行う前に、トランスポートのセキュリティ基準が重要となります。サーバーは、受信接続の Origin ヘッダーを検証し、Originが存在しても無効な場合は403を返す必要があります。ローカルで実行されるサーバーは、すべてのインターフェースではなくlocalhostにバインドすべきであり、接続の認証を行うことが推奨されます。これらの要件は、DNSリバインディングや不正アクセスのリスクを軽減するために存在します。
送信 クライアントからのすべてのJSON-RPCメッセージは、個別のPOSTリクエストとして送信されます。クライアントは、 Accept ヘッダーに application/json および text/event-streamの両方を指定して含める必要があり、ボディは単一のJSON-RPCリクエストまたは通知である必要があります。クライアントはJSON-RPCレスポンスを送信してはなりません。実装者にとって重要な注意点として、トランスポートは通知POSTの挙動を定義していますが、2026-07-28版のコアプロトコルでは、Streamable HTTP経由のクライアントからサーバーへの通知は定義されておらず、通知POSTに対するメタデータヘッダーの要件も規定されていません。
通知 サーバーがリクエストを受け入れた場合、以下のステータスを返します。 202 Accepted ボディは空です。受け入れられない場合はHTTPエラー状態を返し、必要に応じてJSON-RPCエラーレスポンスを含めることができますが、その際 idは含めません。
リクエスト サーバーは、 Content-Type: application/json を伴う単一のJSONオブジェクト、または Content-Type: text/event-stream を伴う、そのリクエストにスコープされたSSEストリームのいずれかを返します。クライアントは両方をサポートする必要があります。サーバーはリクエストごとにいずれかを選択するため、片方しか処理できないクライアントは予期せず動作しなくなります。
レスポンスストリームで送信される内容 サーバーは、最終的なレスポンスの前に、元のリクエストに関連する通知(進捗状況やログメッセージなど)を送信することがあります。最終的なレスポンスはストリームを終了させる必要があります。サーバーは、このストリーム上で独立したJSON-RPCリクエストを送信してはなりません。これは以前の改訂版からの明確な変更点です。
キャンセル SSEレスポンスストリームの切断は、サーバー側でそのリクエストのキャンセルとして扱わなければなりません。各リクエストには独自のストリームがあるため、切断は明確に識別されます。コアプロトコルのキャンセル通知はstdioでのみ使用されます。このトランスポートではキャンセルメッセージは存在せず、また期待もされません。
3. サーバー主導の処理の移行先
以前はサーバーからクライアントへのチャネルを必要としていた2つの機能が、それぞれ異なるメカニズムに分離されました。
クライアントへの要求 (サンプリング、情報の引き出し、ルートなど)は、現在「マルチラウンドトリップリクエスト」パターンに基づき、入力リクエストとして結果に組み込まれています。サーバーは InputRequiredResult を保持し、 inputRequests。クライアントは要求された内容を収集し、対応する inputResponsesを添えて元の呼び出しを再発行します。これはプッシュではなく、2回目のPOSTです。
長期的な変更通知 (ツールリストの変更やリソースの更新など)は、 subscriptions/listen リクエストを送信することで取得されます。このリクエストのレスポンス自体がSSEストリームとなっており、接続を維持したまま、クライアントが選択した通知タイプのみを配信します。進捗状況のようなリクエストスコープの通知はここには表示されず、その通知が属するリクエストのストリーム上でのみ流れます。
この分離は、言葉で聞くよりも整理されています。標準化された長期的な通知ストリームはクライアントの要求によって存在し、その内容はクライアント自身のサブスクリプションによってフィルタリングされるためです。サーバーが必要なコンテキストを requestState にエンコードし、クライアントが再試行時にその不透明な値をそのまま返すことで、複数回のラウンドトリップを伴う処理もMCPトランスポート層でステートレスに保つことができます。

4. プロキシ環境で問題となる2つの詳細
仕様書には、SSEとリバースプロキシの相性の悪さに起因する2つの運用上の注意点が記載されています。
バッファリング。 SSEストリームを開始する際、サーバーは X-Accel-Buffering: noを含める必要があります。これは、nginxなどのリバースプロキシに対してレスポンスのバッファリングを無効にするよう指示するものです。これがないと、プロキシがメッセージを溜め込んでから転送してしまい、遅延が発生してストリーミングの意義が損なわれる可能性があります。ストリーミングによる進捗更新が最後にまとめて届く場合は、レスポンスのバッファリングが原因である可能性が高いため、まず確認すべき中間動作の一つです。
キープアライブ 長時間のストリーム、特に subscriptions/listen レスポンスにおいて、サーバーはキープアライブとして定期的にSSEコメント行(コロンで始まる行)を出力することが推奨されます。これにより、中間サーバーやアイドルタイムアウトによって接続が切断されるのを防ぎます。SSE仕様に基づき、コメントにはイベントデータは含まれず、クライアントはこれらの行を不正なものとして扱うのではなく、無視しなければなりません。
5. ヘッダーコントラクト
これは、このトランスポートを従来のHTTP経由のJSON-RPCとは一線を画すものにする部分であり、その目的は仕様書に直接記されています。つまり、トランスポートはJSON-RPCボディの特定のフィールドをHTTPヘッダーにミラーリングすることで、ロードバランサー、ゲートウェイ、可観測性ツールといった中間サーバーが、ボディを解析することなくリクエストのルーティングや検査を行えるようにします。
MCP-Protocol-Version — すべてのPOSTリクエストで必須であり、その値はボディの _metaに含まれるプロトコルバージョンと一致しなければなりません。不一致の場合は 400 Bad Request および HeaderMismatch エラーで拒否されます。サーバーが実装していないバージョンが指定された場合は 400 エラーが返され、サポートされているバージョンがリストされます。実装されていないメソッドが呼び出された場合は 404 エラーが返され、JSON-RPCの -32601が付与されます。これが、従来のサーバーのそれと区別される点です。 404。
Mcp-Method — ミラーリング対象: method。すべてのJSON-RPCリクエストで必須です。
Mcp-Name — ミラーリング対象: params.name または params.uri。以下で必須となります: tools/call、 resources/read、および prompts/get。
JSON-RPCリクエストの場合、上記のスコープで準拠するためにこれらの標準リクエストヘッダーが必須となります。通知(Notification)のPOSTは別の例外的なケースであり、本改訂ではそのトランスポートメカニズムを定義していますが、メタデータヘッダーの要件については定義していません。最小限の準拠となる tools/call リクエストは、通信経路上では以下のようになります。
POST to the MCP endpoint
POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: get_weather
{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"get_weather","arguments":{"location":"Seattle, WA"},
"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28"}}}サーバーはさらに踏み込んで、特定のツールパラメータをミラーリングするように指定することも可能です。その際は、 x-mcp-header という拡張機能をパラメータのスキーマ内で使用します。これにより、以下のような名前のヘッダーが生成されます。 Mcp-Param-{Name}。例えば、regionパラメータに注釈を付けたサーバーの場合、 Mcp-Param-Region: us-west1 がボディと併せて送信されます。これは、ルーターがペイロードを読み取ることなく、適切なリージョンのバックエンドへクエリを送信するために必要な形式そのものです。
この拡張機能には厳格な制約があり、設計を行う前に把握しておく必要があります。値は空であってはならず、HTTPトークンの構文に準拠し、制御文字を含んではならず、スキーマ内で大文字と小文字を区別せずに一意である必要があります。使用できるのはプリミティブ型(文字列、ブール値、整数)のみであり、 number は明示的に除外されています。また、注釈が付けられたプロパティは、スキーマのルートから、 properties キーのみで構成されるチェーンを通じて静的に到達可能である必要があります。配列キーワードや、 oneOf、 anyOf、 allOf、または not条件分岐ではなく、また $ref。ネストされたオブジェクトは、各ステップが properties キーである限り問題ありません。それ以外の場所にアノテーションがあるとツール定義は無効となり、準拠するクライアントは、そのツールを tools/list から除外した上で警告をログに記録しなければなりません。これにより、1つの不正な定義が他の定義を無効にすることはありません。
プレーンなASCIIとして安全に表現できない値は、センチネル内でBase64エンコードされます。 =?base64?...?=。また、同じエンコーディングが Mcp-Nameにも適用されます。興味深い点として、センチネルのように見えるプレーンなASCII値であっても、曖昧さを排除するためにエンコードする必要があります。
6. なぜ不一致がエラーとなるのか
リクエストボディを処理するサーバーは、ヘッダー値と対応するボディ値が一致しないリクエストを拒否し、 400 を、JSON-RPCエラー -32020とともに返さなければなりません。仕様書ではその理由が明示されており、これは単なる整理の問題ではなく、セキュリティ上の議論に基づいています。つまり、ネットワーク内の異なるコンポーネントが異なる信頼ソースに依存している場合(ロードバランサーがヘッダー値に基づいてルーティングを行い、MCPサーバーがボディ値に基づいて実行を行うなど)に発生する脆弱性を防ぐためです。
これを脅威モデルとして捉えてください。仲介者がヘッダーに基づいて判断を下し、サーバーがそれとは異なる内容のボディに基づいて動作する場合、それらを意図的に異ならせたクライアントによって「信頼ソースの分裂」状態が引き起こされる可能性があります。例えば、ルーティングやポリシーはある値に基づいて評価される一方で、実行には別の値が使用されるといったケースです。サーバー側での必須バリデーションは、現在のリビジョンにおいてこの種の不一致を排除するものであり、エンコードされた値は比較前にデコードする必要があります。
7. ゲートウェイにとっての意味
中間層が何をすべきかを規定するプロトコルは稀です。このプロトコルはそれを規定しているため、マッピングが非常に直接的なものとなっています。
解析なしでルーティング。 Mcp-Method および Mcp-Name を使用することで、プロキシはヘッダーのみからツール呼び出しとリソース読み取りを判別し、どのツールが呼び出されたかを識別できます。これが、MCPを認識するレイヤーと、判断を下すためにすべてのペイロードをデシリアライズしなければならないレイヤーとの違いです(MCPの概要)。
ボディを解析することなく、認証レイヤーに対してツールの識別情報を公開します。 準拠した tools/call リクエストは、ツール名を Mcp-Nameに含めます。これにより、MCPを認識する仲介者は、ツールごとのポリシーを適用する際に使用できるプロトコル定義済みの入力情報を得ることができます。ただし、認証と認可はヘッダーから推測するのではなく、ゲートウェイやサーバー側で強制的に実行する必要があります(MCPの認証とセキュリティに関するドキュメント)。
ツールまたはテナントごとにレート制限を適用。 仕様書では、ミラーリングされたヘッダーを利用したテナントごとのレート制限が、仲介者における意図された用途として挙げられており、バージョンチェックが安全のための条件となっています(レート制限)。
有用なディメンションで観測する。 ボディ解析なしでメソッド名とツール名を取得できることは、ツールごとのテレメトリがまさに求めているものであり、テレメトリ標準で策定されつつあるツール呼び出しの規約とも整合します(分析およびトレーシングのドキュメント)。
トランスポート層からMCPセッションアフィニティを削除する。 プロトコルレベルのセッションが廃止され、レスポンスストリームが個々のリクエストにスコープされるようになったため、MCPトランスポートはスティッキーなルーティングや共有MCPセッションストアを必要としなくなりました。アプリケーションは引き続き、明示的なハンドルや共有ストアを使用して永続的な状態を保持できるため、「ステートレスなトランスポート」は「ステートレスなアプリケーション」を意味するものではありません。2025年初頭のトランスポート形状に関する背景については、以下を参照してください。 stdioとストリーマブルHTTPの比較。一般的なゲートウェイの分散パターンについては、以下で説明しています。 フェイルオーバーと負荷分散。
もう一つの義務は逆方向に作用するもので、通信経路上のあらゆるコンポーネントに適用されます。 Mcp-Param-{Name} ヘッダーを認識できない仲介者は、そのヘッダーを転送しなければならず、それ以外の場合は無視する必要があります。未知のヘッダーを削除する(堅牢化されたプロキシでは一般的なデフォルト設定です)と、それを期待している準拠サーバーが動作しなくなります。
エージェントハーネスの役割。 トランスポートには、いつツールを呼び出すかを判断する呼び出し元が依然として必要です。 TrueForgeは、TrueFoundryのオープンソースエージェントハーネスであり、モデル呼び出し、リモートMCPツール、スキル、サンドボックス化、承認、コンテキスト管理、セッション状態にわたる実行ループを管理します。その MCPコネクタ は、ヘッダー認証やOAuthを使用したリモートサーバーをサポートしており、ユーザーがまだサーバーを接続していない場合のチャット内での承認一時停止機能も備えています。これにより、役割分担が明確になります。TrueForgeがエージェントのステップをオーケストレーションし、ストリーマブルHTTPがクライアント・サーバー間の通信規約を定義し、TrueFoundry MCPゲートウェイが意図的にルーティングされるツールトラフィックを制御します。これらの層は、互いに代用できるものではありません。

8. デプロイ可能な構成
MCPサーバーを運用する場合は、ストリーミングの洗練度を気にする前に、 Originを検証し、接続を認証し、ローカルサーバーを保守的にバインドしてください。次に、SSEレスポンスには X-Accel-Buffering: no を出力し、長時間接続されるストリームにはkeep-aliveコメントを維持してください。バッファリングやアイドルタイムアウトは、アプリケーションの遅延やストリーミングの失敗のように見えることがあります。ヘッダーとボディの整合性を検証し、どちらか一方のみを信頼することは避け、センチネルエンコードされた値はデコードしてから比較してください。以前のStreamable HTTPリビジョンからのトラフィックに対しては、指定された互換性動作を返してください。つまり、 405 をGETおよびDELETEに対して返し、セッションヘッダーとイベントIDヘッダーを無視することで、古いクライアントが予測可能な形で失敗または適応できるようにします。
通信経路上の仲介者を運用する場合は、未知の Mcp-Param-* ヘッダーを転送し、ミラーリングされたヘッダーを信頼できるものとして扱う前にプロトコルバージョンを確認してください。また、ミラーリングが実現するために構築された機能(ルーティング、ポリシー入力、レート制限、メソッドやツール名に基づいたテレメトリなど)を、すべてのペイロードをデシリアライズすることなく活用してください。ヘッダーはメタデータを提供するものであり、呼び出し元がそのアクションを実行できるかどうかを判断するのは、依然としてIDおよび認可レイヤーの役割です。
クライアントを作成する場合は、両方のレスポンスコンテンツタイプをサポートし、SSEのコメント行は無視できるようにし、フォールバックシーケンスに従ってください。つまり、最新のリクエストを試行し、 400 が返された場合は、最新のサーバーも 400 を返す可能性があるため、結論を出す前にボディを調査してください。これは、サポートされていないバージョンやヘッダー検証の失敗時に発生します。認識された最新のエラーであれば、フォールバックではなく再試行を行ってください。
9. このプロトコルが解決すること、解決しないこと
2026年7月28日版のトランスポートはワイヤコントラクトを簡素化するものであり、エージェントのビジネスロジックを決定するものではありません。MCPレベルのセッションアフィニティを排除し、リクエストスコープのストリーミングとリトライの仕組みを定義し、ルーティングやポリシー入力に使用できる検証済みメタデータを仲介者に提供します。エージェントがどのツールを呼び出すべきかの選択、呼び出し元へのツール使用権限の付与、承認ポリシーの定義、アプリケーションメモリの永続化、あるいはダウンストリームの副作用がシステム記録によって承認されたことの証明を行うものではありません。
これらの責任は隣接するレイヤーに属します。例えば、次のようなエージェントランタイムが TrueForge 実行ループを所有し、MCPコネクタ、承認、コンテキスト、セッション状態を管理できます。TrueFoundry MCP Gatewayは、そこを通過するトラフィックの認証、認可、ツールアクセス、可観測性を一元化できます。MCPサーバーとダウンストリームのアプリケーションは、依然として独自のビジネス上の認可と処理結果に対して責任を負います。これらの境界を明確に保つことは、よりクリーンなトランスポートを完全なエージェントセキュリティモデルとして扱うよりも有益です。
最後に、本記事は急速に進化する仕様の一つの改訂版について記述したものです。ここでの要件レベルは2026年7月28日版のテキストに基づいています。実際のクライアントやサーバーは改訂版の適用が遅れる可能性があり、仕様書がすべての要約に対して優先されます。また、本記事は、特定のTrueFoundry Gatewayのデプロイ済みリリースが、2026年7月28日版のミラーリングされたヘッダーをすべて内部的に消費していることを保証するものではありません。
参考文献
- Model Context Protocol — Streamable HTTP transport specification (2026-07-28)。ここで説明したトランスポートの仕組み、セキュリティベースライン、リクエストメタデータ、検証、および互換性ルールのソースです。
- Model Context Protocol — 2026-07-28 changelog、および 2025-11-25 transport revision (以前の仕様)。
- Model Context Protocol — Multi Round-Trip Requests および subscriptions。
- TrueFoundry — stdioとストリーミングHTTP — 以前のトランスポートコンテキスト; MCPの認証とセキュリティ; レート制限; 分析。
- TrueForge — オープンソースのエージェントハーネス および MCPサーバーのセットアップ(ヘッダー認証やOAuthを用いたリモートMCPコネクタのドキュメント化、チャット内承認、承認プロセス、コンテキスト管理、永続セッションなど)。
メカニズム、要件レベル、ヘッダー名、エラーコード、互換性ルール、およびMRTRのステートセキュリティ要件は、リンク先の2026年7月28日付の仕様書テキストを要約したものです。リクエスト例は、仕様書内の図解を基に調整しています。MCPのリモートHTTPワイヤ設計は3つの時代を経て大きく変更されており、本要約よりも仕様書が優先されます。TrueFoundryの製品に関する主張は、リンク先の現在のページに記載されている機能に限定されます。本投稿は、特定のデプロイ済みゲートウェイバージョンが、2026年7月28日時点のミラーリングされたすべてのヘッダーを内部で使用していることを保証するものではありません。
TrueFoundry AI Gateway delivers ~3–4 ms latency, handles 350+ RPS on 1 vCPU, scales horizontally with ease, and is production-ready, while LiteLLM suffers from high latency, struggles beyond moderate RPS, lacks built-in scaling, and is best for light or prototype workloads.














.webp)

.png)



.png)
.png)
.png)

.png)
.png)
.png)
.png)
.png)





