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
{{ message }}
Repository navigation
MCP: Cannot authenticate to multiple Atlassian sites simultaneously - OAuth credentials shared across MCP server configurations #293533
Summary:
When configuring multiple Atlassian MCP servers pointing to different Atlassian Cloud sites (e.g., site-a.atlassian.net and site-b.atlassian.net), VS Code only retains authentication for one site. The OAuth credential appears to be keyed by the OAuth client ID and/or MCP auth provider identity derived only from the server URL origin, causing all Atlassian MCP connections to share a single token.
Steps to Reproduce:
Configure two Atlassian MCP servers in mcp.json with different names (and different query params to differentiate URLs).
Example: https://mcp.atlassian.com/?site=a and https://mcp.atlassian.com/?site=b
Authenticate the first connection — prompted with fresh OAuth flow, select site-a.atlassian.net.
Authenticate the second connection — prompted to reuse "MCP" credential or "Sign in to another account".
Select "Sign in to another account" and authenticate to site-b.atlassian.net.
Call getAccessibleAtlassianResources on both MCP servers.
Expected Result:
Site A connection returns site-a.atlassian.net.
Site B connection returns site-b.atlassian.net.
Actual Result:
Both connections return the same site (whichever was authenticated last).
The second authentication overwrites the first.
Investigation Notes:
Credentials are stored in ~/Library/Application Support/Code/User/globalStorage/state.vscdb.
The providerId appears to be derived from the URL origin only, stripping query parameters.
This means multiple MCP servers with the same origin but different query params (e.g. ?site=a vs ?site=b) resolve to the same providerId and therefore share credentials.
The key uses https://mcp.atlassian.com/ (without query params) and a shared clientId, so all Atlassian MCP servers resolve to the same credential regardless of the configured URL or server name.
Suggested Fix:
Include the full configured URL (including query params) or at minimum the MCP server name from mcp.json when generating the providerId / credential key, allowing per-server credential isolation (multiple OAuth tokens per MCP server configuration).
Workaround:
Use separate VS Code profiles for each Atlassian site.
Summary:
The MCP OAuth server metadata returned from the discovery endpoint at https://mcp.slack.com/.well-known/oauth-authorization-server reports an issuer "https://slack.com" which mismatches the expected issuer "https://mcp.slack.com" used to perform the discovery.
Spec-grounded Analysis
Relevant Specifications:
RFC 8414 (OAuth 2.0 Authorization Server Metadata)
MCP 2025-11-25 (MCP OAuth specification)
RFC 9728 (Protected Resource Metadata)
JSON-RPC 2.0 (general interaction protocol)
Why this mismatch is a valid and justified failure:
Issuer Identifier MUST EXACTLY MATCH in Metadata (RFC 8414, Section 3):
"authorization server metadata MUST include an issuer property that is the issuer identifier of the authorization server as defined in [OpenID.issuer]. The issuer value in the metadata document MUST match the issuer value used for discovery."
Here, the discovery URI was anchored in the issuer https://mcp.slack.com namespace, but the JSON metadata claims "issuer": "https://slack.com". According to RFC 8414, this lack of exact string match constitutes a discovery failure.
Issuer Consistency Required for Trust (RFC 9728, Section 3):
MCP leverages issuer consistency to bind metadata, token issuance, and protected resource validation. A mismatch risks security and operational failure.
MCP 2025-11-25 Requirements for OAuth Provider Metadata:
MCP explicitly mandates strict matching between authorization server metadata issuer and discovery URLs to avoid ambiguity or cross-issuer issues. The MCP tooling depends on this for critical flows such as token issuance and client registration.
Security and Interoperability Implications:
The mismatched issuer may result in clients accepting tokens or metadata from a different domain, breaking trust boundaries and facilitating attacks (token substitution, replay, or phishing).
OAuth clients and MCP tooling will reject authorization servers whose issuer does not match the discovery URI; this is by design and necessary for secure interoperability.
Correct Server Behavior
The OAuth authorization server metadata at https://mcp.slack.com/.well-known/oauth-authorization-servermust contain an issuer field exactly equal to the discovery issuer URI:
{
...
"issuer": "https://mcp.slack.com",
...
}
The metadata should conform to RFC 8414 with all required fields present and consistent.
The server must not redirect or provide metadata pointing to a different issuer domain (e.g., "https://slack.com").
Compliance tools will validate the issuer field against the initial discovery URL and fail if there is any discrepancy.
This binding guarantees that the authorization server, protected resource, and client share a consistent trust domain as mandated by MCP and OAuth 2.0 standards.
Secondary Notes
Other findings such as MCP initialization failure (non-JSON 404 on initialize) and PRM resource mismatch compound interoperability issues but are not as impactful as the fundamental issuer identity failure.
Per JSON-RPC 2.0, MCP devices must respond to initialize requests with valid JSON-RPC responses. Returning a 404 non-JSON constitutes a protocol compliance failure.
RFC 9728 requires exact resource URL matching for protected resource metadata, relevant to secured resource identification but secondary to the issuer mismatch.
RFC 7591 (dynamic client registration) and token endpoint readiness were skipped due to absent metadata fields, which may be a result of this issuer metadata inconsistency.
Conclusion
The AUTH_SERVER_ISSUER_MISMATCH failure is valid, justified, and critical under RFC 8414 and MCP 2025-11-25 requirements. The metadata issuer must be corrected to exactly match the MCP OAuth discovery URI https://mcp.slack.com. Without this fix, compliance, interoperability, and security guarantees are compromised.
If you need further assistance on resolving remaining findings or guidance on MCP tooling corrections, please ask.
exit status 2
Thanks for the detailed report! VS Code uses a standard OAuth flow here — the authorization server is discovered via the .well-known/oauth-authorization-server endpoint on the MCP server origin or via the WWW-Authenticate header.
Can you clarify what the different authorization servers are for each Atlassian site and how they are exposed via a typical OAuth flow?
This issue has been closed as it has been labeled with info-needed and has not received the additional information that was requested from the issue author. It has been labeled as info-needed for 7 days.
Confirming this issue is still reproducible and not limited to VS Code. The same root cause affects Claude Code's MCP OAuth implementation — when two Atlassian MCP server entries are configured pointing to the same MCP endpoint, authenticating the second entry overwrites the credential for the first. Both entries end up using whichever site was authenticated last.
The providerId being derived from the URL origin alone (ignoring server name and query params) is definitively the issue. Users who believe they have two sites configured simultaneously are mistaken — only the last-authenticated site is actually active.
Would be great to see this reopened and addressed. Multi-tenant Atlassian setups are common in enterprise environments where users need access to both a personal/dev site and a work organization site simultaneously.
Atlassian uses a single centralized OAuth authorization server — https://auth.atlassian.com — for all Atlassian Cloud sites. There are no per-site authorization servers. The .well-known/oauth-authorization-server endpoint on mcp.atlassian.com returns the same AS regardless of query parameters.
The per-site differentiation works as follows:
OAuth completes against the shared auth.atlassian.com
The resulting token is multi-site — it covers all cloud resources the user has access to
Callers hit https://api.atlassian.com/oauth/token/accessible-resources to enumerate which Atlassian Cloud sites the token grants access to
API calls then include a cloudId path segment to target a specific site
The mcp.atlassian.com query params (e.g. ?site=a) tell the MCP gateway which site to proxy to — but the underlying token is the same either way
This means VS Code's auth server discovery is working correctly — it finds one auth server because there is only one. The problem is that VS Code doesn't currently support multiple independent credential sessions for the same auth server origin across different MCP server configs. When a second Atlassian MCP entry authenticates, it overwrites the first because both resolve to providerId: "https://mcp.atlassian.com/".
The fix needs to be in how the providerId / credential key is derived — it should incorporate the MCP server name from mcp.json (or the full configured URL) in addition to the origin, so that two MCP server entries pointing to the same endpoint can hold independent tokens. This would allow a user to be authenticated to site-a.atlassian.net via one server config and site-b.atlassian.net via another simultaneously.
Happy to provide additional detail or test a fix if that's helpful.
I'm trying to understand how to map Atlassian's setup to what we follow which is standard OAuth 2.0. I can't be in the business of special casing Atlassian.
Small regression shape I would want here: keep OAuth issuer discovery separate from the local credential slot identity.
I would test two MCP server entries that share the same authorization server and provider origin, but represent different configured resources or site bindings:
authenticate entry A and bind it to site/resource A;
authenticate entry B and bind it to site/resource B;
call the same MCP tool through each entry and verify the selected token/resource context does not collapse to whichever entry authenticated last;
change the configured server name or resource binding and require re-auth or an explicit migration, rather than silently reusing the old credential slot.
That keeps the RFC 8414 issuer semantics intact while making the client-side storage invariant explicit: the credential lookup key should include the configured MCP server identity or resource binding, not only the OAuth provider origin. A useful negative test is token A being valid cryptographically but rejected for entry B because the local credential slot, resource binding, or site context no longer matches the proposed MCP call.
Activity
clgtm commentedon Feb 10, 2026
In case this helps -
┌────────────────────┤ LLM EXPLANATION ├─────────────────────┐
Primary Finding Explanation: AUTH_SERVER_ISSUER_MISMATCH (high confidence, 1.00)
Summary:
The MCP OAuth server metadata returned from the discovery endpoint at
https://mcp.slack.com/.well-known/oauth-authorization-serverreports an issuer"https://slack.com"which mismatches the expected issuer"https://mcp.slack.com"used to perform the discovery.Spec-grounded Analysis
Relevant Specifications:
Why this mismatch is a valid and justified failure:
Issuer Identifier MUST EXACTLY MATCH in Metadata (RFC 8414, Section 3):
Here, the discovery URI was anchored in the issuer
https://mcp.slack.comnamespace, but the JSON metadata claims"issuer": "https://slack.com". According to RFC 8414, this lack of exact string match constitutes a discovery failure.Issuer Consistency Required for Trust (RFC 9728, Section 3):
MCP leverages issuer consistency to bind metadata, token issuance, and protected resource validation. A mismatch risks security and operational failure.
MCP 2025-11-25 Requirements for OAuth Provider Metadata:
MCP explicitly mandates strict matching between authorization server metadata issuer and discovery URLs to avoid ambiguity or cross-issuer issues. The MCP tooling depends on this for critical flows such as token issuance and client registration.
Security and Interoperability Implications:
Correct Server Behavior
https://mcp.slack.com/.well-known/oauth-authorization-servermust contain anissuerfield exactly equal to the discovery issuer URI:"https://slack.com").This binding guarantees that the authorization server, protected resource, and client share a consistent trust domain as mandated by MCP and OAuth 2.0 standards.
Secondary Notes
initialize) and PRM resource mismatch compound interoperability issues but are not as impactful as the fundamental issuer identity failure.initializerequests with valid JSON-RPC responses. Returning a 404 non-JSON constitutes a protocol compliance failure.Conclusion
The AUTH_SERVER_ISSUER_MISMATCH failure is valid, justified, and critical under RFC 8414 and MCP 2025-11-25 requirements. The metadata issuer must be corrected to exactly match the MCP OAuth discovery URI
https://mcp.slack.com. Without this fix, compliance, interoperability, and security guarantees are compromised.If you need further assistance on resolving remaining findings or guidance on MCP tooling corrections, please ask.
exit status 2
TylerLeonhardt commentedon Feb 16, 2026
Thanks for the detailed report! VS Code uses a standard OAuth flow here — the authorization server is discovered via the
.well-known/oauth-authorization-serverendpoint on the MCP server origin or via theWWW-Authenticateheader.Can you clarify what the different authorization servers are for each Atlassian site and how they are exposed via a typical OAuth flow?
vs-code-engineering commentedon Feb 24, 2026
This issue has been closed as it has been labeled with
info-neededand has not received the additional information that was requested from the issue author. It has been labeled asinfo-neededfor 7 days.juteasl commentedon Mar 18, 2026
Confirming this issue is still reproducible and not limited to VS Code. The same root cause affects Claude Code's MCP OAuth implementation — when two Atlassian MCP server entries are configured pointing to the same MCP endpoint, authenticating the second entry overwrites the credential for the first. Both entries end up using whichever site was authenticated last.
The providerId being derived from the URL origin alone (ignoring server name and query params) is definitively the issue. Users who believe they have two sites configured simultaneously are mistaken — only the last-authenticated site is actually active.
Would be great to see this reopened and addressed. Multi-tenant Atlassian setups are common in enterprise environments where users need access to both a personal/dev site and a work organization site simultaneously.
TylerLeonhardt commentedon Mar 19, 2026
I'll reopen but my question hasn't been answered yet.
juteasl commentedon Mar 19, 2026
To answer TylerLeonhardt's question directly:
Atlassian uses a single centralized OAuth authorization server —
https://auth.atlassian.com— for all Atlassian Cloud sites. There are no per-site authorization servers. The.well-known/oauth-authorization-serverendpoint onmcp.atlassian.comreturns the same AS regardless of query parameters.The per-site differentiation works as follows:
auth.atlassian.comhttps://api.atlassian.com/oauth/token/accessible-resourcesto enumerate which Atlassian Cloud sites the token grants access tocloudIdpath segment to target a specific sitemcp.atlassian.comquery params (e.g.?site=a) tell the MCP gateway which site to proxy to — but the underlying token is the same either wayThis means VS Code's auth server discovery is working correctly — it finds one auth server because there is only one. The problem is that VS Code doesn't currently support multiple independent credential sessions for the same auth server origin across different MCP server configs. When a second Atlassian MCP entry authenticates, it overwrites the first because both resolve to
providerId: "https://mcp.atlassian.com/".The fix needs to be in how the
providerId/ credential key is derived — it should incorporate the MCP server name frommcp.json(or the full configured URL) in addition to the origin, so that two MCP server entries pointing to the same endpoint can hold independent tokens. This would allow a user to be authenticated tosite-a.atlassian.netvia one server config andsite-b.atlassian.netvia another simultaneously.Happy to provide additional detail or test a fix if that's helpful.
TylerLeonhardt commentedon Mar 19, 2026
This doesn't seem aligned to OAuth 2.0 spec.
https://datatracker.ietf.org/doc/html/rfc8414#section-2
I'm trying to understand how to map Atlassian's setup to what we follow which is standard OAuth 2.0. I can't be in the business of special casing Atlassian.
7 remaining items
oracle 0.4.0: mcp-fleet multi-workspace OAuth onboarding + v0.3.1 def…
oracle 0.4.0: mcp-fleet multi-workspace OAuth onboarding + v0.3.1 def…
celidrissi commentedon Jul 7, 2026
+1 for this. Very anoying issue 🥲
rpelevin commentedon Jul 7, 2026
Small regression shape I would want here: keep OAuth issuer discovery separate from the local credential slot identity.
I would test two MCP server entries that share the same authorization server and provider origin, but represent different configured resources or site bindings:
That keeps the RFC 8414 issuer semantics intact while making the client-side storage invariant explicit: the credential lookup key should include the configured MCP server identity or resource binding, not only the OAuth provider origin. A useful negative test is token A being valid cryptographically but rejected for entry B because the local credential slot, resource binding, or site context no longer matches the proposed MCP call.
agentHost: send each MCP OAuth token only to its target server (micro…