{"version":3,"file":"adapters.mjs","names":[],"sources":["../../../../src/plugins/mcp/client/adapters.ts"],"sourcesContent":["import type {\n\tMcpAuthClient,\n\tMcpAuthClientOptions,\n\tMcpSession,\n} from \"./index.js\";\nimport { createMcpAuthClient } from \"./index.js\";\n\ninterface HonoContext {\n\treq: { header: (name: string) => string | undefined; raw: Request };\n\tset: (key: string, value: unknown) => void;\n\tjson: (\n\t\tdata: unknown,\n\t\tstatus?: number,\n\t\theaders?: Record<string, string>,\n\t) => Response;\n\theader: (name: string, value: string) => void;\n}\ntype HonoNext = () => Promise<void>;\ntype HonoMiddleware = (\n\tc: HonoContext,\n\tnext: HonoNext,\n) => Promise<Response | void>;\n\ninterface HonoApp {\n\tget: (path: string, handler: (c: HonoContext) => Promise<Response>) => void;\n}\n\nexport function mcpAuthHono(options: McpAuthClientOptions): {\n\tclient: McpAuthClient;\n\tmiddleware: HonoMiddleware;\n\tdiscoveryRoutes: (app: HonoApp, serverURL: string) => void;\n} {\n\tconst client = createMcpAuthClient(options);\n\n\tconst resourceBase = options.resource ?? client.authURL;\n\n\tconst middleware: HonoMiddleware = async (c, next) => {\n\t\tconst authHeader = c.req.header(\"Authorization\");\n\t\tconst token = authHeader?.startsWith(\"Bearer \")\n\t\t\t? authHeader.slice(7)\n\t\t\t: undefined;\n\t\tif (!token) {\n\t\t\tc.header(\n\t\t\t\t\"WWW-Authenticate\",\n\t\t\t\t`Bearer resource_metadata=\"${resourceBase}/.well-known/oauth-protected-resource\"`,\n\t\t\t);\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tjsonrpc: \"2.0\",\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: -32000,\n\t\t\t\t\t\tmessage: \"Unauthorized: Authentication required\",\n\t\t\t\t\t},\n\t\t\t\t\tid: null,\n\t\t\t\t},\n\t\t\t\t401,\n\t\t\t);\n\t\t}\n\n\t\tconst session = await client.verifyToken(token);\n\t\tif (!session) {\n\t\t\tc.header(\n\t\t\t\t\"WWW-Authenticate\",\n\t\t\t\t`Bearer resource_metadata=\"${resourceBase}/.well-known/oauth-protected-resource\"`,\n\t\t\t);\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tjsonrpc: \"2.0\",\n\t\t\t\t\terror: { code: -32000, message: \"Invalid or expired token\" },\n\t\t\t\t\tid: null,\n\t\t\t\t},\n\t\t\t\t401,\n\t\t\t);\n\t\t}\n\n\t\tc.set(\"mcpSession\", session);\n\t\tawait next();\n\t};\n\n\tconst discoveryRoutes = (app: HonoApp, serverURL: string) => {\n\t\tconst discoveryFn = client.discoveryHandler();\n\t\tconst protectedResourceFn = client.protectedResourceHandler(serverURL);\n\n\t\tapp.get(\n\t\t\t\"/.well-known/oauth-authorization-server\",\n\t\t\tasync (c: HonoContext) => {\n\t\t\t\tconst response = await discoveryFn(c.req.raw);\n\t\t\t\tconst data: unknown = await response.json().catch(() => ({\n\t\t\t\t\terror: \"Invalid response from auth server\",\n\t\t\t\t}));\n\t\t\t\treturn c.json(data, response.status as 200 | 502);\n\t\t\t},\n\t\t);\n\n\t\tapp.get(\"/.well-known/oauth-protected-resource\", async (c: HonoContext) => {\n\t\t\tconst response = await protectedResourceFn(c.req.raw);\n\t\t\tconst data: unknown = await response.json().catch(() => ({\n\t\t\t\terror: \"Invalid response from auth server\",\n\t\t\t}));\n\t\t\treturn c.json(data, response.status as 200 | 502);\n\t\t});\n\t};\n\n\treturn { client, middleware, discoveryRoutes };\n}\n\nexport function mcpAuthOfficial(options: McpAuthClientOptions): {\n\tclient: McpAuthClient;\n\thandler: McpAuthClient[\"handler\"];\n\tverifyToken: McpAuthClient[\"verifyToken\"];\n} {\n\tconst client = createMcpAuthClient(options);\n\treturn {\n\t\tclient,\n\t\thandler: client.handler,\n\t\tverifyToken: client.verifyToken,\n\t};\n}\n\ntype OAuthMode = \"direct\" | \"proxy\";\n\ninterface McpUseUserInfo {\n\tuserId: string;\n\troles?: string[];\n\tpermissions?: string[];\n\tscopes?: string;\n\tclientId?: string;\n\t[key: string]: unknown;\n}\n\ninterface OAuthProvider {\n\tverifyToken(token: string): Promise<{ payload: Record<string, unknown> }>;\n\tgetUserInfo(payload: Record<string, unknown>): McpUseUserInfo;\n\tgetIssuer(): string;\n\tgetAuthEndpoint(): string;\n\tgetTokenEndpoint(): string;\n\tgetScopesSupported(): string[];\n\tgetGrantTypesSupported(): string[];\n\tgetMode(): OAuthMode;\n\tgetRegistrationEndpoint?(): string;\n}\n\nexport interface McpUseBetterAuthConfig {\n\tauthURL: string;\n\tgetUserInfo?: (payload: Record<string, unknown>) => McpUseUserInfo;\n}\n\nexport function mcpAuthMcpUse(config: McpUseBetterAuthConfig): OAuthProvider {\n\tconst authURL = normalizeURL(config.authURL);\n\n\tif (!authURL) {\n\t\tthrow new Error(\n\t\t\t\"Better Auth authURL is required. \" +\n\t\t\t\t\"Pass authURL in config, e.g.: mcpAuthMcpUse({ authURL: 'http://localhost:3000/api/auth' })\",\n\t\t);\n\t}\n\n\tconst client = createMcpAuthClient({ authURL });\n\n\treturn {\n\t\tasync verifyToken(\n\t\t\ttoken: string,\n\t\t): Promise<{ payload: Record<string, unknown> }> {\n\t\t\tconst session = await client.verifyToken(token);\n\t\t\tif (!session) {\n\t\t\t\tthrow new Error(\"Invalid or expired token\");\n\t\t\t}\n\t\t\treturn { payload: session as unknown as Record<string, unknown> };\n\t\t},\n\n\t\tgetUserInfo(payload: Record<string, unknown>): McpUseUserInfo {\n\t\t\tif (config.getUserInfo) {\n\t\t\t\treturn config.getUserInfo(payload);\n\t\t\t}\n\t\t\tconst scopes =\n\t\t\t\ttypeof payload.scopes === \"string\" ? payload.scopes.split(\" \") : [];\n\t\t\treturn {\n\t\t\t\tuserId: payload.userId as string,\n\t\t\t\troles: [],\n\t\t\t\tpermissions: scopes,\n\t\t\t\tscopes: payload.scopes as string | undefined,\n\t\t\t\tclientId: payload.clientId as string | undefined,\n\t\t\t};\n\t\t},\n\n\t\tgetIssuer() {\n\t\t\treturn authURL;\n\t\t},\n\n\t\tgetAuthEndpoint() {\n\t\t\treturn `${authURL}/mcp/authorize`;\n\t\t},\n\n\t\tgetTokenEndpoint() {\n\t\t\treturn `${authURL}/mcp/token`;\n\t\t},\n\n\t\tgetScopesSupported() {\n\t\t\treturn [\"openid\", \"profile\", \"email\", \"offline_access\"];\n\t\t},\n\n\t\tgetGrantTypesSupported() {\n\t\t\treturn [\"authorization_code\", \"refresh_token\"];\n\t\t},\n\n\t\tgetMode(): OAuthMode {\n\t\t\treturn \"direct\";\n\t\t},\n\n\t\tgetRegistrationEndpoint() {\n\t\t\treturn `${authURL}/mcp/register`;\n\t\t},\n\t};\n}\n\nfunction normalizeURL(url: string | undefined | null): string | undefined {\n\tif (!url || url.trim() === \"\") return undefined;\n\treturn url.endsWith(\"/\") ? url.slice(0, -1) : url;\n}\n\nexport type { McpSession, McpAuthClient, McpAuthClientOptions };\n"],"mappings":"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"}