An agent is preparing a board packet. It reads Q3 financials from one system, drafts a document in a second, and notifies the audit committee through a third: three tool calls, three Model Context Protocol (MCP) servers, three authorization domains, behind one sentence of human intent.
Locking each of those calls down to least-privilege is the part we know how to do. There are two natural models for it. The basic forms are buildable today on existing OAuth machinery. The interoperable pieces around discovery, requestable denials, asynchronous approval, and task binding are still being standardized. In the first model, the authority lives in the token. An authorization server mints a credential narrowed to the action, and the agent carries it to the call. In the second, the decision lives at the resource. The server that runs the tool evaluates each call as it happens.
There is a third party that is easy to overlook, the tool itself, and MCP makes it first-class. MCP gives the tool boundary its own protocol surface: a catalog to discover tools and a call to invoke them. Task-oriented extensions and proposals then give long-running or approval-gated work a place to wait. Whichever model decides, the tool boundary is where the decision is enforced, and increasingly where the hard parts get solved. None of this is unique to MCP. The two models are how fine-grained authorization works for any OAuth resource server, and MCP simply makes the tool boundary an explicit protocol surface, the sharpest place to watch them play out.
That there are two models is the good news. It is also the trap. Both authorize calls. Neither names the task those calls serve, and nothing else in the protocol stack does either. The failure mode is not an over-authorized call. It is that several correctly authorized calls can compose into work the user never approved. Least-privilege per call can be locally correct and globally wrong, every check passing while the task drifts somewhere the user never sanctioned. The same gap shows up downstream as friction. The user sees a prompt per fragment, and the logs join by timestamp and luck.
Make it concrete, with every grant already at the right grain. The agent reads Q3 financials, drafts the packet, and notifies the audit committee, exactly the audience the user approved. But while drafting, it folds in an unreleased acquisition memo it happened to have access to. The finance server sees a valid read, the document server a valid write, the workflow server a valid notify to the right group. Every check passes, and no single server sees the whole chain. This is not a content-scanning problem. Even with locally valid policy at every hop, no server owns the task boundary, so none can tell whether the notice still belongs to the approved board-packet task. Narrowing the grants does not help, because each call is already within its grant. What is missing is anything that ties the calls back to the work the user actually approved.
That is the gap. Least-privilege per call is the floor, not the ceiling. This part walks both models on plain OAuth, makes the tool boundary first-class, shows where each one strains, and pins down how to choose. The second part covers the standards that close the nearer gaps, AuthZEN, the Access Request and Approval Profile (ARAP), and the proposals around them, and the one gap none of them closes.
Whichever model decides, the MCP-native path lands in the same shape:
| Step | Role |
|---|---|
tools/list | Exposure control |
tools/call | Authorization choke point |
| Denial | Structured remediation |
| Approval | Held work or a new token |
| Resume | Re-evaluate, then execute |
The two models below are how any OAuth resource server reaches that boundary. The rest of this part works through them, then makes the tool boundary first-class.
One Sentence, Three Tool Calls
The board packet takes a sequence of tool calls across three MCP servers, each protecting its resources through its own Authorization Server (AS):
query_financials(period="Q3 2026", entity="Example Corp")on a finance MCP server, with its own AS.create_doc(template="board-packet", title="Q3 Review")on a document MCP server, with a different AS.notify_reviewer(group="audit-committee", deadline="...")on a workflow MCP server, with a third AS.
The user approved the broader task before the agent started: “prepare the Q3 board packet for the audit committee.” In today’s systems, that approval is usually application state, not protocol authority. It does not automatically authorize the individual tool calls. The agent may begin with an existing credential or session accepted by a server, but it does not yet hold action-specific authority for all three systems.
Each tool call has to land at the right grain. Not “agent can act on these resource servers,” but “agent is approved to read this specific financial period for this specific entity, draft this specific document, notify this specific reviewer group.” The agent does not know up front which actions each server permits, which Rich Authorization Request (RAR) types each Authorization Server accepts, or which fields are required. Discovery is part of the protocol.
Before walking the two models, it helps to be precise about what we are actually authorizing.
Three Problems Inside One Tool Call
Everything that follows turns on one distinction. The model is untrusted reasoning that proposes actions. Each tool invocation is a request to exercise specific authority against a specific resource. The protocol layer’s job is to govern the invocation, not the reasoning. That job is three different authorization problems, often conflated:
- Tool discovery. Which tools does the agent see in the first place? An MCP server controls its
tools/listresult, so a deployment can filter the catalog by policy. That shapes exposure, not execution, and the post returns to the difference at the tool boundary. MCP does not currently standardize catalog filtering tied to a durable task object. - Tool invocation. When the agent calls a tool, does the call sit within the authority the agent already holds? The token-side and resource-side models both sit here. Most of this part is about this problem.
- Tool approval. When the call sits outside current authority but is still potentially permissible, what runtime governance workflow turns the denial into a decision? Approval (a human reviewer authorizes the call), consent (the user grants additional consent in band or out of band), and access request (a general governed escalation that may compose risk evaluation, approval routing, and consent collection) are three different workflow shapes.
Both models follow the same authorization pipeline, even though they implement it at different boundaries:
- Discover need. The task requires a specific action against a specific resource. The agent learns this from the task plan, the tool catalog, or a runtime failure that points at the missing capability.
- Request authority. The agent expresses the need on the wire (an RAR to the AS in the token-side model, a tool invocation against the MCP server in the resource-side model).
- Evaluate. Policy evaluates the request against user-approved authority, client registration, deployment rules, and runtime risk posture.
- Authorize or escalate. The evaluation either produces a narrow token, returns a permit decision, or routes through a runtime governance workflow.
- Execute. The MCP server validates the token or enforces the permit and then runs the tool.
The important questions are where each step lives, what step 4 produces, which governance workflows it can invoke, and what protocol object identifies the task across many invocations. The two models answer the first questions. Neither answers the last, which is the subject of the second part.
Three Identities the Decision Needs
Before choosing where the decision lives, a real deployment has to be explicit about the identities the decision will use.
- User identity. The human (or service principal) who approved the task and consented to it.
- Client identity and instance attestation. The agent runs as an OAuth client with a
client_id. Deployments can add the Client Instance Assertion profile to identify the specific instance making the call, allowing instance-level policy and revocation. - Actor chain. When the agent delegates to a sub-agent or crosses workload hops, RFC 8693 Token Exchange defines the
actclaim used to represent the current actor and nested prior actors. The Actor Profile adds structure for agent delegation chains, including instance identity and per-hop authority constraints.
Both models need all three. Without them, the decision collapses the human, the client, and the acting workload into one blurry principal, and the audit record cannot explain who authorized what for whom.
The choice between the two models comes down to three moves:
| |
The Token-Side Model: Authority in the Token
In the token-side model, the client carries the authority. Each tool call is authorized by a token narrowed to the relevant action. Steps 2 through 4 of the pipeline happen at the Authorization Server. The client then presents the resulting token when it asks the MCP server to execute.
Discovery and Request
The agent’s first unauthorized call starts a discovery cycle. The MCP server returns an OAuth WWW-Authenticate challenge carrying the Protected Resource Metadata (PRM) URL and, where possible, scope guidance. This is the layering MCP’s authorization specification adopts. The client fetches PRM, discovers the AS, and follows AS metadata. Action-level authorization_details are an extension: a deployment adopting this model also publishes RAR-type metadata so the client can discover the relevant schemas.
The 401 and the metadata it points at look like this:
| |
| |
The first request for a given task is often approved through a normal OAuth front-channel consent flow. The client submits the request via Pushed Authorization Requests (PAR), the AS renders it to the user in a browser, the user approves, and the AS issues a code the client exchanges for a token. The front-channel case applies especially to the initial request and to high-stakes step-up. But an agent rarely makes a single call. It fans out across tools and iterates, and bouncing the user to a browser for every new authority it turns out to need is not practical. The case that matters is asynchronous approval, where the decision happens out of band with no human at a browser. The proposed token-side answer to it, Deferred Token Response, is covered in part two.
In an RAR flow, the client constructs an authorization_details entry that names the specific action and submits it through PAR. The AS evaluates the request against user-approved authority, client registration, deployment rules, and runtime risk posture. On approval, the AS completes the authorization flow and mints a narrow access token.
The authorization_details entry names the one action in the resource’s own vocabulary, not a coarse scope. The type and its fields are resource-defined. The client learns them from RAR-type metadata:
| |
The baseline shape is a token the MCP server validates against authorization_details, without requiring a policy call at execution time. The client carries the proof that the AS granted the authority. A deployment can still add introspection, event-driven invalidation, or per-call evaluation. The acquisition cycle repeats whenever the agent needs authority outside its current grant.
What the Client Has to Run
Pushing authority into the token makes the client the orchestrator. To invoke a single tool, it may have to run a loop:
- Decide what to request. Listing the catalog may need a coarse scope. Invoking a specific tool needs authority at the action’s grain. The 401 names a Protected Resource Metadata URL and sometimes a
scope. A scope is easy to ask for. An action-levelauthorization_detailsentry is not. The client either reads RAR-type metadata and builds the entry for this exact action, or it guesses. - Acquire a token for it. With the user at a browser, the first grant goes through the normal redirect, and so does a step-up that needs fresh consent or a stronger sign-in. Mid-task, with no one at the browser, new authority has to be approved out of band instead. That asynchronous path is the harder one, and part two takes it up.
- Call the tool, and find out whether the token was enough. Often it is not. A valid token can still fall short on what it grants or on how the user authenticated.
- Read the challenge and correct. Broaden the scope, build the right
authorization_details, step up authentication, or carry a transaction challenge to the AS for a transaction-bound token, then retry. - Keep the result. Cache the token keyed by the authority it carries, so the next call can reuse it instead of starting over.
There are two ways to learn the requirement in step 3, and the client developer has to choose between them.
Reactive: invoke and read the challenge. Call the tool, let it fail, and read the WWW-Authenticate header. OAuth already has a graduated family of challenges for this, one per grain of insufficiency, and the client has to handle each:
insufficient_scopesays the token lacks a required scope. The grain is the capability class.insufficient_authorization_detailsis the RAR analogue, a valid token that lacks standing authority at the action’s grain. It can name theauthorization_details_types_requiredor hand back ready-to-useauthorization_detailsfor the next request.- The OAuth 2.0 Step Up Authentication Challenge Protocol returns
insufficient_user_authenticationwith theacr_valuesormax_agean action requires, when the problem is not what the token grants but how strongly or how recently the user authenticated. - The proposed OAuth Transaction Authorization Challenge goes one grain finer. The resource names the specific transaction in front of it, and the AS evaluates exactly that, runs consent or step-up if needed, and mints a transaction-specific token that authorizes it and nothing else.
The family shares one shape, and it is worth seeing at the protocol layer before any tool machinery arrives. The resource judges the concrete situation and issues a structured challenge. The Authorization Server remediates at the challenged grain, a broader scope, richer authorization details, a stronger authentication, or a single-transaction permit. The client carries the result back as a token. Trigger at the resource, remediation at the AS, enforcement by token. Each challenge demands a different correction, and the cost they share is the failed call. For a read that is a wasted round trip. For anything with a side effect, the client has to be certain the call was rejected before the effect, not after it.
Proactive: read the metadata first. Fetch RAR-type metadata, work out the requirement for the call you are about to make, request the matching token, and only then invoke. The cost moves to interpretation. The client now has to read the resource’s schema correctly, and the resource is still the authority on whether it got it right. A proactive guess that is wrong lands back in the reactive path anyway, and authentication-strength requirements often cannot be discovered ahead of time at all.
Either way, the client is running a small authorization state machine. It has to discover the requirement, request a token, and match held tokens against pending calls. It has to acquire and await new ones, refresh them before they expire, and satisfy a step-up authentication challenge when one comes back. And it has to union scopes across incremental requests, so re-authorization does not drop authority the agent already had. The more granular the authority, the more tokens there are to track. This is the token-side model’s quiet tax, and the client developer pays it on every tool the agent can reach.
The Ontology Problem
The “AS evaluates the request” step is where this model meets domain reality. For the AS to mint a token whose RAR entries describe read Q3 financials for Example Corp, the AS has to be able to evaluate whether the request is sensible: whether the client may make this kind of request, whether the user’s role permits the action, whether the financial period and entity identifier are valid for this user, whether the constraints are compatible. That is resource-domain knowledge. This bites open-world, multi-AS, self-service integrations most. A first-party authorization server built into its own resource server mostly sidesteps it, because the domain knowledge is already in the box.
The AS in a typical multi-tenant SaaS Identity Provider (IdP) is generic. It knows OAuth, RAR, scope, and client registration. It does not natively know what financials means, what Q3 2026 resolves to in the finance system, or which entity identifiers are valid for this user. The RAR type and actions strings are opaque to the AS unless the AS has been taught them. There are three ways out, and each has a cost:
- Tight coupling. The AS is purpose-built for the Resource Server (RS). The finance system’s AS is part of the finance system. This is common for first-party deployments and does not generalize to the open-world MCP scenario where any agent can call any tool on any MCP server.
- Standardized vocabulary. A shared operation language across resources, such as a common RAR-type registry. Real progress, but the vocabulary itself is a slow, committee-driven artifact, and not every RS adopts it.
- Delegated evaluation. The AS calls the RS or an RS-domain Policy Decision Point (PDP) to validate the RAR at issuance time. This works but reintroduces an RS-side decision into the token-side model. The “carry the authority” property weakens because the RS is back in the loop, just earlier than execution.
In practice, many RAR deployments rely on tight AS/RS coupling or delegated evaluation, and clients often know supported RAR types through prior integration. The Zehavi RAR-type metadata draft can surface the schemas through an authorization_details_types_metadata_endpoint, but it does not tell the AS how to validate the domain semantics behind them. RAR improves the expression of authority. It does not eliminate the need for a shared vocabulary or resource-domain validation.
That is the token-side model’s hard part. The AS has to understand a resource’s domain to mint authority over it, the client has to run the acquisition loop to get the right token, and a fresh narrow token piles up for every new kind of action. The authority is portable. The cost is ontology at the server and orchestration at the client.
The Resource-Side Model: The Decision Stays at the Resource
In the resource-side model, the resource server evaluates. The client presents whatever credential or authenticated session the MCP server accepts, and the component controlling execution acts as the Policy Enforcement Point (PEP). It evaluates the concrete request and executes only on a permit.
The appeal is that the resource is the domain expert for its own tools. It already knows what query_financials(period, entity) means, because it implements the call. There is no AS in the request path that needs to learn the resource’s vocabulary. The ontology problem disappears at the issuance layer, because nothing is being issued.
It collapses the client’s side too. There is no scope to discover, no authorization_details to construct, no token to match or refresh per action, and no acquire-and-retry loop. The client presents the one credential it holds and calls the tool. The resource works out the requirement and decides. The acquisition state machine moves behind the resource, where the domain knowledge already lives. The client developer writes a call, not a loop. The work does not vanish. It moves to the resource, which now owns the decision, the denial, and the audit for every call it serves.
The freshness story is also stronger. Consider an agent approved to read Q3 financials for Example Corp. Between approval and execution, the user is offboarded from the finance system, or Example Corp is reclassified as restricted. A token-side server validating offline may still accept a token that remains valid on its face, handing an offboarded user’s agent confidential data. A resource-side server evaluating immediately before execution can reject it. Deciding at the moment of use narrows the time-of-check-to-time-of-use (TOCTOU) window between grant and action.
On plain OAuth, though, the resource-side model has its own hard parts, and they are quieter:
- No standard decision contract. The server has a token and some local logic. How it turns the request into a decision is proprietary. Two MCP servers solve the same problem two different ways, and nothing about the decision is interoperable.
- No standard way to say “denied, but you may ask.” A flat
403is a dead end. The agent has no machine-actionable path from denial to approval to retry. - The decision is not portable. It lives at the server and its policy logic. Another party cannot verify it without re-running the evaluation against the same domain model.
- It fragments across servers. Each MCP server decides with only its local context. A task that crosses three servers produces three unrelated decisions, three approval prompts, and three audit trails.
The resource-side model keeps the meaning where it lives. The cost is that, on traditional OAuth, every server reinvents the decision, the denial, and the audit. Part two is about closing exactly those gaps.
Where the State Lives
The two models answer where the decision lives. A separate axis, easy to conflate with it, is where the authorization state lives that the decision evaluates. There are three topologies, and they are still protocol-layer facts, independent of any tool machinery.
- State in the token. The claims are the authorization state. The
authorization_detailsthe credential carries are everything the resource knows, validation is offline, and nothing consults a backend at decision time. Token reuse is maximally valuable here, because the token is the state owner. The corollary is that token churn is the fulfillment mechanism. Every change in authority forces reissuance, and staleness is bounded only by token lifetime. - State in a store. The PDP evaluates against externalized state: Zanzibar-style relationship tuples in a system like OpenFGA, an entitlements database, or policy data. The token is little more than principal identity. Reuse is trivial but low-meaning, because the leverage moved to the store. A grant fulfills as a store write, and the same token the agent already holds starts passing evaluation. Freshness is strong. Portability and cross-domain proof are weak.
- Hybrid overlay. The token carries constraints and binding data that the PDP combines with backend state. Most production deployments land here, and it offers the most options: cheap narrowing carried in the token, live entitlements read from the store.
The coupling with the two models is asymmetric. The token-side model forces token-resident state at the point of validation, unless introspection quietly reintroduces a backend. The resource-side model can run any of the three. That changes what the earlier tradeoffs weigh. Token reuse, churn, and the TOCTOU window depend on which topology the deployment actually runs, not just on which model it chose. And it changes what an approval has to do to take effect. A grant lands as a fresh token in one topology and as a store write in another, which is exactly the fulfillment question part two picks up.
The Tool Is a First-Class Boundary
Before the policy machinery, it is worth being explicit about the layer both models run through. The token-side model treats the MCP server as a resource server. The resource-side model treats it as a policy enforcement point. MCP itself treats it as something richer than either. It is a host of tools, with first-class verbs of its own.
- The catalog is governed.
tools/listis not just documentation. A deployment can filter the catalog through the same policy that gates invocation, so an agent sees a tool set appropriate to its context. That filtering is exposure control, not authorization. Catalogs can be stale, policy can change, and a client can call a tool by name without listing it first. The server must still authorize everytools/call. - The call is the choke point.
tools/callis where execution actually happens, so it is where enforcement has to sit. A decision made anywhere the call can bypass is not enforcement. Whichever model produced the authority, the tool boundary is where it is finally checked. - The work can be held. This is the piece OAuth never had. Task-oriented MCP extensions and proposals let a tool call return a working result and resume later, which is exactly the substrate an out-of-band approval needs. A denied-but-requestable call does not have to fail. It can become pending work that completes once a human decides.
- The tool can ask. MCP elicitation lets a server gather structured input, confirm an action, or send the user to an external flow. Elicitation is not authorization or durable consent by itself. The server must bind the interaction to the authenticated user and feed the result into its policy or approval workflow. An elicited value changes standing authority only through a governed re-authorization, not by virtue of being collected.
The reason to make the tool first-class is that the hard parts of the resource-side model, the missing decision contract and the missing denial-to-approval workflow, get their home here. The catalog and the call give the tool boundary an enforcement point. Held work gives it a place to park a long-running approval. What is still missing is a standard language for the decision, and a workflow for when the answer is no. Both are where part two goes.
Comparing the Two Models
The two models are not enemies. They place the same five pipeline steps at different boundaries, and the tradeoffs follow from where each step lives. One of those tradeoffs lands squarely on the client developer building the agent, in how much token management each model demands.
| Pipeline step | Token-side: authority in the token | Resource-side: decision at the resource |
|---|---|---|
| Discover need | Agent infers from task plan or a WWW-Authenticate challenge | Agent infers from task plan or a tools/list catalog the MCP server already filtered |
| Tool discovery | Out of scope for the AS. The MCP server can filter independently | Can use the same PDP as invocation, but still requires execution-time authorization |
| Request authority | RAR authorization_details to the AS, narrowed to one action | Tool invocation directly to the MCP server |
| Evaluate | At the AS, optionally consulting a PDP. The AS needs domain knowledge or must delegate | At the MCP server’s PDP, with the resource’s own domain model in scope |
| Authorize or escalate | Narrow access token, or a deferred grant when approval is needed | Permit decision, or held work when approval is needed |
| Execute | Baseline uses local token validation. Higher-assurance deployments add introspection, events, or runtime evaluation | MCP server runs the tool only on a freshness-bounded permit |
| Carried artifact | Sender-constrained access token, bound by Demonstrating Proof of Possession (DPoP) or mutual TLS (mTLS), portable proof | No new artifact on permit. A server-generated MCP taskId while asynchronous approval is pending |
| Authorization state | In the token. Claims are the state, and reissuance is how state changes | In the PDP’s store (or hybrid, with token overlay). A store write changes state under an unchanged token |
| Client token management | Match each call to a held token or fetch a fresh narrow one, and cache the result | Reuse one token, and let the resource broker any approval |
| Latency profile | Token acquisition up front, then local validation unless stronger freshness is required | One PDP evaluation per consequential call. Caching must remain within policy freshness bounds |
| Easy | Offline validation, token portability, low execution-time latency | Domain-specific policy, TOCTOU-resistant execution, no token explosion |
| Hard | AS ontology, RAR vocabulary convergence, token churn | Cross-server audit, approval fragmentation, portable proof |
| Missing | Durable task context across calls | Durable task context across calls |
The choice is per call, not per deployment, and it follows from where the hard part lives:
- Reach for the token-side model when authority has to travel: several downstream hops, offline or low-latency validation, or an audience that cannot call back to a PDP on every request. The cost you accept is the AS ontology problem and token churn.
- Reach for the resource-side model when the decision has to stay where the meaning lives: the resource owns rich domain semantics, the action is consequential, or TOCTOU drift between grant and use is unacceptable. The cost you accept is a per-call evaluation and a decision that is not portable.
- Layer both when you want defense in depth, which is where most production deployments land. A coarse token carries identity and audience, and the resource still evaluates the concrete call at the action’s grain. The token answers who is calling and roughly for what. The resource answers whether this exact call is allowed.
Carry when you can, evaluate when you must, and most real systems do some of each. But whichever you choose, the choice only governs a single call. The moment the work has to stay governed across servers, neither model is enough on its own, which is where the second part begins.
What to Get Right
Both models can be implemented in ways that look like least-privilege without being it. A few failure modes are worth designing against on purpose, whichever model you pick.
- Authority at the wrong grain. A token or policy that says “may call the finance MCP server” is not least-privilege. One that says “may read Q3 financials for Example Corp” is. The token-side model puts the grain in the
authorization_detailsentry. The resource-side model puts it in the PDP’s view of the concrete call. Coarse authority is the most common way least-privilege quietly decays into ambient access. - Bearer tokens that travel. A token-side access token that is not sender-constrained is replayable by anyone who captures it. Bind it to the client with DPoP (RFC 9449) or mTLS (RFC 8705) so a stolen token is useless off the agent that earned it.
- Enforcement off the choke point. Filtering
tools/listis exposure control, not authorization, and a client can call a tool it never listed. The PEP has to sit where execution actually happens and authorize everytools/call, or the decision is bypassable by design. - Stale or replayed approvals. An approval is an input to a fresh decision, not a standing grant. Bind it to the exact subject, action, resource, and request, bind it in time, and reevaluate at execution. The resource-side per-call evaluation narrows the TOCTOU window that an offline-validated token-side token leaves open.
- Confused-deputy delegation. The agent authenticates as itself but acts for a user. The decision must turn on both, not collapse to one. Preserve the actor chain (RFC 8693
act) so the principal and the acting workload stay distinct in the decision and in the evidence.
Where This Goes Next
Part 1 compared where the decision can live. Part 2 is about what has to become standard around that decision: the decision contract, the mapping into it, the denied-but-requestable workflow, and finally the task context none of them provide. Once the task spans more than one call, server, or authorization domain, neither model stands alone, because neither names the task that connects them.
Part two walks that stack and closes every gap but the last. The one that remains is the task. Nothing names it.