[BUG] Claude account logout/switch discards all MCP OAuth grants (mcpOAuth is stored inside the account credential)

Status Open
Reported on v2.1.251
Maintainer reply None cached
Activity 1 comment · opened Aug 29, 2026

Summary

Logging out of my Claude account and logging back in — including switching between Claude accounts, which I do routinely — discards every MCP OAuth grant. All HTTP MCP servers come back unauthenticated and each one has to be re-authorized through a separate browser round trip.

Nothing on the MCP server side expired. The authorizations are with Cloudflare and Figma; they have nothing to do with which Anthropic account is signed in, but their lifetime is tied to that account session.

Environment

  • Claude Code 2.1.251 (Homebrew cask), macOS 26.5.2, arm64
  • 7 remote MCP servers configured with "type": "http":
  • https://mcp.cloudflare.com/mcp and 5 sibling *.mcp.cloudflare.com/mcp servers (project .mcp.json)
  • https://mcp.figma.com/mcp (official figma plugin 2.2.96, plugin:figma:figma)

Steps to reproduce

  1. Authorize one or more HTTP MCP servers via /mcp.
  2. /logout, then log in again (same account, or a different one).
  3. Every HTTP MCP server is unauthenticated again; /mcp + browser OAuth is required once per server.

Today (2026-08-30) this cost 7 consecutive /mcp authorizations in a single session.

Evidence: MCP grants are stored inside the account credential

macOS Keychain, generic-password items. Structure only, values omitted:

service "Claude Code-credentials"
  claudeAiOauth : { accessToken, refreshToken, expiresAt, refreshTokenExpiresAt, scopes, ... }
  mcpOAuth      :
    "cloudflare-api|<hash>"      : { serverName, serverUrl, accessToken, refreshToken,
                                     clientId, issuer, redirectUri, expiresAt, scope,
                                     discoveryState }
    "cloudflare-observability|…" : { ... }        # 6 Cloudflare servers total
    "plugin:figma:figma|<hash>"  : { serverUrl: https://mcp.figma.com/mcp, ... }

service "Claude Code-credentials-<8 hex>"    # 5 of these, one per account signed in on this machine
  claudeAiOauth : { ... }
  (no mcpOAuth key at all)

Two things follow from this layout:

  • mcpOAuth lives in the same Keychain item as claudeAiOauth, so anything that resets the account credential takes the MCP grants with it.
  • The per-account items carry no mcpOAuth at all, so switching accounts cannot reuse an existing grant even though the grant is valid.

Token lifetimes measured at the moment of forced re-auth, i.e. none of these had expired:

  • Cloudflare: access token ~1 h TTL, refresh token present
  • Figma: access token ~2160 h (~90 days) remaining, refresh token present

The refresh tokens that would have made this a non-event are discarded along with the item.

Impact

  • One browser OAuth round trip per server per account switch; it scales linearly with the number of remote servers (7 here).
  • Parallel sessions lose their MCP tools mid-flight after an unrelated account change.
  • It pushes users toward avoiding logout entirely, or toward abandoning OAuth for static tokens where the server happens to allow it.

Proposed solution

In order of preference:

  1. Store mcpOAuth in its own store, keyed by server URL (plus scope where a server needs it), independent of claudeAiOauth. Logging out clears the Anthropic credential only. This matches the trust model: the grant belongs to the user↔MCP-server pair, not to the Anthropic session.
  2. If MCP grants must stay account-scoped, at minimum preserve them across a logout/login of the same account, and carry existing grants over when a per-account credential item is created.
  3. Failing both, provide an escape hatch: claude mcp auth export / import, or a documented setting such as preserveMcpAuthOnLogout.

Alternatives considered

Configuring servers with a static bearer token instead of OAuth, which works for Cloudflare's hosted servers but is undocumented for general clients, and is not offered at all by Figma's remote server. That is a per-vendor workaround, not a fix.

Related issues

Different mechanisms, same class of failure — MCP authorization state is fragile and expensive to rebuild:

  • #88487 — desktop app update wipes claudeAiOauth from .credentials.json
  • #87405 — MCP servers silently unavailable when a tokenless credential stub blocks Keychain refresh
  • #84331 — macOS CLI login loop, Keychain blob with blanked tokens
  • #84274 — MCP OAuth access token never persisted; server reverts to unauthenticated after restart
  • #84614 — stale dynamic client registration replayed forever
  • #89671 — valid token corrupted by the status check

None of them covers logout / account switching discarding otherwise-valid mcpOAuth grants.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗