[Bug] Claude Desktop OAuth flow fails to complete; tokens inaccessible without Claude Code CLI
Bug Description
Title: Claude Desktop cannot complete MCP OAuth flow on its own, but can use tokens obtained by Claude Code CLI
Summary
Claude Desktop fails to complete the OAuth 2.1 authorization flow for MCP servers that require auth. However, when the same MCP server is authenticated once via Claude Code CLI on the
same machine, Claude Desktop transparently picks up the resulting tokens and uses the server's tools without further prompting. The token-storage layer appears shared/compatible between
the two clients, but the OAuth client logic in Claude Desktop does not drive the flow to completion.
Environment
- Claude Desktop on Windows 11 Enterprise 26100
- Claude Code CLI installed on the same machine, same user profile
- MCP server: custom HTTP-MCP server acting as an OAuth 2.1 AS-Proxy (Authorization Code + PKCE S256, RFC 7591 Dynamic Client Registration, RFC 8414 / RFC 9728 discovery)
- Transport: streamable HTTP
Expected behavior
Claude Desktop should: (1) hit /.well-known/oauth-protected-resource + /.well-known/oauth-authorization-server, (2) DCR-register at registration_endpoint, (3) build a PKCE-protected
authorize URL and open the browser, (4) receive the auth code on its loopback redirect URI, (5) exchange it at token_endpoint, (6) persist the token. Exactly the sequence Claude Code
CLI performs successfully against the same server.
Actual behavior
- Claude Desktop never reaches a usable authenticated state on its own. The auth attempt either silently fails, hangs at the browser step, or no callback ever arrives at the server.
- Workaround: run the same server through Claude Code CLI (/mcp -> authenticate). The CLI completes the flow.
- After that, Claude Desktop calls the MCP server's tools without any further prompt — it reads/uses the tokens but cannot produce them itself.
Reproduction
- Configure an MCP server in Claude Desktop that requires OAuth (Auth Code + PKCE, with discovery + DCR). Any reference server with that profile reproduces.
- Trigger the auth flow in Claude Desktop — does not complete.
- Configure the same server in Claude Code CLI on the same machine, run /mcp -> authenticate — completes successfully.
- Return to Claude Desktop — tools are available and callable, despite Desktop never having driven the flow.
Server-side observation
Driven by Claude Desktop:
- Discovery requests arrive.
- DCR succeeds (POST /mcp/register returns 201 with a fresh client_id).
- GET /authorize is either not reached, or reached but the browser never returns to the loopback redirect URI Desktop registered (state token is never consumed at the callback
endpoint).
- POST /token is never invoked.
Driven by Claude Code CLI on the same machine, the same server walks the full sequence cleanly: discovery -> DCR -> /authorize -> upstream login -> callback -> token exchange ->
loopback -> /token.
Why this matters
Users without Claude Code CLI installed cannot use OAuth-protected MCP servers in Claude Desktop at all. The asymmetry strongly suggests Desktop's OAuth client is broken/incomplete
while the token persistence layer is functional and shared with the CLI.
Suggested investigation
- Compare OAuth client logic in Claude Desktop vs. Claude Code CLI: discovery handling, the loopback redirect URI advertised during DCR vs. the one actually listened on, PKCE
verifier/challenge pairing, and the lifecycle of the local callback HTTP listener (started before the browser opens? torn down too early?).
- Verify whether Claude Desktop is starting a local callback listener at all on Windows, and on which interface (127.0.0.1 vs. localhost vs. ::1).
- Confirm the redirect_uri sent during DCR is identical to the one sent on the subsequent /authorize request — RFC 7591 servers commonly validate this.
- Reproduce against at least one third-party reference MCP server to confirm whether this is general or specific to certain AS topologies.
Environment Info
- Platform: win32
- Terminal: windows-terminal
- Version: 2.1.120
- Feedback ID: 5df75cf6-819e-474b-bd93-fd762ca58aab
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗