Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[v2] Era-negotiation probe drops spec-conformant server/discover responses (top-level resultType/_meta) and misclassifies modern servers as legacy

クローズ
#2,722 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
62/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
typescript
領域
api, networking

調査の方向性

client/dist/index.mjs の ProbeWindow.open から始め、言及されているバンドル内の JSONRPCResultResponseSchema、wireResultResponse、decodeResult、classifyResult を追跡します。固定された Client と、仕様に沿った形の server/discover レスポンスで再現します。完了条件は、ネゴシエーション中に準拠したレスポンスが受け入れられ、パースエラーやタイムアウトが誤解を招く legacy 分類ではなく、診断可能な結果を生成することです。

索引モデルが issue の本文から書いたものです。

説明

v2
What happened?

Connecting a Client (stdio transport, pinned negotiation versionNegotiation: { mode: { pin: "2026-07-28" } }) to a spec-conformant MCP 2026-07-28 server fails:

SdkError [EraNegotiationFailed]: Version negotiation failed: the server did not offer
pinned protocol version 2026-07-28 via server/discover (no fallback in pin mode)

The server's response is spec-conformant per the 2026-07-28 Server Discovery spec example, where resultType and _meta appear as top-level siblings of result. Wire-captured exchange (server side verified correct via a binary stdio interceptor):

{"jsonrpc":"2.0","id":"server-discover-probe-1","resultType":"complete","result":{"supportedVersions":["2026-07-28"],"capabilities":{"tools":{"listChanged":false}},"instructions":"..."},"_meta":{"io.modelcontextprotocol/serverInfo":{"name":"<server-name>","version":"0.1.0"}}}

Root cause chain (dist line numbers from @modelcontextprotocol/client 2.0.0 / @modelcontextprotocol/core 2.0.0):

  1. JSONRPCResultResponseSchema = z.object({ jsonrpc, id, result }).strict() (@modelcontextprotocol/core/dist/auth-CUe6YdwF.mjs:191-197; mirrored as wireResultResponse(...).strict() in client/dist/src-D_zzAWoS.mjs:3178) rejects the unknown top-level members resultType / _meta.
  2. ProbeWindow.open's transport.onmessage guard (client/dist/index.mjs:2518-2524) resolves pending probes only when isJSONRPCResultResponse(...) || isJSONRPCErrorResponse(...); the rejected message is dropped silently.
  3. On timeout, the stdio classifier returns {kind:'legacy'} (index.mjs:2321-2323), so pin mode throws at index.mjs:2727 — a modern, spec-literal server gets misdiagnosed as legacy.
  4. Related: decodeResult (src-D_zzAWoS.mjs:3920+) runs only on the post-handshake request path (~line 6120), never during the probe, so even a non-dropped envelope would reach classifyResult's validateResult without decoding.

A raw newline-delimited JSON probe sending exactly this request shape succeeds against the same binary — only the SDK path fails.

What did you expect?

Per the 2026-07-28 Server Discovery spec, the probe should decode the response envelope before classification (or tolerate extra top-level members), and a silently-dropped/timed-out probe reply should surface as a diagnosable error rather than being classified as "legacy".

Suggested fixes (any of)
  • Run decodeResult in the probe path before classifyResult.
  • Relax .strict() → passthrough when parsing response envelopes in the probe window.
  • Minimum viable: log when a probe reply fails envelope parsing instead of silently timing out into a misleading legacy verdict.
Code to reproduce
import { Client } from "@modelcontextprotocol/client";
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";

// Any stdio server answering server/discover with the spec-example shape
// (resultType/_meta as top-level siblings of result):
const transport = new StdioClientTransport({ command: "<server-command>" });
const client = new Client(
  { name: "repro", version: "1.0.0" },
  { versionNegotiation: { mode: { pin: "2026-07-28" } }, capabilities: {} },
);
await client.connect(transport); // -> EraNegotiationFailed after ~60s silent timeout
SDK version

@modelcontextprotocol/client 2.0.0, @modelcontextprotocol/core 2.0.0

Area

Client

主要言語
TypeScript
スター
13.6k
フォーク
2.3k
平均マージ
1日 15時間
マージ済み PR(30日)
51

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

modelcontextprotocol/typescript-sdk のほかの issue

modelcontextprotocol/typescript-sdk の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。