From 692ca2ce6e7ad715d7a6a5d484a4843ff466cb65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B2=94=ED=99=98?= <95680257+bumhwan@users.noreply.github.com> Date: Thu, 3 Sep 2026 12:40:43 +0900 Subject: [PATCH] [v1.x] docs(server/auth): document that resourceServerUrl and resourceMetadataUrl are needed for MCP-compliant discovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both options are optional in the types, but for an MCP server both are effectively required: without resourceServerUrl the Protected Resource Metadata is served at the root well-known with resource set to the origin (not the MCP endpoint), and without resourceMetadataUrl the 401 challenge has no resource_metadata parameter, which the MCP authorization spec requires. Clients that enforce RFC 9728 §3.3 literally (Gemini CLI, Antigravity CLI) abort discovery on the resulting documents while the reference client accepts them, so server authors get no signal. Spell this out in the JSDoc. No behaviour change. Refs #2751 Co-Authored-By: Claude Fable 5.1 --- src/server/auth/middleware/bearerAuth.ts | 6 +++++- src/server/auth/router.ts | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/server/auth/middleware/bearerAuth.ts b/src/server/auth/middleware/bearerAuth.ts index dac6530865..923995e558 100644 --- a/src/server/auth/middleware/bearerAuth.ts +++ b/src/server/auth/middleware/bearerAuth.ts @@ -15,7 +15,11 @@ export type BearerAuthMiddlewareOptions = { requiredScopes?: string[]; /** - * Optional resource metadata URL to include in WWW-Authenticate header. + * Resource metadata URL to advertise in the `WWW-Authenticate` challenge on 401/403 + * responses (RFC 9728 §5.1). The MCP authorization spec requires MCP servers to send it, so + * pass `getOAuthProtectedResourceMetadataUrl(mcpServerUrl)` for any protected MCP endpoint. + * When omitted, clients must guess the well-known location and strict clients can fail + * discovery; leave it out only for non-MCP or legacy deployments. */ resourceMetadataUrl?: string; }; diff --git a/src/server/auth/router.ts b/src/server/auth/router.ts index 1df0be091f..e4271e283f 100644 --- a/src/server/auth/router.ts +++ b/src/server/auth/router.ts @@ -51,6 +51,14 @@ export type AuthRouterOptions = { /** * The URL of the protected resource (RS) whose metadata we advertise. * If not provided, falls back to `baseUrl` and then to `issuerUrl` (AS=RS). + * + * Pass the MCP endpoint URL itself (e.g. `https://api.example.com/mcp`), not just the + * origin. RFC 9728 §3 places the metadata at + * `/.well-known/oauth-protected-resource/` and §3.3 requires its `resource` to be + * identical to the resource the client connected to. The `baseUrl` fallback therefore only + * yields a compliant document when the MCP endpoint is served at the origin root; clients + * that enforce §3.3 (Gemini CLI, Antigravity CLI) reject `resource: https://host/` when they + * connected to `https://host/mcp`, while the reference SDK client happens to accept it. */ resourceServerUrl?: URL;