Summary
Muster's OAuth client (oauth.mcpClient) cannot authenticate to remote MCP servers that expose only RFC 8414 Authorization Server Metadata at /.well-known/oauth-authorization-server, because discoverProtectedResourceMetadata in internal/aggregator/server.go requires RFC 9728 Protected Resource Metadata at /.well-known/oauth-protected-resource and does not fall back.
A concrete victim of this is Atlassian's hosted Remote MCP at https://mcp.atlassian.com/v1/mcp, which is a real endpoint many users want to connect to.
Reproduction
- Configure muster with the OAuth proxy enabled:
# ~/.config/muster/config.yaml
aggregator:
oauth:
mcpClient:
enabled: true
publicUrl: http://localhost:8090
- Add an OAuth-protected MCP server pointing at Atlassian's hosted MCP:
# ~/.config/muster/mcpservers/atlassian.yaml
apiVersion: muster.giantswarm.io/v1alpha1
kind: MCPServer
metadata:
name: atlassian
spec:
auth:
type: oauth
autoStart: true
type: streamable-http
url: https://mcp.atlassian.com/v1/mcp
muster serve (v0.1.130).
muster auth login --server atlassian
Expected
Browser-based OAuth flow opens against Atlassian's authorization server, completes via DCR, server reaches Connected state.
Actual
Authenticating to atlassian...
Error: failed to call auth tool: meta-tool error for core_auth_login:
{"isError":true,"content":[{"text":"Cannot authenticate to 'atlassian':
unable to discover OAuth authorization server. The server's
/.well-known/oauth-protected-resource endpoint may not be available."}]}
Server log:
level=WARN msg="Failed to discover protected resource metadata for atlassian:
resource metadata returned status 404" subsystem=AuthTools
level=WARN msg="Login failure for server atlassian by user default-...:
issuer_discovery_failed (failures: 1)" subsystem=AuthMetrics
Why discovery fails
Atlassian doesn't publish RFC 9728 Protected Resource Metadata at any unauthenticated path:
| Path |
Status |
https://mcp.atlassian.com/.well-known/oauth-protected-resource |
404 |
https://mcp.atlassian.com/v1/.well-known/oauth-protected-resource |
404 |
https://mcp.atlassian.com/v1/mcp/.well-known/oauth-protected-resource |
401 (catch-22: requires the very token we're trying to obtain) |
But Atlassian does publish full RFC 8414 Authorization Server Metadata at the root:
$ curl -sS https://mcp.atlassian.com/.well-known/oauth-authorization-server | jq .
{
"issuer": "https://cf.mcp.atlassian.com",
"authorization_endpoint": "https://mcp.atlassian.com/v1/authorize",
"token_endpoint": "https://cf.mcp.atlassian.com/v1/token",
"registration_endpoint": "https://cf.mcp.atlassian.com/v1/register",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post", "none"],
"code_challenge_methods_supported": ["plain", "S256"],
...
}
This is enough to complete the OAuth flow:
- DCR endpoint is advertised → muster's CIMD-based public-client registration would succeed.
- Authorization + token endpoints are advertised → the standard auth-code + PKCE flow would work.
token_endpoint_auth_methods_supported: ["none"] → public-client (no client secret) is supported, matching muster's CIMD model.
Proposed Fix
Augment discoverProtectedResourceMetadata (internal/aggregator/server.go:2238) with a fallback chain when the RFC 9728 path returns 404:
- RFC 9728:
<base>/.well-known/oauth-protected-resource (current behavior)
- NEW — Parse
WWW-Authenticate header on the 401 from the resource itself for resource_metadata=... parameter (per MCP Auth spec 2025-06-18, §2.1) and follow it.
- NEW — RFC 8414 fallback:
<base>/.well-known/oauth-authorization-server — if it parses, treat its issuer as the authorization server and the response itself as AS metadata, skipping the protected-resource indirection.
- NEW — OpenID Connect Discovery fallback:
<base>/.well-known/openid-configuration — same shape as RFC 8414 in practice for OIDC providers.
Alternatively (simpler MVP): allow operators to manually specify the authorization server in the MCPServer spec, bypassing discovery:
spec:
auth:
type: oauth
authorizationServer: # NEW
issuer: https://cf.mcp.atlassian.com
scopes: "openid offline_access"
When set, skip discovery entirely and use these values. This unblocks users today without re-engineering the discovery code.
Impact
Without one of the above, muster cannot connect to:
- Atlassian Remote MCP (
mcp.atlassian.com)
- Any other future hosted MCP that follows the RFC 8414 / OIDC Discovery convention without ALSO publishing RFC 9728 metadata
Muster's documentation should be updated either way to call out this constraint, but the codebase fix is preferable.
Workaround used today
Switched to the local stdio variant (mcp-atlassian Python package via uvx) authenticated with API tokens. Functional but ties auth to a per-user PAT instead of OAuth-flow-issued credentials.
Environment
muster version 0.1.106 (initial repro), muster version 0.1.130 (latest, same behavior)
- macOS, single-user local install (
muster serve against ~/.config/muster)
- Endpoint:
https://mcp.atlassian.com/v1/mcp (Atlassian hosted Remote MCP)
References
Summary
Muster's OAuth client (
oauth.mcpClient) cannot authenticate to remote MCP servers that expose only RFC 8414 Authorization Server Metadata at/.well-known/oauth-authorization-server, becausediscoverProtectedResourceMetadataininternal/aggregator/server.gorequires RFC 9728 Protected Resource Metadata at/.well-known/oauth-protected-resourceand does not fall back.A concrete victim of this is Atlassian's hosted Remote MCP at
https://mcp.atlassian.com/v1/mcp, which is a real endpoint many users want to connect to.Reproduction
muster serve(v0.1.130).muster auth login --server atlassianExpected
Browser-based OAuth flow opens against Atlassian's authorization server, completes via DCR, server reaches
Connectedstate.Actual
Server log:
Why discovery fails
Atlassian doesn't publish RFC 9728 Protected Resource Metadata at any unauthenticated path:
https://mcp.atlassian.com/.well-known/oauth-protected-resourcehttps://mcp.atlassian.com/v1/.well-known/oauth-protected-resourcehttps://mcp.atlassian.com/v1/mcp/.well-known/oauth-protected-resourceBut Atlassian does publish full RFC 8414 Authorization Server Metadata at the root:
This is enough to complete the OAuth flow:
token_endpoint_auth_methods_supported: ["none"]→ public-client (no client secret) is supported, matching muster's CIMD model.Proposed Fix
Augment
discoverProtectedResourceMetadata(internal/aggregator/server.go:2238) with a fallback chain when the RFC 9728 path returns 404:<base>/.well-known/oauth-protected-resource(current behavior)WWW-Authenticateheader on the 401 from the resource itself forresource_metadata=...parameter (per MCP Auth spec 2025-06-18, §2.1) and follow it.<base>/.well-known/oauth-authorization-server— if it parses, treat itsissueras the authorization server and the response itself asAS metadata, skipping the protected-resource indirection.<base>/.well-known/openid-configuration— same shape as RFC 8414 in practice for OIDC providers.Alternatively (simpler MVP): allow operators to manually specify the authorization server in the
MCPServerspec, bypassing discovery:When set, skip discovery entirely and use these values. This unblocks users today without re-engineering the discovery code.
Impact
Without one of the above, muster cannot connect to:
mcp.atlassian.com)Muster's documentation should be updated either way to call out this constraint, but the codebase fix is preferable.
Workaround used today
Switched to the local stdio variant (
mcp-atlassianPython package viauvx) authenticated with API tokens. Functional but ties auth to a per-user PAT instead of OAuth-flow-issued credentials.Environment
muster version 0.1.106(initial repro),muster version 0.1.130(latest, same behavior)muster serveagainst~/.config/muster)https://mcp.atlassian.com/v1/mcp(Atlassian hosted Remote MCP)References
internal/aggregator/server.go:2238(discoverProtectedResourceMetadata)