MCP OAuth completes but token is not honored — server stays in 'Needs authentication'

Resolved 💬 4 comments Opened May 18, 2026 by mattwillems-exabeam Closed Jun 18, 2026

Summary

Adding a remote HTTP MCP server that uses OAuth 2.1 (authorization_code + PKCE, pre-registered client_id/client_secret) completes the browser OAuth dance successfully, but the resulting token is not used or persisted — /mcp continues to show the server as "Needs authentication" indefinitely. Tools never become available.

Affects multiple OAuth-protected MCP servers hosted by one corporate vendor (three distinct environments — dev, staging, prod-region). Does not affect other OAuth-protected MCP servers (Figma, Atlassian, Google Drive) on the same install, suggesting the issue is specific to some combination of that provider's OAuth metadata, scope handling, or callback timing.

Reproduction

  1. claude mcp add --transport http --client-id <id> --client-secret --callback-port 8080 corp-mcp https://<corporate-mcp-host>/mcp (paste secret at prompt)
  2. /mcp → click Authenticate, or invoke the auto-generated mcp__corp-mcp__authenticate tool
  3. Browser opens to authorization_endpoint, sign-in succeeds, browser redirects to http://localhost:8080/callback?code=...&state=...
  4. Claude Code reports "authentication successful"
  5. /mcp and claude mcp list still show server as "! Needs authentication"
  6. Re-attempting OAuth produces the same outcome on loop

Evidence the server side is healthy

The auth and MCP pipeline both work when bypassing Claude Code:

  • Token exchange via curl with the same client_id/secret/PKCE verifier returns a valid Bearer token (HTTP 200, expires_in: 14400, correct audience/permission claims).
  • That token authenticates a manual POST /mcpinitialize returns proper server capabilities; tools/list returns the full tool inventory with schemas.
  • So the OAuth provider and the MCP server are both functioning correctly in isolation; only Claude Code's bridging between them is failing.

Pattern

In the same Claude Code session, claude mcp list shows:

  • ✓ Connected: Figma (mcp.figma.com), Atlassian (mcp.atlassian.com), Google Drive (drivemcp.googleapis.com)
  • ! Needs authentication (stuck): three corporate MCP servers from the same vendor, across three environments

OAuth providers that work and the ones that don't both implement OAuth 2.1 with authorization_code + PKCE. The differentiator may be the OAuth discovery metadata shape, scope handling, or callback timing.

Environment

  • Claude Code version: 2.1.143
  • OS: macOS 26.4.1
  • Transport: HTTP (streamable)
  • Grant: authorization_code + PKCE (S256), pre-registered client

Workaround

None known via Claude Code's UI. The token can be obtained manually via curl and used directly against the MCP server, but Claude Code does not expose any documented way to inject a pre-obtained Bearer token for a configured MCP server.

Possibly related

A prior Claude Code OAuth callback listener (process named 2.1.143, same as the running CLI version) was found holding port 8080 even though no OAuth flow was active. Killing that stale process was required before a new flow could bind. This may be why "auth successful" + repeated retries keep producing the same "Needs authentication" state — each new attempt may be racing against or talking to a stale prior listener.

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗