| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
Redesigned per your feedback. Replaced the Err(_) + modern-code carve-out Three calls I'd like your input on:
|
Sorry, something went wrong.
|
Rewrote this to classify inside discover_startup instead of on the error The three open review comments are addressed by the rewrite:
|
Sorry, something went wrong.
`ClientLifecycleMode::Auto` only fell back from `server/discover` on `-32601`, so legacy servers that reject the probe with other codes (`-32600`, `-32602`, implementation-defined errors) failed to connect even though `initialize` would have succeeded. The previous attempt (indicates_legacy_server) classified the failure after the fact by reverse-engineering the error type. This rewrite moves the classification into `discover_startup` itself, where the full context (request id, response correlation, transport state) is still available. `discover_startup` now returns `DiscoverOutcome`: `Modern` on success, `Legacy(error)` when the probe received a complete, correlated JSON-RPC error whose code is not a modern-era rejection. Every other failure becomes `Err`, so `Auto` simply matches the outcome — no methods on `ClientInitializeError`, no downcast, no transport-specific types leaking into the generic lifecycle layer. Additional fixes that fall out naturally: - Response correlation is now checked in `expect_response` for both success and error branches. Previously error responses skipped id correlation entirely. A new `UncorrelatedErrorResponse` variant surfaces responses that cannot be tied to the request. - When both discover and the legacy fallback fail, a `LegacyFallbackFailed` compound error preserves both phases instead of discarding the discover error. Fixes modelcontextprotocol#1040.
| Back | FazBrowse Home | New Git URL |
Fixes #1040.
Problem
ClientLifecycleMode::Auto only fell back to the legacy initialize
handshake when server/discover failed with -32601 (METHOD_NOT_FOUND).
Legacy servers commonly reject an unknown pre-initialize request with other
implementation-defined errors (-32600, -32602, session-middleware errors),
so Auto broke against servers that previously worked.
Approach
Classification happens inside discover_startup, where the full context
(request id, response correlation, transport state) is still available — not
after the fact on ClientInitializeError, where that context is gone.
discover_startup returns a DiscoverOutcome:
whose code is not a modern-era rejection. The transport delivered a full
response and is ready for the next request, so a legacy initialize can
follow on the same connection.
modern rejection, client-side state). Surfaced, not retried.
Auto simply matches the outcome. No methods on ClientInitializeError, no
downcast, no transport-specific types leaking into the lifecycle layer.
Two additional fixes that fall out naturally:
Response correlation: expect_response now checks the request id on
both success and error responses. Previously error responses skipped id
correlation entirely. A new UncorrelatedErrorResponse variant surfaces
responses that cannot be tied to the request.
Fallback failure preservation: when both discover and the legacy
fallback fail, a LegacyFallbackFailed compound error preserves both
phases instead of discarding the discover error.
A silently legacy server that ignores the probe and hangs expect_response
is a separate concern (needs a discover timeout); tracked in #1142.
Tests
The existing lifecycle tests verify the behavior end-to-end: -32601,
-32600, and -32602 discover responses trigger fallback; -32021 and
-32020 are surfaced. The client-initialization test was fixed to echo the
real request id (it previously hardcoded 1 against an id provider that
starts at 0, which only worked because error responses were never
correlated).
Scope
Non-JSON HTTP responses (e.g. a legacy server returning a plain-text 422) are
not covered by this PR. Recognizing them as a legacy signal requires the
transport layer to carry a structured HTTP-status signal across the transport
boundary, which is an architectural change best discussed separately.