mcpmetricsmcpmetrics
← 記事一覧
·4 分で読めます

/sse の罠:壊れて見えるが壊れていない 387 台

MCP には HTTP のトランスポートが二種類あります。間違ったほうを使うと、サーバーは 200 を返しながら何も教えてくれません。私たちは 387 台に対してまさにそれをしていました。

MCP は二通りの方法で HTTP を話し、両者は入れ替えられません。Streamable HTTP は JSON-RPC を単一のエンドポイントへ直接送ります。より古い HTTP+SSE トランスポートはまったく別で、まずストリームを開き、どこへ送るかをサーバーが教えてくれます。

失敗したときの見え方

HTTP+SSE のエンドポイントに initialize リクエストを送ると、エラーは返りません。返ってくるのはこれです。

HTTP 200
content-type: text/event-stream

event: endpoint
data: https://example.com/my-mcp/api/process

200 OK。エラーコードも苦情もありません。あるのは「本当のエンドポイントはあちらです」という丁寧な案内だけ。それを予期していないクライアントは、空のレスポンスとして読んでしまいます。

罠はここにあります。成功を返す失敗は、500 を返す失敗よりはるかに気づきにくいのです。

私たち自身が落ちました

読み取れないサーバーは「unknown」に分類しています。なぜこの区分がこれほど大きいのか調べたところ、387 台が誤った方法でリクエストしていた HTTP+SSE エンドポイントだと判明しました。URL が /sse で終わるサーバーのうち 84% が unknown 扱いで、カタログ全体では 10% です。八倍の差は偶然ではなく、指紋です。

それらのサーバーはずっと正常でした。間違ったプロトコルを話していたのは私たちのほうです。

避け方

  • JSON-RPC の本文が空、または解析できない 200 応答は、死んだサーバーではなくトランスポートの不一致として扱ってください。
  • コンテンツタイプが text/event-stream で、最初のイベント名が endpoint なら、それをたどってそちらへ送ってください。
  • URL だけを信用しないでください。/sse で終わるのは手がかりであって保証ではなく、/sse で終わらない HTTP+SSE エンドポイントも多数あります。

サーバーを公開しているなら、最も安上がりな対策はレジストリ登録でどのトランスポートを話すか明示することです。ほとんどのクライアントはそれを信じます。

プロトコルの挙動でサーバーを探す
#mcp#トランスポート#sse

他の記事

/sse の罠:壊れて見えるが壊れていない 387 台 | mcpmetrics