MCP OAuth DCR requests unrelated authorization-server scopes instead of resource scopes
What version of Codex CLI is running?
codex-cli 0.145.0
The same scope-selection behavior is still present in the current source / 0.146.0 alpha line as checked on 2026-07-25.
What subscription do you have?
ChatGPT subscription (exact tier is not relevant to this MCP OAuth issue).
Which model were you using?
N/A — this happens in codex mcp add before a model session starts.
What platform is your computer?
Darwin 25.5.0 arm64 arm (macos-aarch64), npm installation.
What terminal emulator and version are you using (if applicable)?
Codex desktop embedded terminal / zsh.
Codex doctor report
{
"schemaVersion": 1,
"overallStatus": "fail (unrelated local install/sandbox diagnostics)",
"codexVersion": "0.145.0",
"platform": "macos-aarch64",
"installMethod": "npm",
"authMode": "chatgpt",
"mcpServers": 3
}
The complete report is not included because it contains local usernames and filesystem paths. Its MCP/network failures were caused by the restricted diagnostic sandbox; the OAuth flow and MCP tool calls work when run normally.
What issue are you seeing?
For an OAuth-protected MCP server, the protected-resource metadata advertises only the scopes relevant to that resource:
{
"resource": "https://mcp.example.com/mcp",
"authorization_servers": ["https://auth.example.com/"],
"scopes_supported": [
"openid",
"email",
"profile",
"offline_access",
"example:mcp"
]
}
The authorization server is shared by other applications, so its global RFC 8414 / OIDC metadata also advertises unrelated scopes such as phone, roles, and application-specific API scopes.
Running:
codex mcp add example --url https://mcp.example.com/mcp
causes Codex's dynamic client registration request to include at least the unrelated phone scope. A DCR policy that intentionally permits only the MCP resource scopes correctly rejects the registration:
Detected OAuth support. Starting OAuth flow…
Error: Registration failed: Dynamic registration failed: Registration failed:
HTTP 400 Bad Request: {
"error": "invalid_client_metadata",
"error_description": "scope 'phone' is not allowed: only openid email profile offline_access example:mcp are supported."
}
This appears to mean the default login path is falling back to the authorization server's global scopes_supported instead of using the MCP protected resource's resource-specific scopes.
What steps can reproduce the bug?
- Configure an MCP Streamable HTTP endpoint with RFC 9728 protected-resource metadata.
- In that metadata, advertise only the scopes needed by the MCP resource.
- Use a shared authorization server whose global metadata advertises additional OIDC/application scopes, including
phone. - Make the DCR endpoint enforce an allowlist containing only the MCP resource scopes.
- Run:
``sh``
codex mcp add example --url https://mcp.example.com/mcp
- Observe that DCR fails because Codex requests
phone.
A useful control test is:
codex mcp login example \
--scopes openid,email,profile,offline_access,example:mcp
With the explicit scope list, dynamic registration succeeds. This confirms that discovery, the registration endpoint, and the allowed MCP scope set are valid.
On Codex 0.145.0, the flow can subsequently encounter the separate RFC 9207 callback-issuer bug already reported in openai/codex#31573 and openai/codex#34684. That is related OAuth work, but it is not the scope-selection bug reported here.
What is the expected behavior?
For automatic MCP OAuth registration, Codex should:
- Prefer
scopes_supportedfrom the RFC 9728 protected-resource metadata for the selected MCP resource. - If the user supplied
--scopes, use that explicit list. - Avoid registering every scope advertised globally by a shared authorization server.
- Request the minimum resource-specific scopes needed for the MCP connection.
A shared authorization server's global scope catalog is not a least-privilege registration request for one protected resource.
Additional information
Please do not work around this by accepting phone, roles, or arbitrary global scopes at the MCP DCR endpoint. Doing so expands client registration beyond the MCP resource's intended permissions and weakens least privilege.
After registering with the explicit resource scopes (using an older CLI for the already-reported issuer regression) and upgrading back to 0.145.0, the stored OAuth credentials were accepted and a real read-only MCP tool call succeeded. This isolates the failure to automatic OAuth client registration/scope selection rather than token validation or MCP transport.
4 Comments
Facing the same issue
it is caused probably due to https://github.com/openai/codex/pull/29022/changes
This isn't DCR related, it's happening because scope resolution from the MCP is being overwritten with the authority's supported scopes which are generally going to be larger than the scopes the protected resource supports. I've tested and confirmed a fix locally, but openai doesn't support uninvited pull requests. The fix is below if someone has the time to jump through the hoops to get this in:
``` diff
diff --git a/codex-rs/rmcp-client/src/auth_status.rs b/codex-rs/rmcp-client/src/auth_status.rs
index d29419b410..8fdac9264a 100644
--- a/codex-rs/rmcp-client/src/auth_status.rs
+++ b/codex-rs/rmcp-client/src/auth_status.rs
@@ -262,7 +262,14 @@ async fn discover_streamable_http_oauth_with_manager(
match authorization_manager.resolve_metadata().boxed().await {
Ok(resolution) if !resolution.source.is_discovered() => Ok(None),
Ok(resolution) => Ok(Some(StreamableHttpOAuthDiscovery {
})),
Err(AuthError::NoAuthorizationSupport) => Ok(None),
Err(err) => Err(err.into()),
same problem
Note: Codex Desktop can reproduce the scope bug without DCR. With a static client id defined under
mcp_servers.<servername>.oauth.client_idit reaches authorization but requests global authorization-server metadata scopes instead of MCP protected-resource metadata scopes. Therefore the underlying issue is confirmed to be scope selection, not dynamic registration.