fix issues

This commit is contained in:
Paola Estefanía de Campos
2026-02-20 21:06:05 -08:00
parent 195ff451ba
commit 20bcbcefd5
4 changed files with 21 additions and 21 deletions

View File

@@ -359,6 +359,7 @@ The examples above use `withMcpAuth` which requires the Better Auth instance to
}) // [!code highlight]
const mcpServer = new McpServer({ name: "my-server", version: "1.0.0" })
const app = express() // your HTTP framework
app.post("/mcp", auth.handler(async (req, session) => { // [!code highlight]
const transport = new StreamableHTTPServerTransport({
@@ -402,9 +403,9 @@ The examples above use `withMcpAuth` which requires the Better Auth instance to
type: "string",
required: false
},
allowedOrigins: {
description: "Allowed CORS origin(s). Defaults to the authURL origin. Set to '*' to allow all origins (not recommended for production).",
type: "string | string[]",
allowedOrigin: {
description: "Allowed CORS origin. Defaults to the authURL origin. Set to '*' to allow all origins (not recommended for production).",
type: "string",
required: false
},
fetch: {

View File

@@ -32,14 +32,18 @@ export function mcpAuthHono(options: McpAuthClientOptions): {
} {
const client = createMcpAuthClient(options);
const resourceBase = options.resource ?? client.authURL;
const middleware: HonoMiddleware = async (c, next) => {
const token = c.req.header("Authorization")?.replace("Bearer ", "");
const authHeader = c.req.header("Authorization");
const token = authHeader?.startsWith("Bearer ")
? authHeader.slice(7)
: undefined;
if (!token) {
c.header(
"WWW-Authenticate",
`Bearer resource_metadata="${client.authURL}/.well-known/oauth-protected-resource"`,
`Bearer resource_metadata="${resourceBase}/.well-known/oauth-protected-resource"`,
);
c.header("Access-Control-Expose-Headers", "WWW-Authenticate");
return c.json(
{
jsonrpc: "2.0",
@@ -57,7 +61,7 @@ export function mcpAuthHono(options: McpAuthClientOptions): {
if (!session) {
c.header(
"WWW-Authenticate",
`Bearer resource_metadata="${client.authURL}/.well-known/oauth-protected-resource"`,
`Bearer resource_metadata="${resourceBase}/.well-known/oauth-protected-resource"`,
);
return c.json(
{

View File

@@ -1,7 +1,7 @@
export interface McpAuthClientOptions {
authURL: string;
resource?: string;
allowedOrigins?: string | string[];
allowedOrigin?: string;
fetch?: typeof globalThis.fetch;
}
@@ -65,13 +65,11 @@ export interface McpAuthClient {
function buildCorsHeaders(
authURL: string,
allowedOrigins?: string | string[],
allowedOrigin?: string,
): Record<string, string> {
let origin: string;
if (allowedOrigins) {
origin = Array.isArray(allowedOrigins)
? allowedOrigins.join(", ")
: allowedOrigins;
if (allowedOrigin) {
origin = allowedOrigin;
} else {
try {
origin = new URL(authURL).origin;
@@ -110,7 +108,6 @@ function make401Response(authURL: string, resource?: string): Response {
status: 401,
headers: {
"WWW-Authenticate": wwwAuth,
"Access-Control-Expose-Headers": "WWW-Authenticate",
},
},
);
@@ -129,13 +126,11 @@ function send401Node(
if (typeof res.set === "function") {
res.set("WWW-Authenticate", wwwAuth);
res.set("Access-Control-Expose-Headers", "WWW-Authenticate");
res.status?.(401).json(JSON.parse(body));
} else if (typeof res.writeHead === "function") {
res.writeHead(401, {
"Content-Type": "application/json",
"WWW-Authenticate": wwwAuth,
"Access-Control-Expose-Headers": "WWW-Authenticate",
});
res.end?.(body);
}
@@ -148,7 +143,7 @@ export function createMcpAuthClient(
? options.authURL.slice(0, -1)
: options.authURL;
const fetchFn = options.fetch ?? globalThis.fetch;
const corsHeaders = buildCorsHeaders(authURL, options.allowedOrigins);
const corsHeaders = buildCorsHeaders(authURL, options.allowedOrigin);
const verifyToken = async (token: string): Promise<McpSession | null> => {
try {

View File

@@ -145,7 +145,7 @@ describe("mcp-client", async () => {
it("should allow custom CORS origins", async () => {
const client = createMcpAuthClient({
authURL,
allowedOrigins: "https://myapp.com",
allowedOrigin: "https://myapp.com",
});
const protectedHandler = client.handler(async () => {
@@ -175,7 +175,7 @@ describe("mcp-client", async () => {
scopes: "openid profile email",
};
const mockFetch: typeof fetch = async (input) => {
const mockFetch = (async (input: RequestInfo | URL) => {
const url = typeof input === "string" ? input : (input as Request).url;
if (url.includes("/mcp/get-session")) {
return new Response(JSON.stringify(mockSession), {
@@ -184,7 +184,7 @@ describe("mcp-client", async () => {
});
}
return new Response("Not Found", { status: 404 });
};
}) as typeof fetch;
it("should return session for a valid token", async () => {
const client = createMcpAuthClient({
@@ -401,7 +401,7 @@ describe("mcp-client", async () => {
const mockReq = {
headers: { authorization: "Bearer invalid-token-for-test" },
mcpSession: undefined as unknown,
mcpSession: undefined as McpSession | undefined,
};
const mockRes = {
set: (_key: string, _value: string) => {},