[BUG] MCP OAuth: browser confirms "Authentication successful" but CLI still reports "Needs authentication" (HTTP transport, fixed --callback-port)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (closest related but not matching: #37747, #66511, #72818 — none match this exact symptom of browser-confirmed success not reflected client-side)
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code (2.1.220, confirmed via
claude update— already up to date)
What's Wrong?
For a remote HTTP MCP server (https://mcp.lovable.dev), the OAuth authorization flow completes successfully on the server/browser side (the browser shows "Connected / Authentication successful. You can close this tab and return to Claude Code."), but the CLI never registers the successful auth. claude mcp get lovable continues to report Status: ! Needs authentication afterward, and the local auth-needed marker file (~/.claude/mcp-needs-auth-cache.json) gets its timestamp for the lovable entry refreshed (re-flagged as needing auth) at the same moment the browser shows success — i.e. the CLI silently drops a completed authorization instead of persisting it.
This happened consistently across three attempts:
- Initial state:
/mcp→ Authenticate → browser shows a redirect_uri mismatch error page. - Removed and re-added the server (
claude mcp remove lovable/claude mcp add --transport http lovable https://mcp.lovable.dev --scope user) → same redirect_uri mismatch on/mcp→ Authenticate. - Removed and re-added again with a fixed callback port (
claude mcp add --transport http lovable https://mcp.lovable.dev --scope user --callback-port 45678) →/mcp→ Authenticate → this time the browser completed the flow and showed the success page — butclaude mcp get lovablestill shows "Needs authentication" immediately after, andmcp-needs-auth-cache.json'slovabletimestamp was bumped to match.
No error is surfaced to the user in the CLI//mcp UI explaining why the completed authorization wasn't accepted — from the user's perspective the browser said "success" but nothing changed.
Expected Behavior
When the OAuth provider redirects back with a valid authorization code and the CLI's token exchange succeeds (which the browser's "Authentication successful" page implies happened on the provider's side), claude mcp get <server> should report Status: ✓ Connected (or similar) and the server's tools should become available. If the CLI-side token exchange itself fails after a successful provider-side authorization, that failure should be surfaced explicitly (not silently re-flagged as "needs auth" with no error).
Actual Behavior
- Browser: "Connected / Authentication successful. You can close this tab and return to Claude Code."
- CLI (
claude mcp get lovable), run immediately after:Status: ! Needs authentication ~/.claude/mcp-needs-auth-cache.json: thelovableentry'stimestampfield is updated to a new (later) value at the same time — i.e. the CLI actively re-marks the server as needing auth rather than leaving stale state.- No error message is shown anywhere in the CLI output explaining the discrepancy.
Environment
- Claude Code CLI version: 2.1.220 (macOS, Darwin 25.5.0)
- MCP server:
lovable, transporthttp, URLhttps://mcp.lovable.dev - Config scope:
user(global), with--callback-port 45678set explicitly to work around a separate/earlierredirect_urimismatch (attempt 1 above) - No proxy, VPN, or SSH/remote session involved — local interactive
/mcpflow in a native terminal session
Steps to Reproduce
claude mcp add --transport http lovable https://mcp.lovable.dev --scope user --callback-port <fixed-port>- In a Claude Code session, run
/mcpand select Authenticate forlovable - Complete the OAuth flow in the browser through to the "Authentication successful" confirmation page
- Run
claude mcp get lovable— observeStatus: ! Needs authenticationdespite step 3
Additional Notes
This is a different failure mode from the DCR client_id eviction case in #72818 (that one dead-ends at /authorize with an HTTP error page before any success is shown) — here the entire browser-side flow completes successfully, and the failure is purely in the CLI's handling/persistence of that successful result. Also distinct from the pure redirect_uri mismatch reports (#37747, #66511) that fail before reaching a success page at all — the --callback-port fix did get us past that stage, but exposed this second, later-stage failure.
Happy to provide additional debug output if there's a way to get more verbose OAuth/token-exchange logging from the CLI.