Describe the bug
Copilot CLI 1.0.81-1 fails MCP initialization against a stdio server using the Python MCP SDK 2.0.0 dual-era runner.
The CLI opens the connection with a modern server/discover probe whose _meta declares io.modelcontextprotocol/protocolVersion: 2026-07-28. The server replies with a valid successful DiscoverResult (resultType: "complete", supportedVersions: ["2026-07-28"]). The CLI then sends a legacy initialize requesting 2025-11-25 on that same connection, and the server rejects it with -32022.
Per the stdio backward-compatibility rules, a successful DiscoverResult identifies a modern server; legacy initialize fallback is only for a non-modern error or timeout. The CLI declares two protocol eras on one connection.
Related to #4370, but exercises the other probe outcome: #4370 concerns fallback after a non-modern error; this occurs after a successful modern DiscoverResult.
Affected version
1.0.81-1
Verified working on 1.0.80, 1.0.80-1 and 1.0.81-0 with the same server and config. 1.0.81-0 (works) and 1.0.81-1 (fails) were both run via node index.js from the same cache layout, so the difference is the version, not the invocation path. 1.0.81-1 also fails when run as the native binary.
Steps to reproduce the behavior
- Configure a stdio MCP server that implements
server/discover. Reproduced with scrapling 0.4.14 (scrapling mcp), resolved dependency mcp==2.0.0.
- Run Copilot CLI 1.0.81-1.
- The server's tools are missing. The CLI log shows:
failed to initialize MCP client: JSON-RPC error: -32022: connection is serving the 2026-07-28 protocol; the initialize handshake is not accepted({"supported":["2026-07-28"],"requested":"2025-11-25"})
Expected behavior
After a successful DiscoverResult, the CLI should select a mutually supported advertised version and continue in that era without sending legacy initialize on that connection. Legacy initialize fallback should occur only when the probe returns a non-modern error or times out.
Additional context
Wire capture on 1.0.81-1 (abridged — capabilities and instructions elided, marked "..."):
Server side, the Python SDK locks the connection's era from the first message: a non-initialize opening request carrying the reserved io.modelcontextprotocol/protocolVersion key selects the modern runner, which then rejects initialize (mcp/server/runner.py).
Environment: Linux x64, Node v24.15.0, server scrapling 0.4.14 on mcp 2.0.0.
Describe the bug
Copilot CLI 1.0.81-1 fails MCP initialization against a stdio server using the Python MCP SDK 2.0.0 dual-era runner.
The CLI opens the connection with a modern
server/discoverprobe whose_metadeclaresio.modelcontextprotocol/protocolVersion: 2026-07-28. The server replies with a valid successfulDiscoverResult(resultType: "complete",supportedVersions: ["2026-07-28"]). The CLI then sends a legacyinitializerequesting2025-11-25on that same connection, and the server rejects it with-32022.Per the stdio backward-compatibility rules, a successful
DiscoverResultidentifies a modern server; legacyinitializefallback is only for a non-modern error or timeout. The CLI declares two protocol eras on one connection.Related to #4370, but exercises the other probe outcome: #4370 concerns fallback after a non-modern error; this occurs after a successful modern
DiscoverResult.Affected version
1.0.81-1
Verified working on 1.0.80, 1.0.80-1 and 1.0.81-0 with the same server and config. 1.0.81-0 (works) and 1.0.81-1 (fails) were both run via
node index.jsfrom the same cache layout, so the difference is the version, not the invocation path. 1.0.81-1 also fails when run as the native binary.Steps to reproduce the behavior
server/discover. Reproduced withscrapling 0.4.14(scrapling mcp), resolved dependencymcp==2.0.0.failed to initialize MCP client: JSON-RPC error: -32022: connection is serving the 2026-07-28 protocol; the initialize handshake is not accepted({"supported":["2026-07-28"],"requested":"2025-11-25"})Expected behavior
After a successful
DiscoverResult, the CLI should select a mutually supported advertised version and continue in that era without sending legacyinitializeon that connection. Legacyinitializefallback should occur only when the probe returns a non-modern error or times out.Additional context
Wire capture on 1.0.81-1 (abridged —
capabilitiesandinstructionselided, marked"..."):Server side, the Python SDK locks the connection's era from the first message: a non-
initializeopening request carrying the reservedio.modelcontextprotocol/protocolVersionkey selects the modern runner, which then rejectsinitialize(mcp/server/runner.py).Environment: Linux x64, Node v24.15.0, server
scrapling 0.4.14onmcp 2.0.0.