“The handshake and the session are gone. There’s no initialize, no Mcp-Session-Id, no ping. Every request carries its own protocol version and client capabilities in _meta, HTTP is POST-only, and server/discover is there if a client wants to ask first. And servers no longer send requests: a tool that needs the user returns input_required, and the client retries the same call with the answer.
Whether my server changes depends on three things. If it’s plain functions on the v2 SDK, it’s a two-line rename and the SDK serves both eras on one endpoint. If a tool asks the user mid-call, that becomes a resolver that returns a question. If I kept anything keyed by the session id, it moves to a handle or a store every replica can reach.
Then the part people miss: a stateless protocol isn’t a stateless application. The sealed requestState needs one key on every replica, and retries replay, so writes need idempotency keys.
And I don’t flip clients to modern-only. Nothing falls forward, so I serve both eras until the inventory says no legacy client is left.”