---
description: "MCP authorization explained: how the OAuth 2.1 flow, scopes, and token rules in the MCP spec work, and how to enforce per-tool permissions at a gateway."
title: "MCP Authorization: OAuth Scopes and Per-Tool Permissions"
image: https://storage.ghost.io/c/84/03/8403f2f6-141c-411a-8f55-a32d4291533e/content/images/size/w1200/2026/10/mcp-authorization-oauth-scopes-and-per-tool-permissions-bifrost-1920x1080.png
---

Try Bifrost Enterprise free for 14 days. [Request access](https://www.getmaxim.ai/#enterprise-trial)

**TL;DR**

- MCP authorization is an OAuth 2.1 flow, defined for HTTP transports, in which the MCP server acts as a resource server and accepts only bearer tokens issued for its own canonical URI.
- The 2026-07-28 MCP spec requires Protected Resource Metadata (RFC 9728), PKCE with S256, and the `resource` parameter (RFC 8707) on every authorization and token request.
- Scopes in the spec are coarse permission strings with step-up through `403 insufficient_scope`; the spec does not define which caller may run which tool.
- Per-tool permissions are enforced most consistently at an MCP gateway, where one allow-list governs both `tools/list` and `tools/call` for every connected server.
- Bifrost scopes MCP tools to virtual keys with deny-by-default semantics, and request headers can narrow that grant but never widen it.

MCP authorization is the part of the Model Context Protocol that controls whether a client may call a restricted MCP server and what the token it presents allows it to do. [Bifrost](https://www.getmaxim.ai/bifrost), the [open-source AI and MCP gateway](https://github.com/maximhq/bifrost) built by Maxim AI, sits between MCP clients and the servers they reach, so it is one of the places where that authorization is enforced. This guide covers the OAuth 2.1 flow in the current MCP spec, its scope and token rules, where it stops, and how to enforce per-tool permissions at a gateway. For the identity side (API keys, client setup, token storage), see our guide to [MCP authentication and token management](https://www.getmaxim.ai/articles/mcp-authentication-explained-oauth-api-keys-and-token-management/).

## What Is MCP Authorization?

MCP authorization is the set of rules that determines which requests a protected MCP server accepts: whether the bearer token is valid, whether it was issued for this server, and whether its scopes cover the operation. Authentication establishes who the caller is; authorization decides what that caller may do once identified.

The two fail differently: an authentication failure produces a 401, while an authorization failure produces a 403, or a tool call that succeeds when it should not. The [MCP specification](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization) makes authorization optional, says HTTP-based transports should follow it, and says STDIO servers should not, retrieving credentials from the environment instead.

| Question | Authentication | MCP authorization |
| --- | --- | --- |
| What it answers | Who is calling? | What may this caller do? |
| Spec mechanism | OAuth 2.1 client registration and login | Token audience, scopes, step-up |
| Failure response | 401 Unauthorized | 403 Forbidden, `insufficient_scope` |
| Granularity in the spec | Per client and user | Per scope string |
| Granularity production needs | Per user, team, or agent | Per tool, per caller |

The last row is the gap this post covers. As our breakdown of [how MCP tools are discovered and invoked](https://www.getmaxim.ai/articles/how-mcp-tools-work-discovery-invocation-and-access-control/) shows, the protocol lists tools, but nothing in the authorization spec ties a tool to a permission.

## How the MCP OAuth Flow Works

The MCP OAuth flow starts when a client calls a protected server without a token and receives a 401 pointing at the server's Protected Resource Metadata. The client discovers the authorization server, registers, runs an authorization code flow with PKCE and a `resource` parameter, and then sends the access token on every request.

![The MCP OAuth flow moves from a 401 challenge through resource metadata, server discovery, client registration, a PKCE authorization request, the token request, and an authenticated MCP request](https://articles-images-cdn.t3.tigrisfiles.io/diagrams/mcp-authorization/mcp-authorization-oauth-flow.png)

*Figure 1: Every step before the first tool call is discovery and token issuance; nothing in the flow names a tool.*

The current revision (2026-07-28) is specific about each step:

- **Roles.** The MCP server is an OAuth 2.1 resource server and the MCP client an OAuth 2.1 client; the authorization server may be co-hosted or separate.
- **Discovery.** Servers must implement OAuth 2.0 Protected Resource Metadata (RFC 9728). Authorization servers must offer RFC 8414 metadata or OpenID Connect Discovery, and clients must support both.
- **Client registration.** Clients prefer pre-registration, then Client ID Metadata Documents, then dynamic client registration (RFC 7591), which is now deprecated.
- **PKCE.** Clients must use PKCE with `S256` when capable and refuse to proceed if server metadata omits `code_challenge_methods_supported`.
- **Issuer validation.** Clients validate the `iss` parameter in the authorization response (RFC 9207) to block mix-up attacks.
- **Resource indicators.** The `resource` parameter (RFC 8707) carrying the server's canonical URI goes in both the authorization and the token request.

Bifrost runs this flow on its own `/mcp` endpoint, so clients such as Claude Code and Cursor connect to the [MCP gateway](https://www.getmaxim.ai/bifrost/resources/mcp-gateway) without a pasted key. The [OAuth 2.1 patterns guide](https://www.getmaxim.ai/articles/mcp-authentication-oauth-2-1-patterns-for-agent-tool-access/) covers the client side in more depth.

## Scopes and Step-Up Authorization in the MCP Spec

Scopes are the only permission vocabulary the MCP authorization spec defines. A server advertises them in `scopes_supported` and in the `scope` parameter of its `WWW-Authenticate` challenge, clients request the minimum needed, and a server answers a token with insufficient scope with a 403 that names the missing scopes.

The spec tells clients to take scopes from the initial 401 challenge first, and to fall back to everything in `scopes_supported` only when the challenge carries none. When a token lacks a scope at runtime, the server responds like this:

```
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope",
                         scope="files:write",
                         resource_metadata="<https://mcp.example.com/.well-known/oauth-protected-resource>"
```

The client then runs a step-up flow, requesting a token for the union of its previous and challenged scopes and retrying a limited number of times. The spec's [security best practices](https://modelcontextprotocol.io/docs/2026-07-28/tutorials/security/security_best_practices) recommend a minimal initial scope set, because a token carrying `files:*` or `admin:*` turns any leak into broad access.

Three properties of this model shape what happens in production:

- **Scope names are server-defined.** Nothing standardizes whether `files:write` covers one tool or twenty.
- **Scopes attach to the token, not the caller's role.** Two users with the same consent get the same reach.
- **Each server runs its own scheme.** An agent connected to ten servers holds ten unrelated scope vocabularies, which is why teams following an [MCP security checklist](https://www.getmaxim.ai/articles/mcp-security-best-practices-enterprise-checklist-2026/) centralize the mapping.

## Token Handling: Audience Binding and the Confused Deputy

MCP token handling rests on one rule: a server accepts only tokens issued for itself and never forwards them. Clients send tokens in the `Authorization: Bearer` header on every request, never in a query string, and servers validate the audience claim against their canonical URI.

Token passthrough, forwarding a client token unchanged to a downstream API, is explicitly forbidden. An MCP server that calls an upstream API acts as an OAuth client to it and obtains a separate token.

The reason is the confused deputy problem: an MCP server proxying a third-party API with a static client ID can be tricked into reusing an earlier consent for an attacker's request. The spec requires such proxies to obtain user consent for each dynamically registered client. Other token rules in the current revision:

- **Short-lived access tokens.** Authorization servers should issue them to limit the impact of a leak.
- **Refresh rotation.** Authorization servers must rotate refresh tokens for public clients.
- **HTTPS everywhere.** Authorization server endpoints must use HTTPS; redirect URIs must be `localhost` or HTTPS.

Our overview of [MCP security risks and mitigations](https://www.getmaxim.ai/articles/mcp-security-risks-and-how-to-mitigate-them/) covers the wider threat model these rules sit inside.

## Where MCP Authorization Breaks Down in Production

The MCP authorization spec secures the connection between one client and one server. Production teams run many agents against many servers, and the spec leaves several decisions to the implementer: which caller may run which tool, how STDIO servers are governed, how scopes map across servers, and where authorization decisions are recorded.

![An MCP tool call passes three checks in order: token audience and expiry, required scope, then a per-tool permission check, with a 401 or 403 rejection branch under each](https://articles-images-cdn.t3.tigrisfiles.io/diagrams/mcp-authorization/mcp-authorization-three-checks.png)

*Figure 2: The MCP authorization spec stops at scopes, so the per-tool decision needs its own enforcement point.*

The gaps that show up most often:

- **No per-tool permission model.** A token valid for a server's scope can usually call any tool that scope covers, including destructive ones.
- **Uneven server implementations.** Servers that accept a static key or no auth never run the OAuth flow at all.
- **STDIO is out of scope.** Local servers inherit credentials from the environment, with no token to inspect.
- **Shared credentials upstream.** A server configured with one service account makes every caller look identical to the upstream API.
- **Scattered decisions.** Each server logs its own 403s, so no one place shows who called `delete_record` last week.
- **Delegation chains.** When one agent calls another that calls tools, the original caller's permissions are easy to lose.

Per-server fixes repeat one policy everywhere, which is why the guide to [MCP RBAC and tool-level permissions](https://www.getmaxim.ai/articles/mcp-rbac-tool-level-permissions-for-production-ai-agents/) argues for a single enforcement point.

## Enforcing Per-Tool Permissions at an MCP Gateway

An MCP gateway enforces per-tool permissions by sitting between every MCP client and every MCP server, authenticating the caller, and filtering the tool list and each tool call against that caller's grant. One policy then applies whether the upstream server uses OAuth, a static key, or nothing.

A gateway-level authorization model needs four properties to be useful:

1. **Deny by default.** A new caller sees no tools until granted.
2. **The same allow-list for listing and calling.** A tool hidden from `tools/list` must also be refused at `tools/call`, or a client that guesses the name gets through.
3. **Narrowing only.** Per-request controls may restrict a grant, never expand it.
4. **Separate inbound and outbound credentials.** The token a client presents to the gateway is never the token the gateway presents upstream, which matches the spec's no-passthrough rule.

This complements the spec: OAuth still authenticates the client to the gateway, and the gateway makes the tool-level decision the spec leaves open. The [MCP tool governance guide](https://www.getmaxim.ai/articles/mcp-tool-governance-filtering-allowlisting-and-access-control-for-the-enterprise/) covers allowlisting patterns that build on this model.

## How Bifrost Handles MCP Authorization

The [Bifrost AI gateway](https://www.getmaxim.ai/bifrost) authenticates inbound MCP clients with virtual key headers, its own OAuth 2.1 authorization server, or both, then scopes every `tools/list` and `tools/call` to the tools the caller's virtual key allows. Outbound, it authenticates to each upstream MCP server with a separate credential chosen per server.

### Inbound: who may reach the gateway

The [gateway authentication](https://docs.getbifrost.ai/mcp/gateway-auth) setting `mcp_server_auth_mode` takes three values. `headers` (the default) accepts a virtual key or API key header, `both` also accepts Bifrost-issued JWTs, and `oauth` accepts only those JWTs. In OAuth modes, Bifrost serves RFC 9728 metadata, supports dynamic client registration and PKCE with S256, and binds tokens to the `/mcp` resource through the `aud` claim.

Access tokens are JWTs valid for 600 seconds by default, refresh tokens rotate on each use, and rotating a virtual key revokes every grant minted with it.

### Per-tool permissions: what the caller may run

[Virtual keys](https://docs.getbifrost.ai/features/governance/virtual-keys) carry the tool grant. [Tool filtering](https://docs.getbifrost.ai/mcp/filtering) applies three layers that stack, and a tool must pass all of them:

![Upstream MCP tools pass through the client baseline, the virtual key allow-list, and an optional request header before Bifrost serves tools/list and checks tools/call, with unlisted tools blocked](https://articles-images-cdn.t3.tigrisfiles.io/diagrams/mcp-authorization/mcp-authorization-tool-filter-stack.png)

*Figure 3: Each layer can only remove tools, so a request header can narrow a virtual key's grant but never widen it.*

```json
{
  "governance": {
    "virtual_keys": [
      {
        "name": "support-team-key",
        "mcp_configs": [
          { "mcp_client_name": "knowledge_base", "tools_to_execute": ["search", "get_article"] },
          { "mcp_client_name": "ticketing", "tools_to_execute": ["*"] }
        ]
      }
    ]
  }
}
```

A key with no MCP configuration sees no tools, except from clients an admin marks Allow by Default. An `x-bf-mcp-include-tools` header can narrow the list per request; entries the key does not allow are dropped, and [per-key MCP tool filtering](https://docs.getbifrost.ai/features/governance/mcp-tools) is enforced again at execution time. Inactive or expired keys are refused with a 403. [Virtual MCPs](https://docs.getbifrost.ai/mcp/virtual-mcps) bundle a curated tool set behind its own `/mcp/<slug>` endpoint, reachable only through the keys attached to it.

### Outbound: what the upstream server sees

Each upstream server gets one of six [MCP authentication types](https://docs.getbifrost.ai/mcp/auth/overview): `none`, `headers`, `oauth`, `per_user_oauth`, `per_user_headers`, or `token_exchange`. Per-user types store a credential against the caller's identity, so the upstream API sees the individual user rather than a shared account.

[Token exchange](https://docs.getbifrost.ai/mcp/auth/token-exchange), an enterprise feature, exchanges the caller's identity-provider token through RFC 8693 for a short-lived token scoped to the upstream server's audience; the original token is never sent upstream. The [governance overview](https://www.getmaxim.ai/bifrost/resources/governance) shows how these grants sit alongside model budgets and rate limits on the same key.

| Layer | Bifrost control | Spec concept it extends |
| --- | --- | --- |
| Client to gateway | `headers`, `both`, or `oauth` auth mode | OAuth 2.1 resource server, RFC 9728 |
| Tool grant | Virtual key `mcp_configs`, Virtual MCPs | Scopes (per tool instead of per string) |
| Per-request narrowing | `x-bf-mcp-include-tools` header | Least-privilege scope selection |
| Gateway to upstream | Six auth types, incl. token exchange | No token passthrough |

## Agents, Delegation, and MCP Tool Access

Agent-to-agent calls add a delegation step the MCP authorization spec does not cover: an agent that receives a request then makes its own tool calls. In Bifrost, permission to call an agent is a separate grant from MCP tool access, so authorizing an agent never authorizes the tools that agent uses.

[Agent Gateway in Bifrost](https://www.getmaxim.ai/bifrost/blog/introducing-agent-gateway-in-bifrost-one-gateway-for-models-tools-and-agents), launched on October 20, 2026, brings A2A v1 agent calls into the same gateway as model and MCP traffic. A virtual key is given access to specific agents, and authentication enforcement rejects anonymous calls.

![A caller's virtual key passes the Bifrost agent access check, the trusted agent forwards that credential, and Bifrost checks the caller's tool allow-list before the MCP server runs](https://articles-images-cdn.t3.tigrisfiles.io/diagrams/mcp-authorization/mcp-authorization-agent-delegation.png)

*Figure 4: Permission to call an agent does not grant its tools; a forwarded credential keeps the caller's own tool rules in force.*

By default, Bifrost removes the caller's credential before forwarding a request to the agent. For a trusted agent, enabling "Forward Bifrost authentication" lets the agent reuse that credential on its model and tool calls, which then follow the original caller's access rules and budgets. Otherwise the agent uses its own Bifrost key and its permissions. The [agent access control docs](https://docs.getbifrost.ai/features/agent-gateway/overview) cover both setups.

## Auditing MCP Authorization Decisions

Authorization is only verifiable if decisions are recorded centrally. Bifrost records MCP tool calls in its request logs alongside LLM calls, and Bifrost Enterprise adds signed audit logs of administrative activity, such as who changed a virtual key's tool allow-list and when.

[Request logging](https://docs.getbifrost.ai/features/observability/default) captures MCP log entries, and any `x-bf-lh-*` header lands in each entry's metadata for tenant or team attribution. [Audit logs](https://docs.getbifrost.ai/enterprise/audit-logs) cover the other half: entries can be HMAC-signed, filtered by action and outcome, exported as JSON, JSON Lines, or Syslog, and archived to S3 or GCS.

Together they answer which tools a caller ran and who granted that access. The guide to [MCP audit logs for compliance](https://www.getmaxim.ai/articles/mcp-audit-logs-ensuring-compliance-in-enterprise-ai-applications/) maps these records to SOC 2 and HIPAA review workflows. For larger estates, [Access Profiles](https://docs.getbifrost.ai/enterprise/access-profiles) in Bifrost Enterprise define MCP tool access once per role and propagate it to every user holding the profile.

## Frequently Asked Questions

### What is the difference between MCP authentication and authorization?

MCP authentication proves who the client or user is, typically through an OAuth 2.1 login. MCP authorization decides what that identity may do: whether its token is valid for this server, whether its scopes cover the request, and, at a gateway, which tools it may call. Our [MCP authentication explainer](https://www.getmaxim.ai/articles/mcp-authentication-explained-oauth-api-keys-and-token-management/) covers the identity half in detail.

### Does MCP use OAuth 2.1?

Yes. The current MCP spec bases authorization on the OAuth 2.1 IETF draft, plus RFC 6750 bearer tokens, RFC 8414 metadata, RFC 9728 protected resource metadata, RFC 8707 resource indicators, and RFC 9207 issuer identification. Authorization servers must implement OAuth 2.1, and clients must use PKCE with S256 when capable. Bifrost serves this flow on its `/mcp` endpoint in the `both` and `oauth` [gateway auth modes](https://docs.getbifrost.ai/mcp/gateway).

### Is dynamic client registration still required for MCP?

No. In the 2026-07-28 revision, dynamic client registration (RFC 7591) is optional and marked deprecated. Clients should prefer pre-registered credentials, then Client ID Metadata Documents, and fall back to dynamic registration only when the authorization server advertises a `registration_endpoint`. It remains for backwards compatibility.

### Can MCP scopes control access to individual tools?

Only if a server defines one scope per tool, which few do. The spec treats scopes as server-defined strings and does not map them to tools. Per-tool control is more reliable at a gateway: in Bifrost, a virtual key lists the exact tools it may call per server, and the same list filters both tool discovery and execution, as described on the [MCP gateway resource page](https://www.getmaxim.ai/bifrost/resources/mcp-gateway).

### What is the confused deputy problem in MCP?

It is an attack where an MCP server proxying a third-party API reuses an earlier user consent to obtain tokens for an attacker. The spec requires proxy servers that use a static client ID to collect user consent for each dynamically registered client, and it forbids passing client tokens through to upstream APIs. Bifrost's token exchange obtains a separate upstream token instead of forwarding the caller's for the same reason.

### Where should MCP authorization be enforced?

Token and scope checks belong on each MCP server, as the spec requires. Per-tool and per-caller rules are easier to keep consistent at a central gateway, because one policy then covers servers with OAuth, static keys, or no auth. The post on [Bifrost MCP gateway access control](https://www.getmaxim.ai/bifrost/blog/bifrost-mcp-gateway-access-control-cost-governance-and-92-lower-token-costs-at-scale) shows that model running at scale.

## Getting Started with MCP Authorization in Bifrost

MCP authorization in the spec secures each token and scope; per-tool permissions, delegation, and a central record are what teams add for production. Bifrost provides them in one gateway: OAuth 2.1 or key-based access to `/mcp`, deny-by-default tool grants on virtual keys, per-server upstream credentials, and audit trails, with [enterprise deployment](https://www.getmaxim.ai/bifrost/enterprise) options for in-VPC and on-prem environments. To see per-tool MCP authorization running against your own servers, [book a demo](https://getmaxim.ai/bifrost/book-a-demo) with the Bifrost team.

## Read next

[![MCP Connectors Explained: How They Work and How to Govern Them](https://storage.ghost.io/c/84/03/8403f2f6-141c-411a-8f55-a32d4291533e/content/images/size/w720/2026/10/mcp-connectors-explained-how-they-work-and-how-to-govern-the-bifrost-1920x1080.png) An MCP connector is the configured link between an AI application and an external system, made of an MCP client, a transport, credentials, and an MCP server. This guide explains how connectors work, where they break down at scale, and how an MCP gateway governs them centrally.](https://www.getmaxim.ai/articles/mcp-connectors/)

[![Top 5 Gateways for Hosting and Securing Remote MCP Servers in 2026](https://storage.ghost.io/c/84/03/8403f2f6-141c-411a-8f55-a32d4291533e/content/images/size/w720/2026/10/top-5-gateways-for-hosting-and-securing-remote-mcp-servers-i-bifrost-1920x1080@2x.png) Remote MCP servers expose tools to AI agents over HTTP, which makes authentication and tool access the first problems to solve. This guide compares five gateways for hosting and securing them, including Bifrost, Cloudflare, Azure API Management, and Amazon Bedrock AgentCore Gateway.](https://www.getmaxim.ai/articles/remote-mcp-server-gateways/)

[![Top 5 MintMCP Alternatives for Governing MCP in 2026](https://storage.ghost.io/c/84/03/8403f2f6-141c-411a-8f55-a32d4291533e/content/images/size/w720/2026/10/top-5-mintmcp-alternatives-for-governing-mcp-in-2026-bifrost-1920x1080.png) MintMCP, now renamed Mintive, is a managed MCP gateway for governing which tools AI agents can reach. This guide compares five MintMCP alternatives, including Bifrost, Docker MCP Gateway, IBM ContextForge, and Obot, on deployment, tool-level access control, identity, and audit.](https://www.getmaxim.ai/articles/mintmcp-alternatives/)

## More in MCP Gateway

[![Top 5 Gateways for Hosting and Securing Remote MCP Servers in 2026](https://storage.ghost.io/c/84/03/8403f2f6-141c-411a-8f55-a32d4291533e/content/images/size/w720/2026/10/top-5-gateways-for-hosting-and-securing-remote-mcp-servers-i-bifrost-1920x1080@2x.png) Remote MCP servers expose tools to AI agents over HTTP, which makes authentication and tool access the first problems to solve. This guide compares five gateways for hosting and securing them, including Bifrost, Cloudflare, Azure API Management, and Amazon Bedrock AgentCore Gateway.](https://www.getmaxim.ai/articles/remote-mcp-server-gateways/)

[![MCP Connectors Explained: How They Work and How to Govern Them](https://storage.ghost.io/c/84/03/8403f2f6-141c-411a-8f55-a32d4291533e/content/images/size/w720/2026/10/mcp-connectors-explained-how-they-work-and-how-to-govern-the-bifrost-1920x1080.png) An MCP connector is the configured link between an AI application and an external system, made of an MCP client, a transport, credentials, and an MCP server. This guide explains how connectors work, where they break down at scale, and how an MCP gateway governs them centrally.](https://www.getmaxim.ai/articles/mcp-connectors/)

```json
{
    "@context": "https://schema.org",
    "@type": "Article",
    "publisher": {
        "@type": "Organization",
        "name": "Maxim Articles",
        "url": "https://www.getmaxim.ai/articles/",
        "logo": {
            "@type": "ImageObject",
            "url": "https://storage.ghost.io/c/84/03/8403f2f6-141c-411a-8f55-a32d4291533e/content/images/size/w256h256/2025/08/thumbnail.png",
            "width": 60,
            "height": 60
        }
    },
    "author": {
        "@type": "Person",
        "name": "Kuldeep Paul",
        "image": {
            "@type": "ImageObject",
            "url": "https://storage.ghost.io/c/84/03/8403f2f6-141c-411a-8f55-a32d4291533e/content/images/2025/08/1727978381919.jpeg",
            "width": 800,
            "height": 800
        },
        "url": "https://www.getmaxim.ai/articles/author/kuldeep/",
        "sameAs": []
    },
    "headline": "MCP Authorization: OAuth Scopes and Per-Tool Permissions",
    "url": "https://www.getmaxim.ai/articles/mcp-authorization/",
    "datePublished": "2026-10-21T21:33:00.000Z",
    "dateModified": "2026-10-23T21:33:18.000Z",
    "image": {
        "@type": "ImageObject",
        "url": "https://storage.ghost.io/c/84/03/8403f2f6-141c-411a-8f55-a32d4291533e/content/images/size/w1200/2026/10/mcp-authorization-oauth-scopes-and-per-tool-permissions-bifrost-1920x1080.png",
        "width": 1200,
        "height": 675
    },
    "keywords": "MCP Gateway",
    "description": "MCP authorization controls which clients may call a protected MCP server and what their tokens allow. This guide walks through the OAuth 2.1 flow in the current MCP spec, scopes and step-up, token audience rules, the gaps teams hit in production, and per-tool enforcement at a gateway.",
    "mainEntityOfPage": "https://www.getmaxim.ai/articles/mcp-authorization/"
}
```
