MCP OAuth: Codex does not re-register (DCR) on invalid_client / expired refresh token — requires manual re-auth
Summary
When an MCP server's refresh token is rotated or expired, Codex logs Token refresh not possible, re-authorization required and stops. It does not discard the dead client_id and POST to the advertised registration_endpoint to re-register, as OAuth 2.1 / the MCP Dynamic Client Registration (DCR) spec expect. Users must manually log out and re-add the server to recover.
Evidence
From ~/.codex/logs_2.sqlite (target rmcp::transport::auth):
Access token expired or nearly expired, refreshing. remaining_secs=0
refresh token present, attempting refresh
Token refresh not possible, re-authorization required.
error=OAuth token refresh failed: Server returned error response: invalid_grant: refresh token ...
After this point there is no subsequent /register call — the flow just halts. Over the lifetime of this install: 0 events handling invalid_client, only 3 /register events total.
Tested against a spec-compliant FastMCP OAuthProxy server that, for an unknown/stale client_id, returns:
POST /token→401 {"error":"invalid_client"}GET/POST /authorize→400 {"error":"invalid_request","error_description":"Client ID '...' is not registered with this server. MCP clients should automatically re-register by sending a POST request to the registration_endpoint and retry authorization...","registration_endpoint":"https://.../register"}
The server explicitly advertises the registration_endpoint and instructs the client to re-register. Codex ignores it.
Environment: Codex CLI 0.142.0 (macOS, compiled Rust binary). MCP OAuth credentials stored in macOS Keychain under service Codex MCP Credentials.
Impact
Any MCP server that rotates refresh tokens or restarts (losing server-side token state) logs every user out until they manually re-authenticate. codex mcp logout is an unreliable workaround — it is per-server/per-URL-hash scoped and has known cleanup gaps (#25002, #28201).
Expected behavior
On invalid_client (or an unrecoverable refresh failure), Codex should automatically discard the stored client_id + tokens, re-run dynamic client registration against the server's advertised registration_endpoint, and retry authorization — per the MCP authorization spec — rather than stopping and requiring manual intervention.
2 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Adding full environment details:
| | |
|---|---|
| macOS | 26.5 (build 25F71) |
| Codex CLI | 0.142.0 (
codex-cli 0.142.0, installed via Volta / npm@openai/codex) || Codex Desktop | 26.616.71553 (build 4265) |
Both the CLI and the Desktop app exhibit the behavior — they share
~/.codex, and MCP OAuth credentials are stored in the macOS Keychain under serviceCodex MCP Credentials.