Multi-route MCP OAuth discovery uses resource-specific well-known paths
Date: 2026-07-03 Status: Accepted Decision: hl-2jrh Deciders: Sean
Context
Section titled “Context”agentgateway MCP routes that enforce jwtAuthentication.mcp advertise RFC 9728
protected-resource metadata at a /.well-known/oauth-protected-resource path, which
OAuth-discovering MCP clients (e.g. claude mcp add) fetch after a 401. engram — the
first and until now only such route — matches the BARE /.well-known/oauth-protected-resource
prefix. Hosting more OAuth-gated MCP routes on the same host (mcp-gw.fzymgc.house) makes
that bare match ambiguous.
Decision
Section titled “Decision”Each OAuth-gated MCP route matches the RESOURCE-SPECIFIC path
/.well-known/oauth-protected-resource/mcp/<name> (e.g. .../mcp/kubernetes,
.../mcp/terraform-ro), not the bare prefix. This is the exact discovery URL agentgateway
returns: create_auth_required_response builds the WWW-Authenticate: Bearer resource_metadata="..." value by appending the request path to
/.well-known/oauth-protected-resource.
Rationale
Section titled “Rationale”- agentgateway appends the request path, so the discovery URL for
/mcp/kubernetesIS/.well-known/oauth-protected-resource/mcp/kubernetes— matching the suffix is matching exactly what the gateway hands the client. - Multiple routes matching the BARE prefix collide under Gateway API most-specific-match precedence (undefined behavior for equal specificity) — a client could be served the wrong resource’s metadata.
- The per-resource suffix is the longest/most-specific match for each route’s own discovery URL, so it is collision-free and stays correct as MCP routes proliferate.
Alternatives Considered
Section titled “Alternatives Considered”- Copy engram’s bare-prefix match (rejected): works only while engram is the sole OAuth-gated route; at N>1 routes it collides and misroutes discovery.
Consequences
Section titled “Consequences”- Positive: correct, collision-free OAuth discovery as MCP routes multiply behind one host.
- Negative: engram’s existing bare-prefix route should eventually migrate to the suffix form (tracked as a follow-up).
- Neutral: no runtime change for a single-route host; the pattern only matters at N>1.