I’m in the middle of setting up a Mac Mini as a home server, and the plan is simple. It runs my MCP servers, and every machine I own connects to it. One install. One config. One place where the tokens live.
Before this, each machine ran its own copy of the same servers, with its own config file and its own API tokens in plain text. Fix one and the others stay wrong until you remember them. Annoying when it’s just me. A genuine liability across a team.

Stateless MCP shipped in the 2026-07-28 specification revision, and it changes the economics of exactly this. Not because remote MCP servers suddenly became possible โ they were always possible โ but because running one well just got dramatically cheaper. Let me walk through what changed, what it means for how you split work between local and remote, and where the honest tradeoffs sit.
What is stateless MCP?
Stateless MCP is a protocol design where every request carries all the information the server needs to process it, with no session state held between calls. The
initializehandshake and session IDs are gone, so any server instance can handle any request from any client at any time.
This landed through SEP-2575, which reached Final status and was folded into the 2026-07-28 revision. It’s a hard break, not an opt-in mode.
The word “stateless” trips people up, so let me be precise about it. It doesn’t mean your MCP server can’t have state โ it means the protocol stops holding it for you. If your server needs to remember something across calls, it now mints an explicit handle and hands it back as an ordinary tool argument. State moved from being invisible protocol machinery to being something you design on purpose.
What actually changed on 28 July 2026
The old model required a three-way handshake before anything useful happened. Client sends capabilities, server replies with its own plus a session ID, client confirms. From then on, that session ID was the thread holding the conversation together โ and it was pinned to whichever server instance answered first.
Here’s the before and after:
| Thing | Before (2025-11-25) | After (2026-07-28) |
|---|---|---|
| Setup | initialize handshake required | Removed โ every request stands alone |
| Session tracking | Mcp-Session-Id header | Removed entirely |
| Protocol version | Negotiated once | Sent per request in _meta |
| Client capabilities | Declared once at init | Declared on every single request |
| Discovery | Part of the handshake | New server/discover RPC, mandatory |
| Server-initiated calls | Sampling, elicitation, roots/list | Replaced by Multi Round-Trip Requests |
| Dropped connection | Resume with Last-Event-ID | Resumability removed โ reissue the request |
| Log level | logging/setLevel RPC | Per request via _meta |
That per-requestย _metaย object now carriesย io.modelcontextprotocol/protocolVersion,ย io.modelcontextprotocol/clientInfo, andย io.modelcontextprotocol/clientCapabilities. Your payloads get a little fatter. In exchange, any instance can serve any request without coordination.
A stateless MCP server is an ordinary HTTP service, and can be deployed like one. Round-robin load balancing works. Autoscaling works. Serverless works. There’s no Redis session store to run and no sticky routing rules to maintain. If you’ve deployed anything behind a load balancer before โ the same instincts that apply to choosing between Docker and Podman for your container runtime apply here โ you already know how to run this.
Now, that’s the framing every write-up on this leads with, and it’s correct. But it’s not the part that made me change how I work.
Suggested Reading: What is Claude Cowork and Why you should care?
The real problem was never the protocol โ it was twelve laptops

Think about what a local MCP server actually is. It’s an npm or pip package, installed on a developer’s machine, configured in a JSON file, holding whatever credentials it needs to reach the service it wraps.
Now count the copies. Five developers means five installs, five config files, five sets of tokens sitting in plain text in a home directory. I’ve written before about protecting secrets from AI coding tools, and this is the same problem wearing a different hat โ except here you’ve deliberately handed the credentials out, one copy per person.
Two things go wrong, and both are quiet.
Nobody updates them. I went months without touching mine, and I write about this stuff for a living. So when a server ships a fix โ a tightened tool description, a patched injection surface, a corrected permission scope โ it reaches exactly the people who happen to reinstall. You have no inventory of who is running what. You have no way to find out.
The blast radius scales with headcount. Every laptop is a place a token can leak from. Offboard someone and you’re now trusting a checklist to remember which tokens lived on their machine.
Centralising MCP servers turns patching from a broadcast into a deploy. One instance means one place to fix a vulnerable tool, and the fix applies to everyone the moment it ships. This is the argument that convinced me, and it has nothing to do with scaling โ it’s a maintenance and security argument that scaling finally made affordable.
There’s a neat detail in the new spec that makes this concrete. tools/list, prompts/list, and resources/read now return a CacheableResult carrying ttlMs and cacheScope. Clients cache tool definitions and honour that TTL. So “how fast does my fix reach the team” stops being a hope and becomes a number you set. Given that poisoned tool descriptions are a real attack class, being able to correct one and know it propagates within a defined window is worth a lot.
How a shared remote server changes the security picture
Here’s where it gets genuinely interesting, and where the stateless change stops being incidental.
Because there’s no handshake to authenticate once, every request must now be independently authenticated. The spec is blunt about it โ authorization must be included in every HTTP request, and servers must validate that the token was issued specifically for them as the intended audience.
That sounds like more work. Architecturally, it’s a gift. Under the old session model, a session was implicitly one user pinned to one instance, so multi-tenancy fought the protocol. Now identity travels with each call, and one deployment serving twenty people with twenty distinct identities is the natural shape rather than a workaround.
Which brings up the question you have to answer before you deploy anything: whose credentials does the server use?
Shared service account. One credential for everyone. Simple to set up, and it destroys attribution completely โ every action downstream looks like “the MCP server did it.” For anything touching production or customer data, I’d rule this out.
Per-user OAuth. Each person authenticates to the MCP server, which brokers their downstream access. Audit trails survive. Least privilege survives. More setup, and historically the reason teams gave up and used a service account.
Enterprise-Managed Authorization. This is the one I didn’t expect. There’s an official MCP authorization extension, stabilised in June 2026, built on the Identity Assertion JWT Authorization Grant. During SSO the client exchanges the user’s identity token for a grant scoped to a specific target server, which it then trades for an access token. In practice that means access is provisioned centrally through your identity provider, users get connected servers on first login with no per-server OAuth prompt, and audit logs land in one place. Okta was the first identity provider supported at launch.
It’s an extension rather than core spec, so support will be uneven for a while. But it means the shared-token compromise is no longer the only realistic option for a team, which it more or less was before.
Suggested Reading: Best Computer for AI Workload in 2026 – Best Laptop and Desktop
The deprecations tell you where MCP is heading
This is the part most coverage skips, and I think it’s the most revealing thing in the whole revision.
Roots, Sampling, and Logging are all now formally deprecated. Look at the suggested migrations: pass directories and files via tool parameters or resource URIs instead of Roots. Call LLM provider APIs directly instead of Sampling. Log to stderr or OpenTelemetry instead of the Logging feature.
Every single one of those was a case where the server reached back into the client’s machine to borrow something โ its filesystem view, its model access, its log channel. All three are on the way out, with a minimum twelve-month deprecation window under the new feature lifecycle policy.
So the direction isn’t subtle. MCP is being redesigned around the assumption that the server is remote and the client could be anywhere. Statelessness is the scaffolding; the deprecations are the intent. If you’re planning tooling for the next two years, plan for a protocol where the server does not get to reach into the client’s environment.
What should stay local, and what shouldn’t
None of this means everything moves. The split I’d draw:
Keep it local when the server genuinely needs the machine โ filesystem access, git operations, a local database, anything bound to the developer’s working directory.
Move it remote when the server wraps something the whole team already shares โ Jira, internal APIs, analytics, a documentation index, a vector store. If the underlying resource lives on the network, running twelve copies of a client to reach it never made much sense anyway.
The same reasoning shows up whenever you build retrieval systems โ the local versus hosted decision in a RAG setup turns on exactly this question of who else needs the thing.
Your agent connects to both kinds at once, so this isn’t an either/or. The useful exercise is going through your current config and asking which of these has any reason to be on my machine? That’s the audit I ran before setting up the Mac Mini, and most of my servers had no business being on a laptop at all.
Worth saying plainly: remote doesn’t have to mean cloud. A box on your own network counts. My Mac Mini is a remote MCP host in every sense that matters โ my laptop talks to it over HTTP, any of my machines can hit it, and there’s exactly one copy of each server to maintain. You get the consolidation benefit without handing your tokens to a third party or paying for compute you already own. For a solo developer or a small team on the same network, I think that’s the most sensible starting point by some distance.
If you’re still setting up your first few, my guide to setting up MCP servers covers the fundamentals before you worry about where they live.
The tradeoffs nobody’s putting in the headline
I’d be selling you something if I stopped here, so let me be straight about what you give up.
You’re building a credential vault. A shared MCP server holding downstream tokens for the whole team is a concentrated target. Local sprawl is genuinely bad, but it does distribute blast radius. You’re trading many small risks for one large one, and that only works if the one large one is properly defended.
Confused deputy is now your problem. A server holding credentials for many users must guarantee that one person’s request can’t reach another’s data. The spec addresses part of this โ servers must only accept tokens valid for their own resources, and must not accept or pass on any others โ but your own tool logic is where this actually gets won or lost.
Nothing resumes any more. SSE stream resumability is gone. A dropped connection means the in-flight request is lost and the client reissues it with a new ID. Long-running work needs the tasks extension now, which polls via tasks/get rather than blocking.
Round trips got chattier. Under MRTR, a server needing extra input returns a result with resultType: "input_required", and the client answers by retrying the whole original request. Cleaner to reason about, but it’s more traffic than a mid-call callback was.
And it’s early. This spec is days old and the change is backward-incompatible. SDK and client support will be patchy for months. A server can implement both the old initialize path and the new stateless RPCs during the transition, which is the sane way through โ but don’t plan a migration on the assumption that your whole toolchain is ready.
Suggested Reading: Best Mechanical Keyboards for Gamers or Home Office
What I’d do right now

- Inventory what you’re running. List every MCP server in your config and note which ones touch your local machine and which ones just reach a network service.
- Pick one candidate and a host. Take the most obviously shared server on that list โ usually something wrapping an internal API โ and treat it as the pilot. A spare machine on your own network is a perfectly good first host; you don’t need a cloud account to start.
- Decide the credential model before you deploy. Per-user OAuth or Enterprise-Managed Authorization. Not a shared service account, unless the downstream system genuinely has nothing worth protecting.
- Test it behind two instances. If it works round-robin across two containers with no sticky routing, it’s genuinely stateless.
- Set your
ttlMsdeliberately. That number is how fast a fix reaches your team. Pick it, don’t inherit it. - Leave the local ones alone. Filesystem and git servers belong on the machine. Moving them remote solves nothing and breaks plenty.
I don’t think this is a migrate-everything-this-quarter moment. I do think the shape of the protocol has changed permanently, and the deprecation list makes that plain enough that it’s worth designing for now rather than being surprised in a year.
FAQ about Stateless MCP
Does stateless MCP break my existing MCP servers?
Stateless MCP is a backward-incompatible change, so servers written forย 2025-11-25ย won’t work with clients that only speakย 2026-07-28. The specification allows a server to implement both โ keeping the oldย initializeย handshake for legacy clients while exposingย server/discoverย and the stateless RPCs for newer ones. Most SDKs are handling this transition for you, but check your version before upgrading.
Do I still need local MCP servers?
Local MCP servers still make sense for anything tied to your machine โ filesystem access, git operations, local databases, or tools that read your working directory. What changes is the default for everything else. If a server only wraps a network service the whole team uses, there’s little reason for each person to run their own copy.
What replaced sampling and roots in the new spec?
Sampling and Roots are both deprecated, with a minimum twelve-month window before removal. Instead of Sampling, integrate directly with your LLM provider’s API. Instead of Roots, pass directories and files explicitly as tool parameters, resource URIs, or server configuration. Both migrations move the server away from depending on the client’s local environment.
Is a shared remote MCP server less secure than local ones?
A shared remote MCP server concentrates credentials rather than spreading them, which is a real tradeoff. You lose the distributed blast radius of local installs, but you gain a single place to patch, one audit trail, and no plaintext tokens on individual laptops. It’s more secure in practice if โ and only if โ you use per-user authentication rather than one shared service account.
What is SEP-2575?
SEP-2575 is the Model Context Protocol enhancement proposal titled “Make MCP Stateless,” which reached Final status and shipped in theย 2026-07-28ย specification revision. It removes the initialization handshake, moves protocol version and client capabilities into per-requestย _metaย fields, and adds the mandatoryย server/discoverย RPC.





