Skip to content

[BUG] Missing scope Parameter in Dynamic Client Registration and Authorization Requests #4540

Closed

Description

@vobornik

Description:

We have observed that the Claude Code client, when attempting to integrate with an OAuth2 Authorization Server (ORY Hydra) and a Memory Control Plane (MCP) endpoint, consistently fails to include the scope parameter during both the dynamic client registration request and the subsequent authorization request. This behavior deviates from standard OAuth2 practices and prevents proper scope negotiation and authorization.

Our system correctly advertises supported scopes via the OAuth2 Discovery Endpoint (/.well-known/oauth-authorization-server), but the Claude client does not appear to utilize this information when constructing its requests.

Steps to Reproduce:

  1. Configure the Claude Code client to connect to an MCP server that supports OAuth2 Authorization Code Flow with PKCE and dynamic client registration.
  2. Initiate the connection process from the Claude Code client.
  3. Observe the network requests and server-side logs.

Expected Behavior:

  1. During dynamic client registration (POST /register), the Claude client should include a scope parameter in its request body, indicating the desired permissions (e.g., mcp:read, mcp:write, offline_access).
  2. Subsequently, when redirecting to the authorization endpoint (/oauth2/auth), the Claude client should include the scope parameter in the query string, reflecting the permissions it seeks from the user.
  3. According to RFC 6749, Section 3.3 (Access Token Scope): "If the client omits the scope parameter when requesting authorization, the authorization server MUST NOT assume a default scope. Instead, the authorization server SHOULD either deny the request or process the request with a zero-length scope." Therefore, the client is responsible for explicitly requesting scopes.

Actual Behavior:

  1. The Claude Code client successfully performs dynamic client registration, but the scope parameter is entirely absent from the POST /register request body.
  2. The authorization URL generated by the Claude client and sent to the authorization server also lacks the scope parameter.

Technical Details:

1. OAuth2 Discovery Endpoint (/.well-known/oauth-authorization-server) - Supported Scopes:

Our system correctly advertises the following supported scopes:

{
  "scopes_supported": [
    "mcp:read",
    "mcp:write",
    "mcp:search",
    "offline_access"
  ],
 "response_types_supported": [
    "code"
  ]
}

2. MCP Server Log - Dynamic Client Registration Request (POST /register):

The mcp service logs show the incoming request data for dynamic client registration. As seen below, the scope parameter is missing from the request_data payload:

2025-07-27 17:42:31,108 - main - INFO - 2025-07-27T17:42:31.108694 [info     ] Dynamic client registration requested [main] has_client_id=False request_data={'client_name': 'Claude Code (LLMory)', 'redirect_uris': ['http://localhost:65068/callback'], 'grant_types': ['authorization_code', 'refresh_token'], 'response_types': ['code'], 'token_endpoint_auth_method': 'none'}

3. Claude Debug Output / Auth Proxy Log - Authorization URL:

The authorization URL generated by the Claude client and captured in our auth-proxy logs (and also visible in the Claude debug output) explicitly lacks the scope parameter:

[DEBUG] MCP server "LLMory": Authorization URL: https://mcp.llmory.com/oauth2/auth?response_type=code&client_id=claude-code--llmory-d255d3fc&code_challenge=nYb27OxYnL7l_tIs3lj5pzh0qBrEtG_j-_5YhqSpV_4&code_challenge_method=S256&redirect_uri=http%3A%2F%2Flocalhost%3A63692%2Fcallback&state=Zy_iztgf_LsRux2bgLa1v7qZcoyCH_6cxu1QhDgZb2w&resource=https%3A%2F%2Fmcp.llmory.com%2F

(Note: client_id and redirect_uri may vary based on the specific run, but the absence of scope is consistent.)

Impact:

This issue prevents the Claude client from requesting necessary permissions from the user, leading to:

  • Functional limitations: The client will not receive an access token with the required scopes to interact with the MCP server's protected resources.
  • User experience issues: The consent screen presented to the user will not display any requested permissions, potentially confusing the user and hindering the authorization process.

Recommendation:

We request that the Claude Code client be updated to:

  1. Properly parse and utilize the scopes_supported (and ideally mcp_default_scopes) values from the OAuth2 Discovery Endpoint.
  2. Include the appropriate scope parameter in both dynamic client registration requests and authorization requests, as per RFC 6749.

Activity

  1. akshaycj commented on Aug 1, 2025

    @akshaycj

    +1

  2. owlas commented on Aug 1, 2025

    @owlas

    We're seeing the same thing, our MCP works in Claude Desktop but claude code is not requesting any scopes

  3. SudhakarGitMS commented on Aug 5, 2025

    @SudhakarGitMS

    Hi All, we are also seeing same behavior. Can Claude team please share us any update on this?

    @justin-yi-wang, FYI

  4. HansOlavMyklebust commented on Aug 18, 2025

    @HansOlavMyklebust

    +1

  5. SudhakarGitMS commented on Sep 8, 2025

    @SudhakarGitMS

    anyone triaging this bug?

  6. tcvall86 commented on Sep 9, 2025

    @tcvall86

    We are also running into this issue and it is blocking us from using claude code effectivly in combination with the requirement of a dynamic port usage on the local client. This is in essence the same issue as this though (although this is a bit more specific in the requirement)

    #2527

  7. dennismeister93 commented on Sep 11, 2025

    @dennismeister93

    +1

  8. EDjur commented on Sep 16, 2025

    @EDjur

    +1 also seeing this

  9. pmig commented on Sep 16, 2025

    @pmig

    For folks interested in a work around: We built a Gateway/Proxy that intercepts Claude Code’s dynamic client registration request and injects a scope parameter so the authorization server registers the client with the desired scopes:

    https://github.com/hyprmcp/mcp-gateway/blob/main/oauth/dynamic_client_registration.go#L79-L81

    You can put it in front of your remote MCP server and auth will work =). We are also happy to host your MCP server on our platform (https://hyprmcp.com)

  10. timofurrer commented on Sep 16, 2025

    @timofurrer

    @vobornik where is this coming from:

    According to RFC 6749, Section 3.3 (Access Token Scope): "If the client omits the scope parameter when requesting authorization, the authorization server MUST NOT assume a default scope. Instead, the authorization server SHOULD either deny the request or process the request with a zero-length scope." Therefore, the client is responsible for explicitly requesting scopes.

    The referenced RFC section (https://datatracker.ietf.org/doc/html/rfc6749#section-3.3) is stating the opposite:

    If the client omits the scope parameter when requesting
    authorization, the authorization server MUST either process the
    request using a pre-defined default value or fail the request
    indicating an invalid scope. The authorization server SHOULD
    document its scope requirements and default value (if defined).

  11. 10 remaining items

  12. ardabeyazoglu commented on Feb 27, 2026

    @ardabeyazoglu

    Most api servers support many scopes, and we do not always want LLM's to have all of the scopes available. Since we have to expose all of them in .well-known spec endpoints, claude sees them and require all of them right now. This is very inconvenient.

    I see 2 reasonable way of dealing with this:

    1. Claude desktop/code adds a "scope" input in connector configurations, just like "client id", so user provides the scopes. At the end of the day the same user created the oauth2 client id, so it is not too much to ask for also scopes.
    2. If claude sends some "claude" specific header to oauth2 server backends, we can customize the exposed scopes based on the header to tailor them for claude (and all other AI agents)
  13. mihailozepina commented on Apr 6, 2026

    @mihailozepina

    +1

  14. shigechika commented on Apr 6, 2026

    @shigechika

    For anyone hitting this while connecting through a stdio relay — mcp-stdio passes scopes correctly in both the authorization request and token exchange. You can specify the desired scope via the --oauth-scope flag:

    {
      "mcpServers": {
        "my-server": {
          "command": "mcp-stdio",
          "args": ["--oauth", "--oauth-scope", "mcp:read mcp:write offline_access", "https://my-mcp-server.example.com/mcp"]
        }
      }
    }

    This won't help if you're relying on Claude Code's built-in HTTP transport directly, but it's a workaround for stdio-based setups where the scope omission blocks the auth flow.

  15. claude commented on Aug 19, 2026

    @claude
    Contributor

    Scope handling for MCP OAuth is now explicit and documented at https://code.claude.com/docs/en/mcp#restrict-oauth-scopes:

    • You can pin exactly what is requested with "oauth": { "scopes": "mcp:read mcp:write" } on the server entry (space-separated, RFC 6749 §3.3 format); this takes precedence over anything discovered.
    • Without it, current versions request the scope named by the server's WWW-Authenticate challenge or its protected-resource metadata, and deliberately no longer request the whole scopes_supported catalog from discovered authorization-server metadata (that caused invalid_scope rejections on several IdPs). If neither source names a scope, no scope parameter is sent — so for a setup like the one described (scopes advertised only via AS discovery), either set oauth.scopes or have the MCP server advertise its scopes in its protected-resource metadata / 401 challenge.
    • offline_access is appended automatically when the authorization server advertises it, so refresh works without a new sign-in.

    🤖 Generated with Claude Code


    Generated by Claude Code

  16. github-actions commented on Oct 9, 2026

    @github-actions

    This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.

  17. locked as resolved and limited conversation to collaborators on Oct 9, 2026
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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions