You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bug: mcp-auth.json loses tokens for multiple servers — MCP servers suddenly need re-auth
Summary
OAuth tokens in ~/.local/share/opencode/mcp-auth.json get wiped for several MCP servers at once. Sessions that were authenticated start prompting for auth again, even though the OAuth server's refresh token is still valid. It is not server-specific — several unrelated servers lost tokens in the same rewrite.
Observed
File mcp-auth.json was rewritten (mtime changed) without a manual edit.
Before rewrite: several servers had a tokens object (accessToken, refreshToken, expiresAt, scope).
After rewrite: only servers whose entries contained NO leftover PKCE state (codeVerifier / oauthState) kept their tokens. Every entry that still carried codeVerifier + oauthState lost its tokens — reduced to clientInfo + codeVerifier + oauthState + serverUrl.
The affected servers use different OAuth providers (custom SDK OAuth, Keycloak, Jira, etc.), so this is not one provider's token format.
→ no tokens key at all. The server-side refresh token still exists and works (verified by calling the token endpoint with grant_type=refresh_token — returns a fresh access token), so the only thing lost is the client's stored copy.
Impact
Any MCP server that does OAuth (dynamic client registration) requires a full interactive re-auth every time the file is rewritten. This happened at least twice in our setup within days.
Hypothesis
Re-running opencode mcp add <server> overwrites the existing entry with a fresh clientInfo/PKCE state and drops the stored tokens.
Or: the auth file is rewritten wholesale (version upgrade / config change / another process), and only entries written with tokens survive; anything mid-flow or registered-but-not-completed loses its tokens.
Correlates with leftover PKCE state: entries that still hold codeVerifier/oauthState are the ones that lost tokens — clean entries (no leftover PKCE state) kept theirs.
Expected
opencode mcp add / re-config on an existing server should preserve existing tokens (or warn that re-auth is required instead of silently dropping them).
If the file is rewritten wholesale, tokens should be merged/retained per server.
Same issue here — opencode 1.18.18, Linux (headless host).
Setup
Remote MCP server at https://mcp.fibery.io/mcp (OAuth + dynamic client registration), configured as fibery-[redacted]. It was previously named Fibery and later renamed.
Symptoms
Every new opencode session drops back to needs_auth and forces a full interactive re-auth.
The log has ~30 occurrences over the last few days:
One long-lived session stayed authenticated for ~23 hours, so the refresh flow works within a process — it's the persisted token that's lost, not the server-side refresh token.
mcp-auth.json state
Matches the report's signature exactly: leftover PKCE state, no tokens key.
Fibery's authorization server metadata (/.well-known/oauth-authorization-server) advertises
grant_types_supported: ["authorization_code","refresh_token"] and scopes_supported: "openid","offline"]. Exercising the token endpoint directly with grant_type=refresh_token returns a fresh access token, so the server-side refresh token is still valid — only opencode's stored copy was dropped.
Hit this with the atlassian-rovo-mcp remote server (https://mcp.atlassian.com/v1/mcp/authv2) and traced it end to end — adding as a concrete data point since this issue doesn't currently mention Atlassian/Rovo.
Symptom: despite having a 90-day refresh token (offline_access scope, rotating), the server needed a full interactive re-auth (opencode mcp auth atlassian-rovo-mcp) roughly every 8 hours — i.e. exactly the access token's lifetime, as if the refresh token were never being used at all.
Server log (~/.local/share/opencode/log/opencode.log) shows the pattern clearly — repeated failures every 20-90 min for hours with no refresh attempt or error ever logged in between, just an immediate fall-through to needs_auth:
level=WARN message="mcp connect failed" server=atlassian-rovo-mcp status.status=needs_auth
level=WARN message="mcp connect failed" server=atlassian-rovo-mcp status.status=needs_auth
... (repeats every 20-90 min for ~12 hours)
level=INFO message="cli starting" args=["mcp","auth","atlassian-rovo-mcp"] <- manual re-auth required
Root cause appears to be upstream in the MCP TypeScript SDK. Atlassian issues rotating refresh tokens ("https://id.atlassian.com/atl_token_type":"ROTATING_REFRESH" in the decoded JWT) — each refresh invalidates the old refresh token and issues a new one that must be persisted immediately. The SDK's own auth() helper had a bug where a provider.saveTokens() failure during that persistence step was silently swallowed and the client fell through to requesting a brand new authorization — exactly this symptom. Confirmed via the SDK's own changeset description:
Against an authorization server that rotates refresh tokens... this loses credentials rather than merely hiding an error. The exchange has already succeeded server-side, so the old refresh token is invalidated at the moment the new one is issued; dropping the new token set leaves nothing usable on either side.
Fixed upstream in modelcontextprotocol/typescript-sdk#2053, merged 2026-08-18 — but not yet in any published release (latest npm @modelcontextprotocol/sdk is still 1.30.0 from 2026-07-27, before the fix), and opencode itself currently pins 1.29.0 in packages/opencode/package.json, one minor behind even that.
So right now there's no available fix at either layer for OAuth servers with rotating refresh tokens (Atlassian, Keycloak, and per the SDK changeset this is "the OAuth 2.1 default"). Once the SDK cuts a release containing #2053, opencode will also need to bump its @modelcontextprotocol/sdk dependency past 1.29.0/1.30.0 to pick it up.
V2 no longer uses mcp-auth.json. OAuth tokens, the client registration, and the refresh state for each MCP server are stored as a credential in the local database and written atomically per server, so an in-progress login for one server cannot rewrite or drop another server's tokens. Closing as resolved on V2; if tokens go missing on the current release, please open a new issue with steps to reproduce.
Activity
github-actions commentedon Aug 16, 2026
This issue might be a duplicate of existing issues. Please check:
opencode mcp authre-registers a new dynamic client every run instead of reusing the stored registration #35625: MCP OAuth re-registers a new dynamic client every run instead of reusing stored registration — the hypothesis aboutopencode mcp addoverwriting an entry and dropping tokens aligns closely with this issue.iamwoz commentedon Aug 17, 2026
Same issue here — opencode
1.18.18, Linux (headless host).Setup
Remote MCP server at
https://mcp.fibery.io/mcp(OAuth + dynamic client registration), configured asfibery-[redacted]. It was previously namedFiberyand later renamed.Symptoms
Every new opencode session drops back to
needs_authand forces a full interactive re-auth.The log has ~30 occurrences over the last few days:
level=WARN message="server unavailable" key=fibery-[redacted] type=remote status=needs_auth
One long-lived session stayed authenticated for ~23 hours, so the refresh flow works within a process — it's the persisted token that's lost, not the server-side refresh token.
mcp-auth.json state
Matches the report's signature exactly: leftover PKCE state, no
tokenskey.{ "fibery-[redacted]": { "clientInfo": { "clientId": "ccfac24a-…" }, "codeVerifier": "…", "oauthState": "…", "serverUrl": "https://mcp.fibery.io/mcp" }, "Fibery": { "clientInfo": { "clientId": "3a61e33e-…" }, "codeVerifier": "…", "oauthState": "…", "serverUrl": "https://mcp.fibery.io/mcp" } }Two things stand out:
opencode mcp authre-registers a new dynamic client every run instead of reusing the stored registration #35625.Confirmed not a provider issue
Fibery's authorization server metadata (/.well-known/oauth-authorization-server) advertises
grant_types_supported: ["authorization_code","refresh_token"] and scopes_supported: "openid","offline"]. Exercising the token endpoint directly with grant_type=refresh_token returns a fresh access token, so the server-side refresh token is still valid — only opencode's stored copy was dropped.
big-andy-coates commentedon Aug 19, 2026
Hit this with the
atlassian-rovo-mcpremote server (https://mcp.atlassian.com/v1/mcp/authv2) and traced it end to end — adding as a concrete data point since this issue doesn't currently mention Atlassian/Rovo.Symptom: despite having a 90-day refresh token (
offline_accessscope, rotating), the server needed a full interactive re-auth (opencode mcp auth atlassian-rovo-mcp) roughly every 8 hours — i.e. exactly the access token's lifetime, as if the refresh token were never being used at all.Server log (
~/.local/share/opencode/log/opencode.log) shows the pattern clearly — repeated failures every 20-90 min for hours with no refresh attempt or error ever logged in between, just an immediate fall-through toneeds_auth:Root cause appears to be upstream in the MCP TypeScript SDK. Atlassian issues rotating refresh tokens (
"https://id.atlassian.com/atl_token_type":"ROTATING_REFRESH"in the decoded JWT) — each refresh invalidates the old refresh token and issues a new one that must be persisted immediately. The SDK's ownauth()helper had a bug where aprovider.saveTokens()failure during that persistence step was silently swallowed and the client fell through to requesting a brand new authorization — exactly this symptom. Confirmed via the SDK's own changeset description:Fixed upstream in modelcontextprotocol/typescript-sdk#2053, merged 2026-08-18 — but not yet in any published release (latest npm
@modelcontextprotocol/sdkis still1.30.0from 2026-07-27, before the fix), and opencode itself currently pins1.29.0inpackages/opencode/package.json, one minor behind even that.So right now there's no available fix at either layer for OAuth servers with rotating refresh tokens (Atlassian, Keycloak, and per the SDK changeset this is "the OAuth 2.1 default"). Once the SDK cuts a release containing #2053, opencode will also need to bump its
@modelcontextprotocol/sdkdependency past1.29.0/1.30.0to pick it up.rekram1-node commentedon Sep 22, 2026
V2 no longer uses
mcp-auth.json. OAuth tokens, the client registration, and the refresh state for each MCP server are stored as a credential in the local database and written atomically per server, so an in-progress login for one server cannot rewrite or drop another server's tokens. Closing as resolved on V2; if tokens go missing on the current release, please open a new issue with steps to reproduce.