The Model Context Protocol (MCP) is how an AI agent reaches tools in the outside world: a ticketing system, a data warehouse, a payments API, a customer record. An MCP server exposes tools; an MCP client calls them on the user's behalf. MCP has four official SDKs — TypeScript, Python, Go and C# — and between them they are now pulling close to half a billion downloads a month, with TypeScript and Python each past a billion downloads in total.
Software at that scale stops being a community project and starts being infrastructure, which means it starts appearing in security reviews. On 28 July 2026 the protocol shipped its largest revision since launch, and a good part of it is about authorization.
What Changed
The revision was called "Stateless MCP" by many enthusiasts. That's because protocol-level sessions are now gone, along with the initialize handshake. Every request now carries its own protocol version, client identity and capabilities in a _meta field, so any request can land on any server instance behind a plain round-robin load balancer. No server needs to remember which conversation a request belongs to, so the sticky routing and shared session stores that earlier versions required are no longer part of the picture.
Alongside that, Tasks and MCP Apps became formal extensions rather than parts of the core — we wrote about what MCP Apps are and how to secure them when they first appeared.
What the Release Improves for Authorization
We have written about authorizing MCP before, in a CISO's guide to access control for MCP and in how authorization fits the OWASP MCP Top 10. This blog dives deep into what the new specification changes mean for authorization.
Authentication and Identity Hardening
Four changes landed here, each closing a specific weakness:
| Change | What It Prevents |
| A login response must state which authorization server issued it, and the client must check that it matches the one it started with — carried in the iss parameter on the redirect back from login (SEP-2468) | An attacker swapping in a different login server mid-flow and collecting the authorization code |
| Clients must say what kind of application they are when they register, via the application_type field in the registration request (SEP-837) | Command-line and desktop clients being turned away because their local return address looked suspicious |
| A token only works with the authorization server that issued it, so clients must store tokens keyed by that server's issuer identifier (SEP-2352) | A credential obtained in one place being replayed against another |
| Clients now identify themselves with a URL that serves their own metadata document, rather than registering themselves on the fly — Client ID Metadata Documents replacing Dynamic Client Registration (PR #2858) | Any client claiming to be any application, with nothing to verify it against |
Every one of these concerns who is calling and whether their token can be trusted. That is authentication, but what about authorization?
Enterprise-Managed Authorization (EMA)
The EMA extension, stable since June 2026, makes the corporate identity provider the authority over which MCP servers a client may reach. The employee signs in with SSO; the client exchanges that assertion for an Identity Assertion JWT Authorization Grant (ID-JAG) once the IdP has evaluated policy; that token is exchanged again for an access token at the MCP server's authorization server. Access is granted centrally, revoked centrally, and no employee is ever asked to approve a consent screen for a server their company already approved.
If you are confused by all these tokens and exchanges, take a look at the specification's own diagram for that flow: it might clarify things, or make it even worse. Note that the only policy evaluation in it happens at the identity provider, before the first tool is ever called.
If your MCP rollout currently depends on engineers pasting service keys into agent configuration files, deploy EMA. It is a straightforward improvement and it removes a whole category of credential sprawl.
Headers Carry the Decision
Every MCP request now carries two headers, Mcp-Method and Mcp-Name, naming the operation and the tool it targets (SEP-2243). They exist so that the infrastructure a request passes through on its way to the server — load balancers, routers, API gateways — can make decisions without opening the message. They can also authorize on them. The same change adds x-mcp-header, which lets a server mirror chosen tool arguments into Mcp-Param-{Name} headers — the specification's own example puts the region argument of an execute_sql tool into Mcp-Param-Region.
A policy enforcement point (PEP, the software component that is responsible for enforcing authorization policies) can therefore build a complete authorization question out of the headers alone, before it has read the message at all. The figure below shows the three headers of a single request mapping onto the three things a policy needs to know — what is being done, to what, and with which attributes. This information can then be sent to a policy decision point (PDP) to decide whether this tool call is permitted or denied.
An obvious worry about deciding from headers is that headers are easy to write. What if the header says one thing and the message says another? The specification closes that gap: a server must compare the two and reject any request where they disagree, with a HeaderMismatch error. That rule is what makes a header trustworthy enough to decide on — and it is also why a gateway should check the MCP-Protocol-Version header first, to confirm it is talking to a server on a version that made that promise. An older server never did.
A Native Channel for Obligations
Previously a server could only answer a request. Now it can answer with "I need something before I can answer" (SEP-2322): it returns an InputRequiredResult listing what it still needs, the client goes and gets it, then repeats the original request with the answers attached as inputResponses.
That gives the protocol somewhere to put an outcome that is neither permit nor deny, but permit once something else has happened (e.g., a manager approving a refund, or a user confirming an amount). In access control terms this is an obligation: a condition the policy attaches to a permit, which must be satisfied before the action goes ahead. Until now, anyone wanting that behaviour built it themselves in each server.
The sequence below traces a refund through that pattern: the policy permits it on condition that an approver confirms, and the request only completes on the second attempt.
What Those Four Changes Add Up To
Taken together, the release moved the protocol toward the shape an enforcement point wants. Statelessness means a checkpoint in front of MCP needs no sticky routing and no shared session store, so it scales like any other piece of HTTP infrastructure. The headers mean the authorization question can be assembled before the message is parsed. Obligations mean "permit once a human confirms" is a protocol pattern rather than custom plumbing in every server. And EMA means the person's identity arrives already established, from the corporate directory, instead of being inferred from a shared key.
Every one of those makes enforcement easier to build and cheaper to run.
Where the Specification Stops
The EMA extension is explicit about the boundary. Its guidance to authorization server implementers reads:
Map IdP claims to permissions — ID-JAG tokens carry claims (scope and resource information) that your server uses to determine who the employee is and what the employee can access. Define your authorization logic based on these claims.
That last sentence cannot be any clearer. Defining the authorization logic is the responsibility of every MCP server team in the organization.
EMA decides only once at connection time, and it cannot know that a record accessed later belongs to a different legal entity than the user's. It cannot know that this is the four-hundredth tool call in ninety seconds. It cannot know that a data column is classified and this user should receive a masked value rather than a refusal. Coarse scopes frozen into a JWT are the failure mode that attribute-based access control (ABAC) exists to address.
Two further items in this release create new authorization work rather than closing old gaps, and both are worth putting on the roadmap.
- Tool lists are now cacheable, which collides with per-user filtering. Hiding tools a user may not call is one of the most effective controls available for agents: an agent cannot be talked into calling a tool it was never shown. That control works by returning a different tool list to different people. This release makes list results cacheable — they now carry a lifetime (ttlMs) and a scope (cacheScope) — and states that list endpoints no longer vary per connection (SEP-2549). A per-user tool list marked cacheScope: "public" can be stored by a shared cache along the way and handed to the next user who asks. The filtering silently stops being per-user. Anyone doing tool visibility filtering must mark those results "private".
- server/discover answers before anyone has been authorized. Every server must now implement this call so clients can ask which protocol versions, capabilities and identity it supports, and clients may call it before anything else. It is therefore a surface that responds ahead of whatever checks a session would normally apply, and the information it reveals about an internal MCP server might be worth guarding.
When the Specification is Enough
None of the above means every deployment needs more than EMA. On its own, EMA could be more than sufficient depending on the use case.
If every tool on a server is equally sensitive, and anyone permitted to connect may use all of it, then which servers someone may reach is the whole question, and EMA has answered it. If the server passes the user's own token through to a system that already applies that user's record-level permissions, the authorization is already happening in the system that owns the data, and adding a second decision in front of it duplicates work.
The Bigger Picture: Authorization from Login to Data
So to summarize, one question settles how much of this applies to a given deployment: after the token is issued, does anything still vary by person? Wherever the answer is yes, there is a decision to be made, and each of those decisions happens at a different moment on the path from login to data.
| When the decision is made | What it settles |
| At login | Which MCP servers this employee may reach, and with which coarse scopes — this is what EMA now covers |
| Before the model sees the tool list | Which tools this user is shown at all; a hidden tool cannot be argued into being called |
| Before a tool runs | Whether this call proceeds, given these arguments — the same tool with different arguments can decide differently |
| After a tool returns | What comes back: records dropped, sensitive fields masked |
| On a RAG retrieval | Which documents a search is allowed to return, with the condition pushed into the vector store |
Only the first row is settled by the protocol. The rest are decisions tha have to be made on every request. Additionally, where that enforcement physically sits is a deployment choice, not a fixed part of the architecture — it can be a gateway in front of servers you do not control, at an MCP server you own, or the client-side agent application. The decisions stay the same regardless of where the trust boundary happens to fall.
The figure below places those decisions on the path a single request takes: the left-most is the one the protocol now covers.
Axiomatics operates at every decision after the first, and at whichever enforcement point suits the deployment: gateway enforcement for MCP gateways such as IBM Context Forge, client-side enforcement in agent frameworks including LangChain and Google ADK, and server-side enforcement in MCP servers such as FastMCP. Therefore, policy sits wherever the trust boundary actually is, policies authored once in the abbreviated language for authorization (ALFA) and evaluated with OASIS XACML 3.0 semantics across an entire estate of servers rather than reimplemented in each one, and a decision record for every call — which is the artifact a compliance auditor asks for.
Closing
The MCP protocol grew up recently. It handles identity properly, it scales like ordinary infrastructure, and it says plainly that the access decision is yours to define. That decision is worth making in one place, declaratively, with a record of what was decided and why.
If you are putting MCP through a security review at the moment, we would be glad to talk it through.
Sources
- MCP 2026-07-28 specification changelog — modelcontextprotocol.io
- Release announcement, including SDK download figures — MCP blog
- Release candidate announcement — MCP blog
- Streamable HTTP transport, header requirements and validation rules — specification
- Enterprise-Managed Authorization extension — specification and announcement
- NIST Special Publication 800-207 — architecture





