The Stateless Evolution: Why I Finally Care About MCP
Legacy MCP made you spend one HTTP request just to be issued a session id, and kept a connection open whether you used it or not. The 2026-07-28 spec makes a tool call a single request with no server-side state, and no, that does not make MCP a fancy word for an API.
Time for a 2025 throwback, because we need to talk about the Model Context Protocol (MCP). I thought it was a massively overrated, bloated spec that caused more problems than it solved, and I never used it day to day because it was, frankly, annoying.
I've changed my mind. Here is what was broken and what got fixed, in the smallest number of words I can manage.
Legacy MCP: two requests and a memory
The older stateful MCP, which I'm going to call legacy MCP, was built around a session. Every server needed its own dedicated, bidirectional connection to the client, and that connection stayed up whether or not you ever called the tool. Three servers meant three open connections doing nothing. Give that agent five sub-agents and you are at 30 stateful connections eviscerating your CPU and triggering security alerts like sispolicyd on macOS.
Calling a single tool took two HTTP requests. The first one exists only to open a session and collect an Mcp-Session-Id, and the second one does the thing you actually wanted.
POST /mcp HTTP/1.1
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {},
"clientInfo": { "name": "my-app", "version": "1.0" }
}
}
POST /mcp HTTP/1.1
Mcp-Session-Id: 1868a90c-3a3f-4f5b
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "search",
"arguments": { "q": "otters" }
}
}
Look at what the server now owes you. It has to hold that session id somewhere, and every later request from that client has to be routed back to the same backend machine that holds it.
Your load balancer stops being a load balancer. It becomes a lookup table, and the two instances you are paying for cannot touch the work. That is the real bill, and you pay it for a tool that sits idle 99% of the time.
The fix: one request
The new spec moves MCP to a stateless core. The same search is one HTTP request, with headers carrying what the session used to carry.
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search",
"arguments": { "q": "otters" },
"_meta": {
"io.modelcontextprotocol/clientInfo": { "name": "my-app", "version": "1.0" }
}
}
}
This is so much cleaner from both a client-side and a server-side implementation perspective. It is also a better fit for building scalable web applications, since you no longer keep server-side state to track session ids, or worry about routing the same session to the same backend machine.
Which is what unlocks the hosting story. Your server can live on serverless and edge infrastructure like AWS Lambda or Cloudflare Workers, where it costs nothing for as long as nobody is calling it. Even Simon Willison, who originally lost interest, says stateless MCP has "recaptured his interest" because it is so much simpler to implement.
They called it MCP 2026-07-28. Not 2.0, not v2, just a date, the way you would name a database migration nobody is meant to read. You cannot say it out loud and you cannot remember it. The thing it describes is still right.
"So MCP is just a fancy word for an API"
This is the take going around on X and under every YouTube video about the new spec, now that the transport is plain request-response, and it is the wrong lesson to walk away with.
An API is written for a developer. A person reads the docs and writes the code that calls it. Every new tool means another integration somebody has to sit down and write.
MCP is written for a model. The server describes itself at runtime: here are my tools, here is what each one does, here are the arguments each one takes. The agent reads that description and works out the call on its own. Nobody writes glue for each tool.
That self-description is the whole product. Point any MCP client at any MCP server and it works, because both ends agreed on how a tool introduces itself. Strip the descriptions out of a normal API and a developer still integrates it from the docs. Strip them out of an MCP server and the agent has nothing left to reason about.
Why this matters for agents
Giving an agent a full shell is fraught with risk, because you cannot list in advance what it might do. A set of self-describing endpoints can be read and refused before anything runs. The agent can only do exactly what those endpoints allow.
That is what turns MCP from a worse version of a CLI into something I would actually put in front of a sensitive system.
The catch: compatibility
The new spec is not backwards compatible, and it cannot be. Legacy clients expect a bound, stateful connection, and you cannot take that away and expect them to carry on.
So we are going to see a lot of "MCP slop": servers that claim to support MCP while sitting on the heavy, legacy standard. For a while, "supports MCP" on a landing page will tell you nothing.
If your company ships one of those servers, this stops being a spec argument and starts being your bill. You are paying to keep machines warm so they can hold sessions nobody is using, and paying again for the sticky routing that makes sure a returning client finds the machine that remembers it. Look back at Fig 1. Two of those three instances are yours, and they are not allowed to answer.
The quieter cost is the one you will not see in a dashboard. New clients send a single request with the protocol version in a header. A legacy server does not know what to do with that. The call fails, and the agent moves on to a tool that answers. That does not look like an outage. It looks like your usage graph going flat while everyone tells you MCP adoption is growing.
Then there is the badge. Once "supports MCP" is on your marketing page, every mismatch arrives as a support ticket, and your team cannot close any of them, because the fix is not a bug in your code. The fix is the transport.
The good news is that the work is smaller than the anxiety around it. Your tool logic does not change at all. What changes is how a call arrives and the fact that you stop storing sessions, which is mostly deletion. We live in the era of LLMs. Point one at the new spec, have it update your bindings in an hour, and delete the session store while you are in there.
If your server still demands a session before it will do anything, that is the work for this quarter.
It's wild to say, but I'm actually excited to play with MCP again. It finally feels like it understands developers instead of trying to be a "god spec" for everything.