Skip to content

fix(client): fall back from discover for any non-modern error - #1133

Open
ip2a wants to merge 1 commit into
modelcontextprotocol:mainfrom
ip2a:fix/auto-lifecycle-fallback
Open

fix(client): fall back from discover for any non-modern error#1133
ip2a wants to merge 1 commit into
modelcontextprotocol:mainfrom
ip2a:fix/auto-lifecycle-fallback

Conversation

@ip2a

@ip2a ip2a commented Aug 5, 2026

Copy link
Copy Markdown

ClientLifecycleMode::Auto only fell back to the legacy initialize handshake when server/discover failed with JSON-RPC -32601 (METHOD_NOT_FOUND). Deployed legacy servers commonly reject an unknown pre-initialize request with other implementation-defined errors (-32600, -32602) or with session-middleware errors before method dispatch, so Auto broke against servers that previously worked.

Per the 2026-07-28 backward-compatibility guidance, the fallback MUST NOT be keyed to one specific error code: the client falls back to initialize for every discover failure that does not positively identify a modern server. The recognized modern failures — a negotiated version mismatch, a missing-required-capability error, or a header validation failure — are surfaced instead of triggering a fallback.

Fixes #1040.

Motivation and Context

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

`ClientLifecycleMode::Auto` only fell back to the legacy `initialize`
handshake when `server/discover` failed with JSON-RPC `-32601`
(`METHOD_NOT_FOUND`). Deployed legacy servers commonly reject an unknown
pre-`initialize` request with other implementation-defined errors
(`-32600`, `-32602`) or with session-middleware errors before method
dispatch, so Auto broke against servers that previously worked.

Per the 2026-07-28 backward-compatibility guidance, the fallback MUST
NOT be keyed to one specific error code: the client falls back to
`initialize` for every discover failure that does not positively
identify a modern server. The recognized modern failures — a negotiated
version mismatch, a missing-required-capability error, or a header
validation failure — are surfaced instead of triggering a fallback.

Fixes modelcontextprotocol#1040.
@ip2a
ip2a requested a review from a team as a code owner August 5, 2026 07:44
@github-actions github-actions Bot added T-test Testing related changes T-core Core library changes T-service Service layer changes labels Aug 5, 2026
// Fall back to the legacy `initialize` handshake. The 2026-07-28
// backward-compatibility guidance is explicit that this MUST NOT
// be keyed to one specific error code.
Err(_) => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Err(_) also catches 401 and 403, as well as client-side failures like NoPreferredProtocolVersion. Neither indicates that the peer is legacy, but Auto now attempts initialize and may hide the original actionable error.

// must not trigger a legacy fallback. Surface the error.
Err(error) if is_modern_server_error(&error) => return Err(error),
// Any other outcome — `-32601`, `-32602`, `-32600`, another
// implementation-defined error, or no response at all — means

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discover_startup waits in expect_response until a message comes in or the transport closes. So, if a legacy server is open but silently ignores server/discover, it never reaches this branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-core Core library changes T-service Service layer changes T-test Testing related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ClientLifecycleMode::Auto does not fall back for deployed legacy-server responses

2 participants