Skip to content

[Server][Auth] SEP-2350: Emit per-operation scopes in insufficient_scope 403 responses (RFC 6750 §3.1) #362

Description

@chr-hertel

Implements the server-side portion of SEP-2350 for the MCP Spec 2026-07-28 release.

Tracked by umbrella #338. Client-side scope accumulation is covered by existing #322.

Spec summary

Aligns 403 insufficient_scope responses with RFC 6750 §3.1 — servers report only scopes needed for the current operation, NOT the union of previously granted. Clients are responsible for computing the union of (previously requested ∪ newly challenged) scopes on step-up re-authorization.

PHP SDK changes

  • src/Server/Transport/Http/OAuth/ 403 responses must emit ONLY the scopes required for the requested operation in WWW-Authenticate: Bearer error="insufficient_scope" scope="...".
  • Audit current middleware — likely needs adjustment if it emits a cumulative scope set.

Related

Activity

  1. added
    ServerIssues & PRs related to the Server component
    P1Significant bug affecting many users, highly requested feature
    authIssues and PRs related to Authentication / OAuth
    improves spec complianceImproves consistency with other SDKs such as TyepScript
    enhancementRequest for a new feature that's not currently supported
    on May 26, 2026
  2. added
    2026-07-28All issues and PRs related to the spec release 2026-07-28
    on May 26, 2026
  3. wWzZb commented on Aug 14, 2026

    @wWzZb
    Contributor

    I'd like to work on this. I checked the current main, and most of the server-side SEP-2350 path is already in place: JwtTokenValidator::requireScopes() puts the operation's full required scope set on the 403 result, and AuthorizationMiddleware prefers those result scopes.

    The remaining edge case is AuthorizationResult::forbidden() without scopes. AuthorizationMiddleware::resolveScopes() then falls back to the resource-wide scopes_supported, so a 403 can advertise unrelated scopes instead of the requirements for the current operation.

    I propose keeping the scopes_supported fallback for initial 401 challenges, while making 403 challenges use only scopes explicitly carried by AuthorizationResult. If a custom validator returns a 403 without scopes, the header would omit scope rather than infer it from PRM. This preserves the current public factory and is allowed by RFC 6750, where the 403 scope attribute is optional.

    I'd cover explicit per-operation scopes, omitted scope on a scope-less 403, and unchanged 401 fallback behavior. Does that match the intended scope for this issue?

  4. removed
    P1Significant bug affecting many users, highly requested feature
    on Aug 19, 2026
  5. chr-hertel commented on Aug 19, 2026

    @chr-hertel
    MemberAuthor

    Already correctly scoped since the OAuth middleware landed in #221 — JwtTokenValidator::requireScopes() reports only the scopes required for the current operation, never a cumulative set. No change needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    2026-07-28All issues and PRs related to the spec release 2026-07-28ServerIssues & PRs related to the Server componentauthIssues and PRs related to Authentication / OAuthenhancementRequest for a new feature that's not currently supportedimproves spec complianceImproves consistency with other SDKs such as TyepScript

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions