Skip to content

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

Description

@tsarlandie-oai

Summary

ClientLifecycleMode::Auto only retries legacy initialize when
server/discover fails with JSON-RPC METHOD_NOT_FOUND (-32601). Existing
production MCP servers communicate unsupported modern discovery through other
recognizable responses, so enabling modern negotiation breaks servers that
previously worked.

Observed against deployed servers

Testing protocol 2026-07-28 against public legacy MCP services reproduced the
problem with:

  • OpenAI documentation, which exposes five tools through legacy initialization.
  • Microsoft Learn, which exposes three tools.
  • DeepWiki, which exposes three tools.

All three worked before modern discovery was enabled. With the modern lifecycle
enabled, startup failed with:

Unsupported protocol version: 2026-07-28

Codex’s existing rmcp 1.8 implementation connected to the same servers by retrying initialize with protocol 2025-06-18.

Current behavior

match discover_startup(...).await {
    Ok(()) => {}
    Err(ClientInitializeError::JsonRpcError(error))
        if error.code == ErrorCode::METHOD_NOT_FOUND =>
    {
        legacy_startup(...).await?;
    }
    Err(error) => return Err(error),
}

Production-shaped HTTP prevalidation responses observed during interoperability
testing include:

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32000,
    "message": "Bad Request: Unsupported protocol version: 2026-07-28 (supported versions: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07)"
  }
}
{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32000,
    "message": "Bad Request: No valid session ID provided"
  }
}

Both occur as initial HTTP 400 responses before a session exists. Other useful
legacy-only signals include correlated unsupported-version errors, discovery
results advertising exclusively historical protocol versions, and initial HTTP
404/405 responses.

Observed versus expected lifecycle

Actual:

→ server/discover, protocol 2026-07-28
← recognizable legacy-only rejection
✗ startup terminates without attempting initialize

Expected:

→ server/discover, protocol 2026-07-28
← recognizable legacy-only rejection
→ initialize, protocol 2025-06-18
← successful initialization
→ notifications/initialized
→ tools/list

Integration tests now reproduce these production-shaped responses and verify
the successful sequence
["server/discover", "initialize", "notifications/initialized"].

Downgrade safety

Fallback must remain conservative. Unrelated response IDs, arbitrary null-ID
errors, unknown or future protocol versions, HTTP 401/403 responses, existing-
session 404 responses, and ordinary modern-server rejections must not trigger
downgrade.

The observed public-server failures and successful reference-client comparison
demonstrate an existing interoperability regression rather than a hypothetical
extension to automatic lifecycle negotiation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is not working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions