MCP OAuth on Windows: claude mcp login is undiscoverable, browser reports success on failure, and failed auth leaves an empty-token credential entry
Summary
Authenticating an OAuth-protected remote MCP server took me several hours across a week, with an authorization page reappearing on every app start. The fix was a single command — claude mcp login <server> — which is surfaced nowhere that a stuck user would look. Along the way I hit four separate issues that each independently sent me down a wrong path. All are reproducible and all seem cheap to fix.
Environment
- Windows 11 Pro 10.0.26200
- Claude Desktop 1.30096.1
- Claude Code CLI 2.1.231
- Node.js v24 (portable install)
- mcp-remote 0.1.36
- MCP server: remote streamable HTTP, OAuth/PKCE, Microsoft Entra ID
---
1. claude mcp login is not surfaced anywhere it is needed
claude mcp login <server> solves this in one step. It is not mentioned in:
- the
server requires authenticationnotice - the error returned by
/mcpwhen actions are unavailable - the
/mcpinline hint, which shows only[reconnect|enable|disable [<server>|all]]
It is discoverable only by running claude mcp --help and reading the subcommand list.
Worth noting: the Claude Code assistant embedded in Claude Desktop also failed to find it. It first routed me through /mcp, then through a full CLI first-run setup including an account login, before reading claude mcp --help and locating the correct command. If the in-product assistant does not know the intended path, this is a discoverability defect rather than user error.
Ask: name the command in the auth-required notice, in the /mcp error, and in /mcp help output.
2. /mcp cannot authenticate in the Claude Desktop Claude Code pane
In the desktop app, /mcp accepts only:
/mcp [reconnect|enable|disable [<server>|all]]
There is no authenticate action. The interactive server list with an Authenticate entry exists only in the terminal CLI. Same slash command, same product, different capability, no indication of the difference.
Ask: support MCP authentication in the desktop pane, or have /mcp state which surface can do it.
3. Reconnect, enable, and disable aren't available in this session. is a dead end
This message does not say why, which sessions do support the actions, or what to do instead. I retried it in several sessions precisely because the wording implies it is session-dependent while giving no way to identify a qualifying session.
Ask: state the reason and point to claude mcp login <server>.
4. The callback page reports success before the token exchange succeeds
The browser shows:
Authorization successful! You may close this window and return to the CLI.
while the client log shows the exchange failing immediately afterwards:
[29808] Auth code received, resolving promise
[29808] Completing authorization...
[29808] Authorization error: InvalidGrantError: incorrect code_verifier
[29808] Fatal error: InvalidGrantError: incorrect code_verifier
I believed the login had succeeded for days and kept debugging why it would not persist. The success page is actively misleading.
Ask: render success only after the token exchange completes; render the error otherwise.
5. Failed auth leaves a credential entry indistinguishable from a valid one
After the failed attempts, ~/.claude/.credentials.json contained:
"my-server|<hash>": {
"serverName": "my-server",
"serverUrl": "https://<redacted>/mcp",
"accessToken": "",
"discoveryState": { "oauthMetadataFound": true },
"clientId": "https://claude.ai/oauth/claude-code-client-metadata",
"redirectUri": "http://localhost:3118/callback"
}
Empty accessToken, no refreshToken. Neither claude mcp list nor the desktop UI flags this as incomplete — it looks configured. An explicit "authentication incomplete" state would have made the diagnosis immediate.
Ask: surface entries with an empty accessToken as incomplete in claude mcp list / get and in the UI.
---
Adjacent, likely a different repo but same user-visible failure
Claude Desktop does not reload claude_desktop_config.json, and the stale in-memory config intercepts other clients' OAuth. After I removed an MCP server from the file, the app kept launching it from memory. That process held its fixed OAuth callback port and captured a login intended for Claude Code — I authenticated correctly, the browser reported success, and the token landed with the removed client. Claude Code's store stayed empty, silently. Only a full quit including the tray icon reloaded the file.
Ask: reload on change, or warn visibly when the running config differs from disk.
mcp-remote is the recommended bridge for Claude Desktop and self-destructs with a single client. Claude Desktop restarts a stdio MCP server while the previous proxy process is still alive. Both use the same fixed callback port and write the same <hash>_code_verifier.txt; the second overwrites the first while its consent page is still open, producing the incorrect code_verifier above. This was the root cause of the authorization page returning on every app start.
Ask: support http/sse MCP servers directly in claude_desktop_config.json, as Claude Code already does with {"type":"http","url":"…"}, and drop the bridge requirement.
---
Item 1 alone would have reduced hours to two minutes. Item 4 cost me several days of false assumptions. Happy to provide full logs or test any fix.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗