[BUG] mcp-needs-auth-cache.json is shared across CLAUDE_SECURESTORAGE_CONFIG_DIR profiles — one account's auth failure blocks the other's MCP servers
Environment
- Claude Code: 2.1.234 (native install)
- Platform: macOS (Darwin 27.0.0)
- Two accounts on one machine, split via
CLAUDE_SECURESTORAGE_CONFIG_DIR
Summary
CLAUDE_SECURESTORAGE_CONFIG_DIR correctly namespaces credential storage — each profile gets its own Keychain item (Claude Code-credentials vs Claude Code-credentials-<hash>). But ~/.claude/mcp-needs-auth-cache.json is not namespaced: both profiles read and write the same file.
The cache is keyed by server name only, with a 15-minute TTL during which new processes skip the MCP connection attempt entirely (see #48670). Since claude.ai connector server names are identical across accounts ("claude.ai Teamwork", "claude.ai Figma", …), a needs-auth entry written by profile A blocks profile B from even attempting to connect — despite profile B holding a valid token in its own Keychain item.
Repro
- Set up two accounts:
- Profile A: plain
claude(default securestorage) - Profile B:
CLAUDE_SECURESTORAGE_CONFIG_DIR=internal claude
- Authenticate a claude.ai connector (e.g. Teamwork) on profile B; leave it unauthenticated/expired on profile A.
- Start a session as profile A → the connector fails auth → entry written to the shared
~/.claude/mcp-needs-auth-cache.json. - Within 15 minutes, start a session as profile B.
Expected: profile B connects — its Keychain item has a valid token.
Actual: profile B skips the connection ("cached needs-auth") and reports the server as requiring authentication.
Impact
- Worst for SDK/headless consumers (
sdk-tsentrypoint, agent hosts): they can't run/mcpinteractively, so within the TTL window there is no in-session recovery. Combined with the cross-profile poisoning, alternating between two accounts makes MCP auth appear to "never stick" — each profile's failures continuously re-poison the other. - Interactive sessions show misleading "needs authentication" status for servers that are actually fine for the current profile.
Workaround
rm -f ~/.claude/mcp-needs-auth-cache.json after re-authenticating, before starting the next (SDK) session.
Suggested fix
Namespace the needs-auth cache by the same securestorage profile hash already used for the Keychain service name — e.g. mcp-needs-auth-cache-<hash>.json, or include the profile hash in each cache key. Alternatively, on cache hit, cheaply verify that a credential for that server exists in the current profile's storage before trusting the cached needs-auth verdict.
Related
- #48670 — needs-auth cache blocks SDK reconnection after successful re-auth (single profile; closed not-planned). This issue is the multi-profile variant: the cache isn't just stale, it's shared across identities.
- #80635, #78220 — other cases of the cache being keyed too coarsely (by server name only)
- #79223 —
CLAUDE_SECURESTORAGE_CONFIG_DIRdocumentation request