From 19e1357a06e1732a8a08c848e2a7d92e982dc8d0 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Tue, 22 Sep 2026 00:25:06 -0500 Subject: [PATCH] fix(core): stop forcing a consent prompt on MCP OAuth login (#50519) --- packages/core/test/mcp-oauth.test.ts | 9 +++++++++ ...@modelcontextprotocol%2Fclient@2.0.0.patch | 20 +++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/packages/core/test/mcp-oauth.test.ts b/packages/core/test/mcp-oauth.test.ts index 76a9ce55b87..3ca361cca04 100644 --- a/packages/core/test/mcp-oauth.test.ts +++ b/packages/core/test/mcp-oauth.test.ts @@ -422,6 +422,15 @@ describe("MCP OAuth", () => { expect(tokenRequests[0]?.get("grant_type")).toBe("refresh_token") }) + test("requests offline_access without forcing a consent prompt", async () => { + const { server } = authorizationServer({ scopes_supported: ["read", "offline_access"] }) + const { url } = await Effect.runPromise( + Effect.scoped(start(server, { client_id: "client", scope: "read" })), + ).finally(() => server.stop(true)) + expect(url.searchParams.get("scope")).toBe("read offline_access") + expect(url.searchParams.has("prompt")).toBe(false) + }) + test("forwards iss from the redirect so issuer-advertising servers can complete", async () => { const { server } = authorizationServer({ authorization_response_iss_parameter_supported: true }) const result = await Effect.runPromise( diff --git a/patches/@modelcontextprotocol%2Fclient@2.0.0.patch b/patches/@modelcontextprotocol%2Fclient@2.0.0.patch index 8a2b217f062..24f289be493 100644 --- a/patches/@modelcontextprotocol%2Fclient@2.0.0.patch +++ b/patches/@modelcontextprotocol%2Fclient@2.0.0.patch @@ -1,5 +1,5 @@ diff --git a/dist/index.cjs b/dist/index.cjs -index 635f1c0134274c89e7efbcae2adf3d9ecba575ee..0054b779ff7b550ecf6d4008e177a888003f9c92 100644 +index 635f1c0134274c89e7efbcae2adf3d9ecba575ee..5eaa7b451c8c7e12e51f61c2a835ff6f7a8ea0ae 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -977,7 +977,6 @@ async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, o @@ -10,8 +10,16 @@ index 635f1c0134274c89e7efbcae2adf3d9ecba575ee..0054b779ff7b550ecf6d4008e177a888 } let response = await tryMetadataDiscovery(url, protocolVersion, fetchFn); if (!opts?.metadataUrl && shouldAttemptFallback(response, issuer.pathname)) response = await tryMetadataDiscovery(new URL(`/.well-known/${wellKnownType}`, issuer), protocolVersion, fetchFn); +@@ -1158,7 +1157,6 @@ async function startAuthorization(authorizationServerUrl, { metadata, clientInfo + authorizationUrl.searchParams.set("redirect_uri", String(redirectUrl)); + if (state) authorizationUrl.searchParams.set("state", state); + if (scope) authorizationUrl.searchParams.set("scope", scope); +- if (scope?.split(" ").includes("offline_access")) authorizationUrl.searchParams.append("prompt", "consent"); + if (resource) authorizationUrl.searchParams.set("resource", resource.href); + return { + authorizationUrl, diff --git a/dist/index.mjs b/dist/index.mjs -index f02ce3ca394e826fc27c9848dbe9a214bf6ba7a9..8e27c9320e14ba8816fda752f250f6ddb1cc7ed0 100644 +index f02ce3ca394e826fc27c9848dbe9a214bf6ba7a9..73a93a066c3540e131fa0770a74b4a7e8d9343a0 100644 --- a/dist/index.mjs +++ b/dist/index.mjs @@ -974,7 +974,6 @@ async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, o @@ -22,3 +30,11 @@ index f02ce3ca394e826fc27c9848dbe9a214bf6ba7a9..8e27c9320e14ba8816fda752f250f6dd } let response = await tryMetadataDiscovery(url, protocolVersion, fetchFn); if (!opts?.metadataUrl && shouldAttemptFallback(response, issuer.pathname)) response = await tryMetadataDiscovery(new URL(`/.well-known/${wellKnownType}`, issuer), protocolVersion, fetchFn); +@@ -1155,7 +1154,6 @@ async function startAuthorization(authorizationServerUrl, { metadata, clientInfo + authorizationUrl.searchParams.set("redirect_uri", String(redirectUrl)); + if (state) authorizationUrl.searchParams.set("state", state); + if (scope) authorizationUrl.searchParams.set("scope", scope); +- if (scope?.split(" ").includes("offline_access")) authorizationUrl.searchParams.append("prompt", "consent"); + if (resource) authorizationUrl.searchParams.set("resource", resource.href); + return { + authorizationUrl,