-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Problem
https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization changes the semantic meaning of https://datatracker.ietf.org/doc/html/rfc6750#section-3.1 by placing scope accumulation responsibility on the server rather than the client. This contradicts the RFC, creates an impossible requirement for stateless servers, and leads to infinite re-authorization loops in practice.
what RFC 6750 Section 3.1 says
RFC 6750 3.1 defines the scope attribute in WWW-Authenticate as:
If the request included an access token and failed authentication, the resource server SHOULD include the "scope" attribute with the value of the scope necessary to access the requested resource.
The key phrase is "the scope necessary to access the requested resource" - the specific resource being accessed, not a union of every scope the client might need across all operations, not a union of the client's existing scopes + scopes required.
what the MCP spec says instead
The https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#runtime-insufficient-scope-errors section defines three server strategies:
- Minimum approach: "Include the newly-required scopes for the specific operation. Include any existing granted scopes as well, if they are required, to prevent clients from losing previously granted permissions."
- Recommended approach: "Include both existing relevant scopes and newly required scopes to prevent clients from losing previously granted permissions"
- Extended approach: "Include existing scopes, newly required scopes, and related scopes that commonly work together"
All three approaches expect the server to include "existing granted scopes" in the 403 challenge. This changes the RFC 6750 3.1 semantics from "scopes needed for this resource" to "scopes needed for this resource plus scopes the client already has".
This is problematic because:
- It contradicts RFC 6750 3.1. The RFC says the scope attribute describes what's needed for the requested resource. For example, if an operation requires
files:write, including unrelated scopes likeuser:profilein the challenge misrepresents the requirements of that operation. The server should report what this operation needs, not what the client previously had. - It requires server-side client state tracking. To include "existing granted scopes," the server must know what scopes the client's current token carries. Stateless servers that validate tokens and report missing scopes for the current operation cannot do this without inspecting the token - which may be opaque, or may not enumerate scopes in a way the resource server can parse.
- It's the wrong abstraction. The server knows what a specific operation requires. The client knows what scopes it has accumulated across operations. Scope accumulation across a session is inherently a client-side concern.
Missing Guidance
The https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#scope-selection-strategy only covers the initial 401 handshake. The https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#step-up-authorization-flow at step 2 says:
Determine required scopes as outlined in Scope Selection Strategy.
But the Scope Selection Strategy says nothing about merging or accumulating scopes. If a client follows this literally during step-up — replacing its scope set with the 403 challenge's scope — previously granted scopes are lost.
This is further complicated by the https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#protected-resource-metadata-discovery-requirements guidance:
Clients MUST treat the scopes provided in the challenge as authoritative for satisfying the current request.
"Authoritative" here is ambiguous: does it mean "these scopes are required for this operation" or "these are the only scopes the client should request"?
Meanwhile, the https://modelcontextprotocol.io/specification/2025-11-25/basic/security_best_practices#scope-minimization section actively encourages per-operation scope challenges:
- "Emit precise scope challenges; avoid returning the full catalog"
- "Incremental elevation via targeted
WWW-Authenticate scope="..."challenges"
Servers following these best practices will emit per-operation scopes. Without client-side accumulation guidance, this leads to scope thrashing and re-authorization loops.
Proposed Changes
- Align Server Scope Management with RFC 6750 3.1
Reframe the server strategies in https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#runtime-insufficient-scope-errors to match the RFC: the scope attribute in 403 responses describes the scopes needed for the requested operation. Remove the expectation that servers include "existing granted scopes" - that's the client's responsibility.
- Add explicit client-side scope accumulation to the step-up authorizaiton flow
Step 2 of the https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#step-up-authorization-flow should specify that clients SHOULD compute the union of previously requested scopes and the scopes from the current challenge before initiating re-authorization. For example:
Determine required scopes by computing the union of the client's previously requested scope set and the scopes from the current challenge. This ensures previously granted permissions are preserved when servers emit per-operation scope challenges per RFC 6750 3.1.
- Clarify "authoritative" semantics
Clarify in https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#protected-resource-metadata-discovery-requirements that "authoritative for satisfying the current request" means the challenged scopes are required for this operation, not that they are the exclusive set the client should request:
Clients MUST treat the scopes provided in the challenge as authoritative for the current operation. When re-authorizing, clients SHOULD include these scopes alongside any previously granted scopes to avoid losing permissions needed for other operations.
Related
- TypeScript SDK issue: Scope overwrite in 403 upscoping prevents progressive authorization for servers with per-operation scopes typescript-sdk#1582
- TypeScript SDK fix: (client-side scope union): fix(client): accumulate scopes across 401/403 auth challenges typescript-sdk#1618