Follow the stateless request lifecycle
See how every request carries its own version and capabilities, and how clients discover servers.
- Explain what the stateless core of the 2026-07-28 revision means
- Fill in the required
_metafields of a request - Negotiate a protocol version and use
server/discover
MCP revisions are named by date. In the current revision, 2026-07-28, MCP became a stateless request/response protocol. Earlier revisions (2025-11-25 and before) opened a connection with an initialize handshake and kept a session; now there is no handshake and no protocol-level session.
Instead, every request carries what the server needs in its params._meta:
io.modelcontextprotocol/protocolVersion- required, e.g."2026-07-28",io.modelcontextprotocol/clientCapabilities- required, what this client supports,io.modelcontextprotocol/clientInfo- recommended, the client’s name and version.
A request missing a required field is rejected with -32602. Because each request is self-contained, any server instance behind a plain load balancer can answer it - no sticky sessions or shared session store needed.
Try it
Up to 15 XPA stateless conversation
Step through a host listing a server’s tools and calling one. Before each message appears, predict it. Notice that every request repeats the _meta fields.
Predict: What does a client send first if it wants to learn a server’s versions and capabilities in one go?
Choosing a version
Clients and servers may support several revisions. If a server does not support the version a request declares, it replies with an UnsupportedProtocolVersionError (-32022) listing the versions it does support, and the client retries with a common one. Version strings are dates in YYYY-MM-DD form, so the newest common version is simply the largest shared string.
1client = ["2025-11-25", "2026-07-28"]
2server = ["2025-06-18", "2025-11-25"]
3common = set(client) & set(server)
4print(max(common) if common else "no common version")2025-11-25
Key takeaways
The current revision (2026-07-28) is stateless: no handshake, no session.
Every request carries
protocolVersionandclientCapabilities(required) andclientInfoin_meta.server/discoverreturns versions, capabilities and identity; unsupported versions get-32022with the supported list.
Lesson quiz
7 questions · pass with 5 correct · up to 50 XP
Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.
Practice: build an MCP server
Write Python in the editor and run it against sample inputs. Python runs locally in your browser using a WebAssembly runtime.
Negotiate a protocol version
The first line lists the client’s supported versions and the second the server’s, separated by spaces. Print the newest version both support, or no common version.
- Older shared version
- Both current
- Nothing shared
Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.
Validate request metadata
Read one JSON-RPC request. Print ok if its params._meta contains both required keys - io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities. Otherwise print -32602 missing: followed by the missing key names, comma-separated, in that order.
- Complete
- No capabilities
- No params at all
Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.
Questions about this lesson
Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.
Loading posts…