From 13c9dac2895ba1c555c65d7acd3d4d078a5ddfe0 Mon Sep 17 00:00:00 2001 From: Andrew Qu Date: Wed, 4 Jun 2025 10:59:30 -0700 Subject: [PATCH 1/3] .changeset/spicy-dragons-relate.md src/next/auth-wrapper.ts --- .changeset/spicy-dragons-relate.md | 5 +++++ src/next/auth-wrapper.ts | 22 +++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 .changeset/spicy-dragons-relate.md diff --git a/.changeset/spicy-dragons-relate.md b/.changeset/spicy-dragons-relate.md new file mode 100644 index 0000000..6990a88 --- /dev/null +++ b/.changeset/spicy-dragons-relate.md @@ -0,0 +1,5 @@ +--- +"@vercel/mcp-adapter": patch +--- + +Update auth logic to not throw error is missing bearerToken diff --git a/src/next/auth-wrapper.ts b/src/next/auth-wrapper.ts index d71de22..02b6ef1 100644 --- a/src/next/auth-wrapper.ts +++ b/src/next/auth-wrapper.ts @@ -4,7 +4,8 @@ import { withAuthContext } from "./auth-context"; export function withMcpAuth( handler: (req: Request) => Response | Promise, verifyToken: ( - req: Request + req: Request, + bearerToken?: string ) => AuthInfo | undefined | Promise, { required = false, @@ -17,13 +18,17 @@ export function withMcpAuth( return async (req: Request) => { const origin = new URL(req.url).origin; - const authInfo = await verifyToken(req); + const authHeader = req.headers.get("Authorization"); + const [_, bearerToken] = authHeader?.split(" ") || []; + + const authInfo = await verifyToken(req, bearerToken); + if (required && !authInfo) { - return Response.json( - { + return new Response( + JSON.stringify({ error: "unauthorized_client", error_description: "No authorization provided", - }, + }), { status: 401, headers: { @@ -38,8 +43,11 @@ export function withMcpAuth( } if (authInfo.expiresAt && authInfo.expiresAt < Date.now() / 1000) { - return Response.json( - { error: "invalid_token", error_description: "Authorization expired" }, + return new Response( + JSON.stringify({ + error: "invalid_token", + error_description: "Authorization expired", + }), { status: 401, headers: { From 33ffbacf5f66aba54360885b4758128aed1037c6 Mon Sep 17 00:00:00 2001 From: Andrew Qu Date: Wed, 4 Jun 2025 11:24:32 -0700 Subject: [PATCH 2/3] src/next/auth-wrapper.ts --- src/next/auth-wrapper.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/next/auth-wrapper.ts b/src/next/auth-wrapper.ts index 02b6ef1..6e72ada 100644 --- a/src/next/auth-wrapper.ts +++ b/src/next/auth-wrapper.ts @@ -19,8 +19,9 @@ export function withMcpAuth( const origin = new URL(req.url).origin; const authHeader = req.headers.get("Authorization"); - const [_, bearerToken] = authHeader?.split(" ") || []; + const [type, token] = authHeader?.split(" ") || []; + const bearerToken = type?.toLowerCase() === "bearer" ? token : undefined; const authInfo = await verifyToken(req, bearerToken); if (required && !authInfo) { From 52ffe92cd08351da310b8d85d370c782baf21fb2 Mon Sep 17 00:00:00 2001 From: Andrew Qu Date: Wed, 4 Jun 2025 11:24:57 -0700 Subject: [PATCH 3/3] src/next/auth-wrapper.ts --- src/next/auth-wrapper.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/next/auth-wrapper.ts b/src/next/auth-wrapper.ts index 6e72ada..75e835d 100644 --- a/src/next/auth-wrapper.ts +++ b/src/next/auth-wrapper.ts @@ -21,7 +21,10 @@ export function withMcpAuth( const authHeader = req.headers.get("Authorization"); const [type, token] = authHeader?.split(" ") || []; + // Only support bearer token as per the MCP spec + // https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization#2-6-1-token-requirements const bearerToken = type?.toLowerCase() === "bearer" ? token : undefined; + const authInfo = await verifyToken(req, bearerToken); if (required && !authInfo) {