docs(SEP-2575): consolidate back-compat rule and broaden stdio fallback#2776
docs(SEP-2575): consolidate back-compat rule and broaden stdio fallback#2776kurtisvg wants to merge 1 commit into
Conversation
Move the per-transport rule for "modern vs legacy server" detection into the Lifecycle: Backward Compatibility section as the single source of truth, and replace the duplicated paragraphs in Transports (stdio + HTTP) and Discover with brief cross-links. For the stdio probe, broaden the fallback condition: legacy servers are not required to answer an unknown pre-initialize method with -32601 (or to respond at all), so the client falls back to initialize on any error other than UnsupportedProtocolVersionError, or on no response within a reasonable timeout. The client also restarts the server process before sending initialize, since the legacy server may be in an undefined state after the unrecognized probe.
| without the requested version. Retry using one of the versions in its | ||
| advertised `supported` list rather than falling back to `initialize`. | ||
| - **Any other error response, or no response within a reasonable timeout**: | ||
| restart the server process and perform the legacy `initialize` handshake |
There was a problem hiding this comment.
Hmm, not sure if this restart is necessary. I'll check what all the official SDKs do. I agree it's probably cleaner to restart, but also very churny and will slow down initialization for any clients that block on initializing all MCP servers.
There was a problem hiding this comment.
ffs, they all handle it except Rust, which exits :(
So I don't think we need to proactively restart any server: they either restart themselves or gracefully handle it.
Rust is a problem though.
More generally, this is an issue because the SDKs don't manage stdio process lifecycle, so it's actually the applications that need to implement this, and I think that's a huge problem. We really cannot expect all applications to implement this backwards compat approach.
I think options are:
- Fix Rust ASAP so that at least new stdio servers work correctly. Accept that it breaks old Rust MCP stdio servers for modern clients.
- Add language to the spec that mandates clients to implement the stdio server respawn and init-fallback logic.
- Think of something else?
I lean towards (1) depending on how many big rust stdio servers are out there.
There was a problem hiding this comment.
Popular rmcp (official Rust SDK) stdio MCP servers
Ranked by GitHub stars. All run rmcp::serve(stdio()).
| Stars | Repo | What it is | stdio |
|---|---|---|---|
| 2,373★ | afnanenayet/diffsitter | tree-sitter AST difftool; ships an optional MCP server (8 AST tools) | default |
| 1,372★ | imhuso/cunzhi (寸止) | MCP server: "don't stop early" popup, per-project memory, code search | stdio-only |
| 891★ | microsoft/wassette | Microsoft — runs WebAssembly Components as MCP tools in a Wasmtime sandbox | default (also http/sse) |
| 740★ | penso/arbor | agentic-coding desktop app; ships a dedicated arbor-mcp server |
default |
| 364★ | nwiizo/tfmcp | Terraform MCP server (plan/apply/state) for Claude Desktop | stdio-only |
| 209★ | gbrigandi/mcp-server-wazuh | Wazuh SIEM data (alerts, agents, vulns) as MCP tools | default |
| 121★ | fabio-rovai/open-ontologies | ontology engineering — 43 onto_* tools over an Oxigraph store |
default |
| 120★ | tidewave-ai/mcp_proxy_rust | presents a stdio MCP server that proxies to remote SSE/HTTP servers | stdio-only |
| 54★ | radiosilence/fastmail-cli | Fastmail JMAP CLI with an mcp subcommand (email tools) |
stdio-only |
| 53★ | jokemanfire/mcp-containerd | containerd CRI/ctr operations as MCP tools | default |
There was a problem hiding this comment.
this is an issue because the SDKs don't manage stdio process lifecycle, so it's actually the applications that need to implement this,
I don't think that's true -- can't the SDK do this are part of the initialization that happens today? The SDK is the one that's starting up the stdio process right?
Do we know what the impact on start up time is? Generally a process spin up is pretty lightweight.
There was a problem hiding this comment.
I don't think that's true -- can't the SDK do this are part of the initialization that happens today? The SDK is the one that's starting up the stdio process right?
Yes, you are right, I got that wrong, so I think it should be ok to do the restart. The only thing I'd change is to not do it unconditionally: only restart if the server actually dies.
Do we know what the impact on start up time is? Generally a process spin up is pretty lightweight.
For nice languages/runtimes, yes, but e.g. playwright (yarn mcp-server-playwright) takes 750ms on average to spawn and respond to initialize. For a simple echo FastMCP server, it's 400ms warm.
|
Adding this to the 2026-07-28 Milestone, to ensure that we track and decided before the final release. |
Move the per-transport rule for "modern vs legacy server" detection into the Lifecycle: Backward Compatibility section as the single source of truth, and replace the duplicated paragraphs in Transports (stdio + HTTP) and Discover with brief cross-links.
For the stdio probe, broaden the fallback condition: legacy servers are not required to answer an unknown pre-initialize method with -32601 (or to respond at all), so the client falls back to initialize on any error other than UnsupportedProtocolVersionError, or on no response within a reasonable timeout. The client also restarts the server process before sending initialize, since the legacy server may be in an undefined state after the unrecognized probe.