HTTP MCP OAuth: pending flow state lost across a turn boundary, breaks manual complete_authentication on remote sessions
Environment:
- Claude Code version: 2.1.267 (native install)
- Session type: remote/sandboxed (browser's
localhost:<callbackPort>redirect is not reachable from the session — confirmed vialsof/curl, nothing listens on that port from the session's own network namespace) - MCP server: HTTP-type with OAuth (
"type": "http",oauth.clientId+oauth.callbackPortin.claude.json), specifically anOrg62-Sobject-Readserver pointing athttps://api.salesforce.com/platform/mcp/v1/platform/sobject-reads
Summary:
For an HTTP MCP server configured with OAuth, calling authenticate followed later by complete_authentication (the documented fallback for remote sessions, where the redirect page can't load) fails with "No OAuth flow is in progress for <server>. Call authenticate first, then retry with the callback URL." — even when the callback URL's state matches exactly what authenticate just returned, and even when the user completes the browser login as fast as possible.
Repro steps:
- In a remote/sandboxed Claude Code session, call
<server>__authenticate. Receive an authorization URL with acode_challenge/state. - Open the URL in a browser, complete login/consent. Browser redirects to
http://localhost:<port>/callback?code=...&state=...— page fails to load (expected in remote sessions per the tool's own docs), but the URL is captured from the address bar. - Call
<server>__complete_authenticationwith that exact callback URL. - Actual:
"No OAuth flow is in progress for <server>..."— every time, regardless of how quickly step 3 follows step 2. - Expected: the flow completes and exchanges the code for a token.
Isolating evidence:
Called authenticate and immediately (same turn, no user round trip, near-zero delay) called complete_authentication with a deliberately fake code. That returned a different error: "Authentication failed for <server>: retry your request" — i.e., the pending flow was found and it proceeded to attempt a token exchange (which correctly failed on the bogus code). This shows the pending-flow state exists and is briefly valid immediately after authenticate, but does not survive a normal turn boundary (assistant sends message → waits for user → user replies), which is unavoidable for any real browser-based OAuth login. This makes the manual complete_authentication fallback effectively non-functional for HTTP MCP OAuth on remote sessions.
Suspected cause: pending OAuth flow state (PKCE verifier + expected state) for HTTP MCP OAuth appears to be held in memory scoped to a single turn/tool-execution context rather than persisted for the lifetime of the flow, so it's discarded before a human can complete the browser step and report back.
Secondary note (unrelated, encountered while diagnosing): hitting the generic login.salesforce.com domain (rather than the org's My Domain) for this particular External Client App produced OAUTH_AUTHORIZATION_BLOCKED - Cross-org OAuth flows are not supported for this external client app — resolved by using "Use Custom Domain" to the org's actual My Domain. Not a Claude Code bug, but worth noting since it compounds the above (extra turns spent on login retries before ever reaching the state-loss issue).
🤖 Filed via Claude Code
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗