A dual-era client sends a modern request to an HTTP MCP server and receives 400 Bad Request. What should the client do next to determine whether to fall back to the legacy initialize handshake?
Select an answer to reveal the explanation.
Short Explanation
A 400 is a shrug that needs reading: you look at what the server actually said before deciding it's from the old era. The trap is falling back on the status code alone, since modern servers use 400 too.
Full Explanation
The Streamable HTTP backward-compatibility rules let a client that supports both modern and legacy versions detect the server's era by attempting a modern request first. On 400 Bad Request, the client should inspect the response body before falling back, because modern servers also return 400 for UnsupportedProtocolVersionError, MissingRequiredClientCapabilityError and header-validation failures. If the body contains a recognized modern JSON-RPC error, the server speaks a modern version, so the client retries with one of the advertised supported versions or corrects the request instead of falling back. If the body is empty or is not a recognized modern error, the client falls back to initialize and continues with the legacy version. Falling back on any 400 would wrongly downgrade conversations with modern servers that merely rejected a version or a missing header. Blind retries waste time, because the same request will draw the same deterministic error. Switching straight to HTTP+SSE skips the initialize fallback; the old transport is tried only when the POST fails with 400, 404 or 405 and no recognized modern error appears, and then only by issuing a GET that returns an endpoint event. Exam caveat: on stdio the probe is server/discover, but the same recognized-modern-error rule applies. Operational check: log the error code from each 400 body during era detection.