[BUG] macOS: saving an MCP server's OAuth tokens wipes the shared Keychain entry, signing out every session (regression of #45551)
What's wrong?
On macOS, saving one remote MCP server's OAuth tokens wipes the whole Claude Code-credentials Keychain entry: the Claude account sign-in and the tokens of every other MCP server. Every running Claude Code session on the Mac shows Not logged in · Please run /login at the same moment. /login fixes it until the next save of that server's tokens.
This is the symptom of #45551 (closed as fixed in 2.1.136, now locked). It happens again on 2.1.296.
Steps to reproduce
- Be signed in to Claude Code (subscription) on macOS. Have one other OAuth MCP server (Vercel,
plugin:vercel:vercel) signed in, so that the credential entry is above ~4 KB. The debug log showedKeychain payload (4180B JSON) exceeds security -i stdin limit; using argv, and everything still worked at that point. - Add a remote HTTP MCP server that uses OAuth with dynamic client registration and short-lived access tokens (
expires_in: 900) ("<server>" in the log below), and sign in to it via/mcp. A third server (Sanity,https://mcp.sanity.io/) was configured but not signed in. - Send any prompt:
Not logged in · Please run /login. A second Claude Code session on the same Mac is signed out as well.
It happens every time with our server. Signing in to Vercel alone did not trigger it.
What the debug log shows (claude --debug-file, 2.1.296)
The wipe happened at start-up, on the automatic token refresh, before any /mcp action:
09:24:28.105 MCP server "plugin:vercel:vercel": Returning tokens <- Vercel tokens present
09:24:28.177 MCP server "<server>": Starting token refresh
09:24:28.352 MCP server "sanity": Saving discovery state (authServer: https://mcp.sanity.io/)
09:24:28.665 [WARN] Keychain payload (4493B JSON) exceeds security -i stdin limit; using argv
09:24:28.860 MCP server "plugin:vercel:vercel": Returning tokens <- still present
09:24:30.209 MCP server "<server>": Token refresh successful
09:24:30.209 MCP server "<server>": Saving tokens <- no Keychain size warning on this save
09:24:34.417 MCP server "plugin:vercel:vercel": No token data found <- everything gone
...
09:25:06.564 [ERROR] API error: Could not resolve authentication method ...
09:25:06.567 [ERROR] [engine] turn ended in error: Not logged in · Please run /login
The entry was 4493 bytes just before the save. The save itself logged no exceeds security -i stdin limit warning, so the payload it wrote was under 4096 bytes. That means it wrote the entry back from an empty or partial base, which dropped claudeAiOauth and every other server's mcpOAuth entry. The save ran while Sanity's start-up write through the argv path was in progress, so a read-modify-write race on the shared entry looks likely.
A fresh /mcp sign-in to the same server (after "Clear authentication") ends the same way.
Why short-lived tokens make it worse
With expires_in: 900, Claude Code refreshes the server's token on almost every start-up. Each refresh is a write to the shared entry, so a user with such a server connected can be signed out each time they start Claude Code.
What should happen
Saving one MCP server's tokens should never remove the Claude account sign-in or other servers' tokens. Suggested fixes (same as in #45551): keep claudeAiOauth and mcpOAuth in separate Keychain entries, and/or do a locked read-modify-write that refuses to write if the read failed.
Environment
- Claude Code 2.1.296 (native install), macOS (Darwin 25.6.0), Apple Silicon
- Subscription sign-in (claude.ai)
- Several sessions running at the same time
- Related: #45551, #92839, #93537, #90647
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗