anthropics / anthropics/claude-code

HTTP MCP OAuth: pending flow state lost across a turn boundary, breaks manual complete_authentication on remote sessions

Open
#94,824 1 comment 0 reactions 0 assignees View on GitHub
area:auth area:mcp bug has repro
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

**Environment:**
- Claude Code version: 2.1.267 (native install)
- Session type: remote/sandboxed (browser's `localhost:` redirect is not reachable from the session — confirmed via `lsof`/`curl`, nothing listens on that port from the session's own network namespace)
- MCP server: HTTP-type with OAuth (`"type": "http"`, `oauth.clientId` + `oauth.callbackPort` in `.claude.json`), specifically an `Org62-Sobject-Read` server pointing at `https://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 . 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:**
1. In a remote/sandboxed Claude Code session, call `__authenticate`. Receive an authorization URL with a `code_challenge`/`state`.
2. Open the URL in a browser, complete login/consent. Browser redirects to `http://localhost:/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.
3. Call `__complete_authentication` with that exact callback URL.
4. **Actual:** `"No OAuth flow is in progress for ..."` — every time, regardless of how quickly step 3 follows step 2.
5. **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 : 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

Contributor guide

No contributing guide indexed for this repository

Research direction

Start at the HTTP MCP `authenticate` and `complete_authentication` tool entry points, using the `.claude.json` OAuth configuration and the callback URL described in the report. Compare pending-flow lifetime across the immediate same-turn fake-code case and a normal turn boundary. Done means a matching callback can find the pending flow and exchange its code for a token in a remote session.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, authentication
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.