Describe the bug
For an HTTP-type MCP server that uses OAuth (PKCE, public client — clientSecret: null), Copilot CLI appears to mint a new token-cache entry under a different cache-key hash more often than expected, instead of finding and reusing the one still-valid cached token for that server.
Over about 3 weeks of normal use, I have 13 separate <hash>.tokens.json files in ~/.copilot/mcp-oauth-config/ that are all for the exact same server URL + OAuth scope, when I'd expect at most one entry that gets updated/refreshed in place. Only 1 matching <hash>.json client-registration file exists for that server, so the token-cache key and the client-registration key appear to diverge over time.
Two of the 13 token files were written in the same second and contain byte-identical expiresAt epoch values, which strongly suggests a single OAuth completion got persisted under two different cache-key hashes rather than one canonical entry being reused.
Separately (possibly independent, possibly compounding): none of the 13 cached tokens contain a refreshToken field — only accessToken + expiresAt. Observed access-token lifetime is consistently ~75–90 minutes. Since there's no refresh token, once it expires there is no silent-refresh path and the full interactive browser consent flow must run again. Combined with the cache-key issue above, the net effect looks like "the token expires in under an hour and I constantly have to re-authenticate," when it's really a mix of (a) a genuinely short-lived, non-refreshable token, and (b) the client sometimes failing to locate a still-valid cached token for the same server.
Affected version
1.0.80
Steps to reproduce the behavior
- Configure an HTTP MCP server that requires OAuth (registered in
~/.copilot/mcp-config.json with "type": "http", pointing at a server behind an internal API gateway).
- Authenticate once via the interactive browser flow.
- Use the tool across multiple CLI sessions (including separate worktree-backed sessions) over several days.
- Inspect
~/.copilot/mcp-oauth-config/*.tokens.json — instead of a single file per server updated in place, multiple files accumulate for the identical server URL/scope. Some have expiresAt values identical to the second with another file.
- In practice this surfaces as being prompted to re-authenticate noticeably more often than the access token's actual ~75–90 minute lifetime would suggest, i.e. sessions don't always find/reuse an already-valid cached token.
Expected behavior
- A given MCP server's OAuth token cache entry should be looked up and updated using a single, stable cache key (e.g., derived only from server/resource URL + client ID), not one that can vary across otherwise-identical auth attempts for the same server.
- When a still-valid, non-expired cached token already exists for a server, any session should find and reuse it rather than triggering a fresh interactive login.
- If a variable value (such as the randomly chosen local loopback redirect port used during the OAuth flow) is unintentionally being folded into the persisted cache-key, that would explain the duplicate-key behavior observed above.
Additional context
- OS: Windows 11 (Windows_NT)
- MCP server type:
http, OAuth with PKCE, public client
- Token cache directory (
~/.copilot/mcp-oauth-config/) is per-user/global, not per-session, so in principle tokens should already be shareable across sessions/worktrees on the same machine — but the duplicate cache-key entries above show that reuse isn't happening reliably.
- Observed access-token lifetimes across 13 samples for the same server: consistently ~75–90 minutes.
- No
refreshToken field present in any of the 13 cached token files for this server.
- Docs describe
mcp-oauth-config/ as file-based storage used "when keychain-backed storage is unavailable." On this machine (Windows 11 with Credential Manager available) it may be worth confirming why the file-based fallback path is being used at all, since that could be related to the cache-key inconsistency.
Describe the bug
For an HTTP-type MCP server that uses OAuth (PKCE, public client —
clientSecret: null), Copilot CLI appears to mint a new token-cache entry under a different cache-key hash more often than expected, instead of finding and reusing the one still-valid cached token for that server.Over about 3 weeks of normal use, I have 13 separate
<hash>.tokens.jsonfiles in~/.copilot/mcp-oauth-config/that are all for the exact same server URL + OAuth scope, when I'd expect at most one entry that gets updated/refreshed in place. Only 1 matching<hash>.jsonclient-registration file exists for that server, so the token-cache key and the client-registration key appear to diverge over time.Two of the 13 token files were written in the same second and contain byte-identical
expiresAtepoch values, which strongly suggests a single OAuth completion got persisted under two different cache-key hashes rather than one canonical entry being reused.Separately (possibly independent, possibly compounding): none of the 13 cached tokens contain a
refreshTokenfield — onlyaccessToken+expiresAt. Observed access-token lifetime is consistently ~75–90 minutes. Since there's no refresh token, once it expires there is no silent-refresh path and the full interactive browser consent flow must run again. Combined with the cache-key issue above, the net effect looks like "the token expires in under an hour and I constantly have to re-authenticate," when it's really a mix of (a) a genuinely short-lived, non-refreshable token, and (b) the client sometimes failing to locate a still-valid cached token for the same server.Affected version
1.0.80
Steps to reproduce the behavior
~/.copilot/mcp-config.jsonwith"type": "http", pointing at a server behind an internal API gateway).~/.copilot/mcp-oauth-config/*.tokens.json— instead of a single file per server updated in place, multiple files accumulate for the identical server URL/scope. Some haveexpiresAtvalues identical to the second with another file.Expected behavior
Additional context
http, OAuth with PKCE, public client~/.copilot/mcp-oauth-config/) is per-user/global, not per-session, so in principle tokens should already be shareable across sessions/worktrees on the same machine — but the duplicate cache-key entries above show that reuse isn't happening reliably.refreshTokenfield present in any of the 13 cached token files for this server.mcp-oauth-config/as file-based storage used "when keychain-backed storage is unavailable." On this machine (Windows 11 with Credential Manager available) it may be worth confirming why the file-based fallback path is being used at all, since that could be related to the cache-key inconsistency.