fix(server/oauth): use URL constructor to avoid double slash in metadata proxy#1483
Merged
Merged
Conversation
…ata proxy
The DCR-direct metadata proxy was string-concatenating a path onto the
issuer, which canonically ends with a trailing slash:
`${issuer}/.well-known/oauth-authorization-server`
// → "https://tenant.auth0.com//.well-known/oauth-authorization-server"
Auth0 returns 404 for any path starting with "//", which broke OAuth
discovery end-to-end against real Auth0 tenants in DCR-direct mode.
new URL(path, base) normalizes the join regardless of trailing slash, so
this works for any provider whose canonical issuer ends with "/".
Fixes mcp-use#1482.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
khandrew1
requested changes
May 12, 2026
…RL constructor
`new URL("/.well-known/...", issuer)` resolves the leading-slash path against
the issuer's origin, stripping any path on the issuer. That breaks providers
like Supabase whose issuer is `https://<project>.supabase.co/auth/v1`. Replace
with a trailing-slash-stripping template literal, which handles both Auth0
(issuer ends with `/`) and Supabase (issuer has a path).
khandrew1
approved these changes
May 18, 2026
commit: |
Contributor
|
| SDK | Score | vs main | vs canary |
|---|---|---|---|
| typescript | 30/30 (100%) | ⚪ +0 | ⚪ +0 |
All passing — click to expand
| Scenario | typescript |
|---|---|
| completion-complete | ✅ |
| dns-rebinding-protection | ✅ |
| elicitation-sep1034-defaults | ✅ |
| elicitation-sep1330-enums | ✅ |
| logging-set-level | ✅ |
| ping | ✅ |
| prompts-get-embedded-resource | ✅ |
| prompts-get-simple | ✅ |
| prompts-get-with-args | ✅ |
| prompts-get-with-image | ✅ |
| prompts-list | ✅ |
| resources-list | ✅ |
| resources-read-binary | ✅ |
| resources-read-text | ✅ |
| resources-subscribe | ✅ |
| resources-templates-read | ✅ |
| resources-unsubscribe | ✅ |
| server-initialize | ✅ |
| server-sse-multiple-streams | ✅ |
| tools-call-audio | ✅ |
| tools-call-elicitation | ✅ |
| tools-call-embedded-resource | ✅ |
| tools-call-error | ✅ |
| tools-call-image | ✅ |
| tools-call-mixed-content | ✅ |
| tools-call-sampling | ✅ |
| tools-call-simple-text | ✅ |
| tools-call-with-logging | ✅ |
| tools-call-with-progress | ✅ |
| tools-list | ✅ |
Client Conformance
| SDK | Score | vs main | vs canary |
|---|---|---|---|
| typescript-browser-client | 20/20 (100%) | ⚪ +0 | ⚪ +0 |
| typescript-node-client | 20/20 (100%) | ⚪ +0 | ⚪ +0 |
| typescript-react-client | 20/20 (100%) | ⚪ +0 | ⚪ +0 |
All passing — click to expand
| Scenario | typescript-browser-client | typescript-node-client | typescript-react-client |
|---|---|---|---|
| auth/2025-03-26-oauth-endpoint-fallback | ✅ | ✅ | ✅ |
| auth/2025-03-26-oauth-metadata-backcompat | ✅ | ✅ | ✅ |
| auth/basic-cimd | ✅ | ✅ | ✅ |
| auth/metadata-default | ✅ | ✅ | ✅ |
| auth/metadata-var1 | ✅ | ✅ | ✅ |
| auth/metadata-var2 | ✅ | ✅ | ✅ |
| auth/metadata-var3 | ✅ | ✅ | ✅ |
| auth/pre-registration | ✅ | ✅ | ✅ |
| auth/scope-from-scopes-supported | ✅ | ✅ | ✅ |
| auth/scope-from-www-authenticate | ✅ | ✅ | ✅ |
| auth/scope-omitted-when-undefined | ✅ | ✅ | ✅ |
| auth/scope-retry-limit | ✅ | ✅ | ✅ |
| auth/scope-step-up | ✅ | ✅ | ✅ |
| auth/token-endpoint-auth-basic | ✅ | ✅ | ✅ |
| auth/token-endpoint-auth-none | ✅ | ✅ | ✅ |
| auth/token-endpoint-auth-post | ✅ | ✅ | ✅ |
| elicitation-sep1034-client-defaults | ✅ | ✅ | ✅ |
| initialize | ✅ | ✅ | ✅ |
| sse-retry | ✅ | ✅ | ✅ |
| tools_call | ✅ | ✅ | ✅ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the metadata-proxy URL construction in DCR-direct OAuth mode (
oauthAuth0Provider, and any other provider whose canonical issuer ends with/).Before:
\${issuer}/.well-known/oauth-authorization-server`→https://tenant.auth0.com//.well-known/...` → Auth0 returns 404 → MCP server's/.well-known/oauth-authorization-serverreturns500 server_error, which aborts Claude Desktop's OAuth flow end-to-end.After:
new URL("/.well-known/oauth-authorization-server", issuer).toString()→ correct URL regardless of whetherissuercarries a trailing slash.Why this matters
auth0.ts:21deliberately stores the issuer with a trailing slash because that's the canonical form Auth0 puts in theissclaim of every JWT, andverifyToken(auth0.ts:52) validates against this exact string. So the issuer must end with/. The bug was in the consumer not accounting for that.Repro
Closes #1482 — full reproduction steps + direct-curl evidence (200 vs 404) are there.
Test plan
MCPServerwithoauthAuth0Provider({ domain, audience }), curl/.well-known/oauth-authorization-server, confirm the response is Auth0's actual metadata JSON (issuer, registration_endpoint, etc.) instead of{"error":"server_error",...}.src/server/oauth/routes.ts). Happy to add one — a mock fetch + assertion on the constructed URL would cover this. Let me know if you'd prefer that before merge.Notes
While confirming the bug I noticed
routes.tshas similar string concatenations elsewhere (lines 295/296/297/385) that build${baseUrl}/...URLs. Those use a differentbaseUrl(the MCP server's own URL, not the upstream issuer), so they may be fine — but worth a grep if anyone wants to harden the file further. Out of scope for this PR.Changeset
Patch bump on
mcp-use. Included inlibraries/typescript/.changeset/fix-oauth-metadata-double-slash.md.🤖 Generated with Claude Code