Skip to content

Fix stdio legacy-fallback rule and add a compatibility matrix#2844

Merged
CaitieM20 merged 6 commits into
mainfrom
fix/spec-improvements
Jun 3, 2026
Merged

Fix stdio legacy-fallback rule and add a compatibility matrix#2844
CaitieM20 merged 6 commits into
mainfrom
fix/spec-improvements

Conversation

@dsp-ant

@dsp-ant dsp-ant commented Jun 2, 2026

Copy link
Copy Markdown
Member

Motivation and Context

The draft spec removed the initialize handshake (SEP-2575). For stdio, the backward-compatibility text told clients to fall back to the legacy initialize handshake only when a server/discover probe returns Method not found (-32601).

Legacy protocol revisions never specified how a server responds to an unknown request received before initialize, and implementations differ: the TypeScript SDK returns -32601, the Python SDK rejects the request as invalid (-32602, the unknown method fails request validation before dispatch), and some servers do not respond at all. A fallback keyed to -32601 therefore fails against real legacy servers.

Changes

  • Rewrite the stdio fallback rule: any error that is not a recognized modern error, or no response within a reasonable timeout, indicates a legacy server. Keying the fallback to a single error code is now forbidden.
  • Add guidance to cache the era determination per server.
  • Recommend probing with server/discover on stdio even for modern-only clients. Some legacy servers do not validate that requests arrive after initialize and would process era-ambiguous methods (such as tools/call) under legacy semantics, silently ignoring the declared protocol version; probing turns this into a deterministic failure.
  • Add a compatibility matrix for implementors covering modern/dual-era/legacy client and server combinations, including previously unspecified cases: legacy client against a modern-only server, and how a dual-era server selects semantics.
  • Align the duplicated backward-compatibility text in transports and server/discover.

The branch also carries two small pre-existing doc fixes (deprecated-feature mentions, architecture links).

How was this tested?

npm run prep (schema generation, format check, link check, SEP check) passes.

dsp-ant added 5 commits June 2, 2026 13:49
The stdio backward-compatibility probe told clients to fall back to the
legacy initialize handshake only on Method not found (-32601). Legacy
protocol revisions never specified how a server responds to an unknown
request received before initialize, and implementations vary: some return
-32601, others reject the request as invalid (-32602), and some do not
respond at all. A fallback keyed to -32601 therefore fails against real
legacy servers.

- Rewrite the stdio fallback rule: any error that is not a recognized
  modern error, or no response within a timeout, indicates a legacy
  server. Forbid keying the fallback to a single error code.
- Add guidance to cache the era determination per server.
- Recommend probing on stdio even for modern-only clients, since legacy
  servers may process era-ambiguous methods under legacy semantics.
- Add a compatibility matrix covering modern/dual-era/legacy client and
  server combinations, including the previously unspecified cases
  (legacy client vs modern-only server, dual-era server semantics).
- Align the duplicated text in transports.mdx and discover.mdx.
@dsp-ant dsp-ant requested a review from a team as a code owner June 2, 2026 16:39
@mintlify

mintlify Bot commented Jun 2, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
mcp-staging 🟢 Ready View Preview Jun 2, 2026, 4:43 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@mintlify

mintlify Bot commented Jun 2, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
mcp 🟢 Ready View Preview Jun 2, 2026, 4:48 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@Agent-Hellboy

Copy link
Copy Markdown

Hi @dsp-ant, this should be addressed through #2841

* Restructure draft transport documentation

The transports page presented MRTR, subscription streams, and the
request-metadata model as Streamable HTTP features, while the stdio
section was silent about them. The split mirrored the old transport
model, where each transport had genuinely different capabilities. In the
current draft, protocol semantics are identical on every transport; only
the binding differs.

- Split basic/transports.mdx into a transports/ section:
  - index.mdx: transport-independent overview — the client-initiated
    message flow, MRTR and subscriptions/listen as the only
    server-to-client mechanisms on any transport, the per-request
    metadata model, and what a binding must define.
  - stdio.mdx and streamable-http.mdx: per-transport bindings.
- Move MRTR from basic/utilities/ to basic/transports/, since it is part
  of the transport message flow rather than an optional utility. Add a
  redirect for the old URL.
- Remove leftovers from the bidirectional era: clients no longer send
  JSON-RPC responses on either transport, and the stdio page now states
  explicitly that servers must not write JSON-RPC requests to stdout.
- Update navigation and all draft-internal links.

* Fix typos in MRTR security requirements

* Note that stdio framing generalizes to any byte stream

The stdio wire format (newline-delimited JSON-RPC over a reliable
bidirectional byte stream) is not specific to standard streams; only the
process-lifecycle rules are. State this on the stdio page and recommend
that custom stream-based transports (Unix domain sockets, TCP) reuse the
stdio framing instead of defining new framing.

* State the transport message flow declaratively

* Trim request metadata wording in transport overview

* Replace em-dashes with plain punctuation in new spec text

* Make message-direction rules prescriptive in transport bindings

* Clarify stdio receiving-messages section

* Deduplicate backward-compatibility text across lifecycle and transports

The era-detection mechanics were spelled out three times: in lifecycle,
in the transport binding pages, and partially in server/discover. The
copies had already drifted once.

- Binding pages are now canonical for detection mechanics. The stdio
  page absorbs the detail previously only in lifecycle (preferred
  version in _meta, three probe outcomes, supportedVersions selection).
- Lifecycle keeps the transport-independent content: the era model,
  caching guidance, and the compatibility matrix. It links to the
  binding pages for mechanics.
- server/discover refers to the stdio binding page instead of restating
  the fallback rules.

* Reorder lifecycle page: scope first, transition material last

- Open with a scope statement and a short overview instead of normative
  rules.
- Add a terminology section defining modern, legacy, and dual-era before
  first use (previously defined inside the compatibility-matrix intro).
- Group the statelessness requirements under their own heading; split
  compound bullets and demote the connection-identity rationale to a
  note.
- Move extension negotiation before backward compatibility, so core
  protocol material precedes transition material.
- Promote backward compatibility to a top-level section (anchor
  unchanged).

* Reorder transport overview: scope first, transition material last

- Open with a scope statement instead of the UTF-8 encoding rule; the
  encoding requirement moves to the top of Message Flow.
- Move Custom Transports before Backward Compatibility, so requirements
  for new bindings precede transition material.

* Add message patterns page; keep MRTR under utilities

Review feedback on the transport restructure: MRTR describes message
flow and contents, like subscriptions and progress, which live under
utilities. Moving only MRTR under transports was inconsistent. The
underlying gap is that no page defined the core message patterns every
transport carries.

- Add basic/patterns.mdx (Message Patterns), after Lifecycle in the nav.
  It defines the client-initiated model and the three core patterns
  (request/response, multi round-trip requests, subscribe and notify),
  each with a sequence diagram and a link to its detailed page, and
  states that new patterns are added there without transport changes.
- Move MRTR back to basic/utilities/ and drop the redirect.
- Slim the transports overview to binding concerns: message delivery
  requirements, metadata carriage, cancellation, custom transports, and
  backward compatibility. It links to the patterns page for flow
  semantics.

* update basic/index.mdx to reference message patterns page

* add message patterns

* Align pattern names between overview and patterns page

Use the same pattern names and order in the base-protocol overview as on
the patterns page, and link each pattern to its section. Rename the
Request/Response heading to Request and Response so its anchor does not
contain an encoded slash.

* Title the transports index page Overview, matching other group index pages

* Rename Lifecycle to Versioning and Compatibility

The protocol is stateless: there is no initialize/operate/shutdown
sequence left to describe. Initialization became per-request metadata,
and shutdown is a transport-binding concern documented on the binding
pages. The remaining content of the lifecycle page has one theme: how
two implementations agree on what they are speaking.

- Rename basic/lifecycle.mdx to basic/versioning.mdx, titled
  "Versioning and Compatibility", covering version negotiation,
  extension negotiation, and backward compatibility. Add a redirect.
- Move the statelessness section to the base-protocol overview, where
  the execution model belongs.
- Update navigation and all draft-internal links.

---------

Co-authored-by: Caitie McCaffrey <caitiem20@github.com>
@CaitieM20 CaitieM20 merged commit 1b08d18 into main Jun 3, 2026
9 checks passed
@CaitieM20 CaitieM20 deleted the fix/spec-improvements branch June 3, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants