Why Stateless MCP Reignited My Interest (and How to Probe It Yourself)
Picture this: you’re watching an AI agent do something useful, and it’s great… right up until you realize the “useful” part involved a shell prompt, a network call, and a few chances for things to go sideways.
That tension has been following Model Context Protocol (MCP) around like a little shadow. MCP, for the uninitiated, is a standard way for LLM-powered agent frameworks to discover and call external tools (web APIs, databases, file accessors, diagram renderers, and so on). For a while, MCP’s main appeal was that it made tool-calling consistent and auditable. Then the ecosystem started to prefer more ad-hoc approaches—because with enough tooling, you can often replicate the value of a protocol with a “terminal + curl” style setup.
Then Tuesday happened: the rollout of MCP 2.0’s stateless specification (the finalized spec dated 2026-07-28). It didn’t just tweak implementation details. It removed a whole class of protocol complexity, and suddenly MCP felt fun to build with again. (claude.com)
The difference that matters: stateful sessions vs stateless requests
Before the stateless revision, “legacy MCP” required a handshake-style session setup. In practice, that meant two separate HTTP requests:
initialize, which negotiated protocol behavior and returned anMcp-Session-Idheader.tools/call, which then referenced that session ID so the server could interpret the call correctly.
That sounds reasonable until you’re deploying at scale. Why does a session ID make life harder? Because it implies server-side state. And server-side state implies you can’t treat each request as independent.
The stateless MCP revision (SEP-2575) removes the initialize/initialized handshake and eliminates the Mcp-Session-Id from the wire format. The spec instead carries what it needs with every request. (modelcontextprotocol.io)
On the wire, that shows up as two big changes:
- The protocol version is sent per request (via
MCP-Protocol-Versionin HTTP transports, or via_metain JSON-RPC payloads). - Client identity/capabilities move into per-request metadata, typically the JSON-RPC
_metaenvelope, so the server doesn’t need to remember anything from earlier calls. (csharp.sdk.modelcontextprotocol.io)
And there’s another practical result: stateful routing disappears. A tool server can sit behind a regular load balancer without worrying that request 17 must land on the same backend instance that request 16 happened to use. The MCP team explicitly frames this as “no sessions” at the protocol layer and highlights simpler deployment patterns plus caching opportunities for things like tools/list. (blog.modelcontextprotocol.io)
What “stateless” looks like in an HTTP request
Even if you never write MCP server code, learning the “shape” of the request helps you reason about the architecture.
With stateless MCP 2026-07-28, a tools/call request includes:
- HTTP headers like
MCP-Protocol-Version - The JSON-RPC message body with
method: tools/call _metafields that include things like client identity (io.modelcontextprotocol/clientInfo) and protocol version information ()
The key mindset shift is this: tool invocation is a self-contained HTTP transaction. No earlier “session initialization” request is required to make the call meaningful.
Why this matters for real agents (and smaller models)
A lot of agent setups still use a shell environment with internet access. That can be powerful—but it’s also a risk magnet. Even when you trust the model, you still have prompt-injection opportunities, accidental data exfiltration, and “oops, ran the wrong command” problems.
Stateless MCP changes the ergonomics around tool access: instead of handing the model a general-purpose execution environment, you expose a curated set of tools. MCP tools also come with structured input/output schemas, which tends to be easier to audit and constrain than free-form command execution.
There’s also a model-performance angle. A smaller model running locally can often drive a well-specified tool surface more reliably than it can drive a shell and reliably infer all the operational details.
Building a developer “X-ray”: mcp-explorer
One of the traps with any spec is that you can’t “feel” it until you poke it. When you’re debugging tool calling, you want to see: what tools exist, what arguments they accept, what the server returns, and which protocol mode you’re actually talking.
That’s where mcp-explorer comes in. The version that really got me interested is the stateless CLI tool by Simon Willison. Its README is refreshingly concrete: it can list tools, inspect tool schemas, and call tools—with explicit support for forcing stateless vs legacy behavior. (github.com)
Here are the core workflows.
1) List tools exposed by a server
mcp-explorer list https://agentic-mermaid.dev/mcp
The CLI defaults to the MCP 2 stateless protocol, and you can force legacy mode with --legacy. (github.com)
2) Inspect one tool and read its schema
mcp-explorer inspect https://agentic-mermaid.dev/mcp render_svg
This is where schema-driven development becomes real. You get nested input/output structure, plus _meta and other execution annotations the server provides. (github.com)
3) Call the tool with arguments
mcp-explorer call \
https://agentic-mermaid.dev/mcp \
render_svg \
-a source 'graph TD; A-->B' \
-a options '{"padding":24}'
For tool debugging, this is the difference between “the model said it worked” and “the request payload matches the declared schema and the response is shaped the way the client expects.” (github.com)
Turning Datasette into an MCP tool server (datasette-mcp)
Exploring MCP servers locally is satisfying, but the bigger moment is when the MCP spec starts showing up inside everyday web apps.
datasette-mcp does exactly that: it adds an MCP endpoint to any Datasette instance, exposing a small, read-only tool set. Datasette itself is an open source way to explore and publish data, and this plugin turns that into an agent-callable interface. ()
Once installed, datasette-mcp adds an HTTP endpoint at /-/mcp and exposes three tools by default: ()
list_databases()— list available databasesget_database_schema(database_name)— return SQL schema detailsexecute_sql(database_name, sql)— execute a single read-only SQL statement and return structured columns/rows plus a truncation indicator
It also enforces Datasette’s permission model and only routes SQL through the same read-only validation and execution path used by Datasette’s own UI. ()
That’s a surprisingly important detail. Tool calling is only as safe as its weakest link. With datasette-mcp, “execute_sql” is constrained to SELECT-style read-only execution and guarded by visibility/permission checks for the current Datasette actor. ()
So what does this unlock? A chat tool or agent can use MCP-style tool calls to run multi-step analysis:
- inspect schema
- craft a query
- run it
- then summarize results
That’s the exact flow many people end up implementing manually with bespoke integrations. MCP lets those steps become reusable and standardized across agent frameworks.
The quiet win: fewer moving parts
Stateless MCP doesn’t just reduce server complexity. It reduces the cognitive overhead of building and operating tool services.
When each request carries the protocol version and the client metadata, there’s less “session plumbing” to debug and less risk of subtle deployment issues (like routing affinity problems). The spec explicitly positions statelessness as enabling simpler load balancer setups and improved traceability. (blog.modelcontextprotocol.io)
And for people who learn by building, it’s hard not to get enthusiastic. Tool calling stops feeling like a ceremony around a session ID and starts feeling like a normal HTTP API design—with better structure around schemas and metadata.
Closing thought
Stateless MCP recaptured my interest because it made the protocol feel less like infrastructure glue and more like something you can reason about locally, deploy confidently, and audit cleanly.
Even if you never touch the wire format directly, the idea lands: every tool call is self-contained. That single shift changes how MCP scales, how tooling can inspect it, and how agents can safely explore real systems without being handed the keys to a shell.
Comments (0)
No comments yet. Be the first to respond!
Leave a Comment
Your comment will be visible after review.