[BUG] Missing `scope` Parameter in Dynamic Client Registration and Authorization Requests
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:
- Configure the Claude Code client to connect to an MCP server that supports OAuth2 Authorization Code Flow with PKCE and dynamic client registration.
- Initiate the connection process from the Claude Code client.
- Observe the network requests and server-side logs.
Expected Behavior:
- During dynamic client registration (
POST /register), the Claude client should include ascopeparameter in its request body, indicating the desired permissions (e.g.,mcp:read,mcp:write,offline_access). - Subsequently, when redirecting to the authorization endpoint (
/oauth2/auth), the Claude client should include thescopeparameter in the query string, reflecting the permissions it seeks from the user. - 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:
- The Claude Code client successfully performs dynamic client registration, but the
scopeparameter is entirely absent from thePOST /registerrequest body. - The authorization URL generated by the Claude client and sent to the authorization server also lacks the
scopeparameter.
Technical Details:
1. OAuth2 Discovery Endpoint (/.well-known/oauth-authorization-server) - Supported Scopes:
Our system correctly advertises the following supported scopes:
```json snippet
{
"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.
20 Comments
+1
We're seeing the same thing, our MCP works in Claude Desktop but claude code is not requesting any scopes
Hi All, we are also seeing same behavior. Can Claude team please share us any update on this?
@justin-yi-wang, FYI
+1
anyone triaging this bug?
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)
https://github.com/anthropics/claude-code/issues/2527
+1
+1 also seeing this
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)
@vobornik where is this coming from:
The referenced RFC section (https://datatracker.ietf.org/doc/html/rfc6749#section-3.3) is stating the opposite:
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).
+1
We are implementing DCR and the auth code grant flow fails because of this issue. Is there a way to provide the client_id in the config so we can complete the flow without DCR?
I can't register Vercel's MCP server with Claude Code as the URL that Claude Code passes for the scopes is wrong.
(ref: https://vercel.com/docs/mcp/vercel-mcp#claude-code)
Expected:
...&scopes=openid+email+offline_access+profile&prompt=consent...
Actual:
...&scope=openid+email+offline_access+profile&prompt=consent...
This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
This is still an issue, also working around this issue by proxying DCR requests
+1
Still an issue and still need to keep proxy for DCR requests (ugly solution)
~~This may have been addressed. If your MCP server implements the scope parameter in the WWW-Authenticate header as specified in the https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#runtime-insufficient-scope-errors, Claude Code will include the scopes in subsequent authorization requests.~~
~~Per the spec, when the server returns a 403 Forbidden with insufficient scope:
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope",
scope="mcp:read mcp:write offline_access",
resource_metadata="https://example.com/.well-known/oauth-protected-resource"~~
~~Claude Code picks up these scopes and includes them in the OAuth flow.~~
~~This aligns with https://datatracker.ietf.org/doc/html/rfc6750#section-3 for Bearer token error handling.~~
~~However, I ran into a separate blocking issue: the redirect_uri contains an unencoded space (/call back instead of /callback), which breaks the OAuth flow entirely. See #17176.~~
Confirming this issue still exists —
scopeis not included in the DCR registration request.Update: RFC 7591 Section 2 states scope is optional:
> "If omitted, an authorization server MAY register a client with a default set of scopes."
However, Claude Code should still send
scopeduring DCR for the following reasons:Claude Code should send scopes during registration to be a good OAuth citizen.
Experiencing the same issue. After investigating, I found there are actually two separate bugs:
Bug 1: Missing scope in DCR request
Claude Code doesn't include the scope parameter when registering via Dynamic Client Registration (POST /connect/dcr).
Workaround: I modified my auth server to apply default scopes when creating DCR clients.
Bug 2: Missing scope in Authorization request
Even with the DCR workaround above, Claude Code still doesn't include the scope parameter in the authorization request (GET /connect/authorize). My auth server then rejects with "scope is missing" (as required by RFC 6749 Section 3.3).
---
@bluedog13 The WWW-Authenticate header approach you mentioned might fix Bug 1, but you'll still hit Bug 2 since Claude Code doesn't pass scopes to the authorize endpoint either.
Could the Claude team provide an update on this? Both issues seem to stem from the same root cause: Claude Code not reading/using scopes_supported from the OAuth protected resource metadata. Thanks!
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)
+1
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-scopeflag: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.