Codex Desktop MCP OAuth DCR registers fewer scopes than it later requests

Open 💬 2 comments Opened May 18, 2026 by 4bmis

Description

Codex Desktop fails OAuth login for a remote Streamable HTTP MCP server that supports Dynamic Client Registration (DCR).

The authorization server metadata advertises DCR and the following scopes:

{
  "issuer": "https://clerk.actionbook.dev",
  "authorization_endpoint": "https://clerk.actionbook.dev/oauth/authorize",
  "token_endpoint": "https://clerk.actionbook.dev/oauth/token",
  "registration_endpoint": "https://clerk.actionbook.dev/oauth/register",
  "scopes_supported": [
    "openid",
    "profile",
    "email",
    "public_metadata",
    "private_metadata",
    "offline_access"
  ],
  "code_challenge_methods_supported": ["S256"]
}

Codex Desktop appears to dynamically register an OAuth client without registering the same scopes that it later requests during the authorization step. The flow reaches the browser callback, but authorization fails with:

OAuth provider returned `invalid_scope`: The requested scope is invalid, unknown, or malformed. The OAuth 2.0 Client is not allowed to request scope `openid`.

The callback URL contains:

error=invalid_scope&error_description=The requested scope is invalid, unknown, or malformed. The OAuth 2.0 Client is not allowed to request scope `openid`.

Expected behavior

Codex Desktop should keep the DCR registration request and the subsequent authorization request consistent.

If Codex Desktop later requests:

scope=openid profile email ...

at /oauth/authorize, then it should register the dynamic client with the same requested/allowed scopes at /oauth/register, or only request scopes that were successfully registered/allowed for that dynamic client.

Actual behavior

DCR succeeds far enough for Codex Desktop to proceed to authorization, but the dynamically registered OAuth client is not allowed to request openid. Codex Desktop then requests openid during authorization, causing the authorization server to reject the flow with invalid_scope.

Why this appears client-side

The same MCP server works with Claude against the same authorization server. In that flow, the DCR registration scopes and authorization request scopes are consistent.

This does not appear to be a case where the MCP server lacks DCR support. The problem is that Codex Desktop registration and authorization use inconsistent scope sets.

Environment

  • Product: Codex Desktop
  • MCP transport: Streamable HTTP
  • OAuth provider: Clerk OAuth with Dynamic Client Registration enabled
  • MCP URL: https://edge.actionbook.dev/mcp

View original on GitHub ↗

2 Comments

mjherich · 3 months ago

Hitting the same bug independently — different MCP server, different Clerk dev instance, identical failure.

Two extra data points that corroborate the reporter's diagnosis:

  1. PRM scope advertising doesn't change anything. I tried scopes_supported: ["openid", "profile", "email"] and then expanded to ["openid", "profile", "email", "offline_access"]. Codex Desktop hits the same invalid_scope for openid in both cases — so the DCR scope set Codex sends to Clerk isn't being driven by what the PRM exposes.
  2. Claude Desktop works against the exact same MCP server + Clerk AS. So the server-side metadata, Clerk's DCR endpoint, and the scope set are all fine; the inconsistency is purely between Codex's DCR registration request and its subsequent /authorize request.

Verbatim callback for the record:

error=invalid_scope&error_description=The+requested+scope+is+invalid%2C+unknown%2C+or+malformed.+The+OAuth+2.0+Client+is+not+allowed+to+request+scope+%27openid%27.
fortuna · 1 month ago

Reproduced on chatgpt.com using a developer-mode app connected to AgentMail at https://mcp.agentmail.to/mcp. The OAuth callback fails with the identical invalid_scope error stating that the dynamically registered client is not allowed to request openid. This suggests the scope mismatch also affects the hosted ChatGPT connector flow, rather than only Codex Desktop.