llm

Why Stateless MCP Reignited My Interest (and How to Probe It Yourself)

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:

  1. initialize, which negotiated protocol behavior and returned an Mcp-Session-Id header.
  2. 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-Version in HTTP transports, or via _meta in JSON-RPC payloads).
  • Client identity/capabilities move into per-request metadata, typically the JSON-RPC _meta envelope, 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
  • _meta fields 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 databases
  • get_database_schema(database_name) — return SQL schema details
  • execute_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.

ahsan

ahsan

Hello! I am Mr Ahsan, the writer of the Website. I am from Netherland. I like to write about technology and the news around it.

Comments (0)

No comments yet. Be the first to respond!

Leave a Comment

Your comment will be visible after review.