If you have wired up authorization for an MCP server, you have probably had this moment. The OAuth flow works, tokens validate, the audience check passes, and you still cannot answer the question your security team is actually asking. Can this agent, acting for this user, run this specific tool on this specific record. The standards got you a valid token. They did not get you that decision.
This is not a criticism of the people building MCP. The authorization story is being written in real time, and the pieces that exist are solid. The point is knowing where each standard stops, so you do not assume a layer is covered when it is not. This article walks through what MCP's authorization standards actually specify, why OAuth scopes cannot carry fine-grained tool authorization on their own, where the OpenID AuthZEN standard fits, and the parts that are still genuinely unsolved. It is a companion to our pillar on what an MCP gateway is and where authorization fits.
What are the MCP authorization standards?
The MCP authorization standards are the set of OAuth specifications the protocol builds on. Under the current MCP authorization spec, a protected MCP server acts as an OAuth 2.1 resource server, MCP clients act as OAuth clients, and servers validate access tokens issued for them. The spec requires Protected Resource Metadata for discovery and Resource Indicators for audience binding. These standards cover authentication and token handling. They do not define fine-grained authorization.
What OAuth actually gives you

The MCP spec is specific about its foundations. Servers must implement RFC 9728, Protected Resource Metadata, so clients can discover the right authorization server. Clients must implement RFC 8707, Resource Indicators, and include the resource parameter in both authorization and token requests, so tokens are bound to the server they are meant for. Servers must validate that a token lists them in the audience claim and reject it otherwise. The base is OAuth 2.1, which is itself still an IETF draft rather than a ratified RFC.
This is a good authentication story. It tells the server that the caller holds a valid token, that the token was issued for this server and not borrowed from somewhere else, and where to go to verify it. Audience binding in particular matters, because it is what stops a token minted for one server being replayed against another. If you get this part right, you have closed a real class of attacks.
What you have not done is decide anything about the specific call. OAuth answers "is this a valid token for me." It does not answer "should this action run." The MCP spec is candid about the boundary. Authorization support is marked optional, and as The New Stack observed, the built-in story stops at authentication and does not reach fine-grained authorization.
Why OAuth scopes are not enough for MCP
The usual instinct is to reach for OAuth scopes to close the gap. Scopes are how OAuth has always expressed coarse permission, so why not encode tool permissions as scopes. In an MCP setting this breaks down for three concrete reasons, and I laid them out during the AuthZEN masterclass at Identiverse 2026.
The first is that the token is issued to the agent, not to the human behind it. There is no standard slot in an OAuth token for "this agent is acting on behalf of this user." So a scope on the agent's token tells you what the agent may do in general, not what it may do for the particular person it is currently serving. In most real systems those are very different sets.
The second is that scopes are coarse by design. A scope like read:tickets is a category, not a decision. The call in front of you is not "read tickets in general," it is "read this ticket," and whether that is allowed usually depends on who the user is and which ticket it is. Encoding every resource-level rule as a scope produces either a handful of scopes that are too broad to be safe or thousands that are impossible to manage.
The third is that the resource a tool touches often depends on the arguments of the call. The same get_record tool is harmless on one record and a data breach on another. Scopes are fixed at token-issue time. They cannot see the arguments of a call that has not happened yet. So the thing that determines whether a call is safe is exactly the thing scopes cannot inspect.
Put those together and the real question is richer than any token can carry. Can this agent, acting for this user, invoke this tool with these arguments. That is a decision that has to be made at the moment of the call, with the arguments in hand and the acting user known. It is not something you bake into a scope in advance.
Where AuthZEN fits

This is the gap the OpenID AuthZEN Authorization API is built for. AuthZEN reached final specification status in January 2026, which means it is stable and not subject to further revision. It defines a standard way for a policy enforcement point to ask a policy decision point a single question and get a yes or no back. The question is expressed in terms of a subject, an action, a resource, and context, which is exactly the shape of the MCP question above. The agent and its acting user are the subject, the tool is the action, the arguments and the target are the resource, and everything else is context.
The value of a standard here is that the enforcement point and the decision engine do not have to be the same product. Your gateway can enforce, your policy engine can decide, and they speak a defined protocol in between. We have written separately on what AuthZEN means for enterprises.
There is an emerging profile in the AuthZEN community aimed specifically at MCP tool authorization, which is worth watching if you are building this now. The idea is that a tool declares its authorization intent in its input schema, and the enforcement point, the gateway or the server, calls the decision point before the tool executes. The mapping between the call and the decision request is expressed as expressions over the tool's arguments and the token's claims, so the decision can reason about both the arguments of this specific call and the identity behind it. One detail is a good sign that the people writing this take enforcement seriously. A deny is defined at the protocol level, returned as a JSON-RPC error so the tool cannot run, rather than as a soft signal the client is free to ignore. That is fail-closed by construction.
Refer here for draft 1 of the MCP profile for AuthZEN: “COAZ-MCP: COAZ Binding for the Model Context Protocol - Draft 1”
The delegation piece, and what is still missing
Standards also exist for the acting-on-behalf-of problem, and they are worth knowing even though they do not fully close it. RFC 8693, OAuth Token Exchange, defines how one party can exchange a token to act on behalf of another, with act and may_act claims that express delegation. It is the cleanest standardized way to carry a delegation relationship, and it is the right primitive for an agent that acts for a user. Treating tokens themselves as authorization decisions worth governing is part of the same thinking.
What is still missing is honest to state. There is no widely adopted standard slot that reliably carries "which human is this agent acting for" across every hop of a chain, which is why so much of the current work is about delegation. And the hardest version, delegation that crosses organizational boundaries, is genuinely unsolved. George Fletcher, in what several attendees called the strongest technical session at Identiverse 2026, described this as the crossing-the-trustee problem. Inside one company you can paper over delegation. The moment a chain reaches into a different trust domain, where the party you are delegating to is governed by someone else, the easy answers stop working. Business-to-business cases can be handled with contracts and a transparency layer. Consumer cases, he was candid, are still open.
There is also the question of what happens after a yes. Decisions are not always permanent. A policy engine may need to attach obligations to a decision, or withdraw one already in flight, and most implementations are not thinking about that yet. It is the kind of thing that separates a demo from a production authorization layer.
The reason to name all of this plainly is the same reason Nathan Harris of Gartner made a point of it at Gartner IAM London 2026. AI can help you write and improve authorization policies, but the runtime decision itself has to be deterministic. Standards are what keep it deterministic. Knowing which parts are settled and which are still moving is how you avoid building on the parts that are not there yet.
How Cerbos fits

Cerbos is a policy decision point that speaks AuthZEN, so it plugs into the pattern above as the decision engine an MCP gateway or server calls. When a tool is about to run, the enforcement point sends the agent, the acting user, the tool, and the arguments, and the Cerbos PDP returns a deterministic allow or deny.
Policies are written in YAML with CEL for conditions, which means the rule that decides a call can read both the arguments of the invocation and the claims on the token, and can be reviewed and tested like any other code. Because the decision is external to the agent and the tool, changing what an agent may do is a policy edit, not an agent redeploy. And because it speaks a ratified standard rather than a proprietary API, it is not a lock-in choice. The practical patterns for this live in our MCP guide and on the dynamic authorization for MCP servers page.
The short version is that OAuth authenticates the agent, AuthZEN carries the decision, and a policy engine makes it. Scopes were never going to be the answer, because the question depends on the user and the arguments, and those only exist at the moment of the call. Build on the standards that are settled, keep the runtime decision deterministic, and stay close to the delegation work, because that is the part still being written.
Try Cerbos Hub to see AuthZEN-based authorization for MCP in practice, or book a call to talk through your token and policy model with the team.
Go deeper:
- Zero Trust for AI: Securing MCP servers (eBook) for the full authorization pattern behind MCP
- How to adopt externalized authorization (eBook) for moving the decision out of application and agent code
FAQ
Tagged in




