{"version":3,"sources":["../src/handler/mcp-api-handler.ts","../src/lib/log-helper.ts","../src/webmcp/script-handler.ts","../src/handler/index.ts","../src/events/register.ts","../src/events/schemas.ts","../src/events/json.ts","../src/events/validate-delivery.ts","../src/auth/auth-wrapper.ts","../src/lib/url.ts","../src/auth/auth-metadata.ts"],"names":["name","messages"],"mappings":"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","sourcesContent":["import {\n  createMcpHandler as createSdkMcpHandler,\n  McpServer,\n  type CreateMcpHandlerOptions as SdkMcpHandlerOptions,\n  type ServerOptions as McpServerOptions,\n} from \"@modelcontextprotocol/server\";\nimport type {\n  McpEvent,\n  McpRequestEvent,\n  McpErrorEvent,\n} from \"../lib/log-helper\";\nimport { createEvent } from \"../lib/log-helper\";\nimport {\n  createWebMcpScriptHandler,\n  type WebMcpScriptHandlerOptions,\n} from \"../webmcp/script-handler\";\n\nexport type WebMcpOptions = Omit<WebMcpScriptHandlerOptions, \"endpoint\">;\n\n/**\n * Options for the MCP handler: the SDK's `ServerOptions` (capabilities,\n * instructions, ...) plus handler-level extras.\n */\nexport type McpHandlerOptions = McpServerOptions & {\n  /**\n   * Maximum number of concurrent `subscriptions/listen` streams.\n   * Set to `0` to reject subscriptions without opening an SSE stream.\n   * @default 1024\n   */\n  maxSubscriptions?: SdkMcpHandlerOptions[\"maxSubscriptions\"];\n  /**\n   * Name and version reported to clients during initialization.\n   */\n  serverInfo?: {\n    name: string;\n    version: string;\n  };\n  /**\n   * If true, enables console logging.\n   * @default false\n   */\n  verboseLogs?: boolean;\n  /**\n   * Callback function that receives MCP events.\n   * This can be used to track analytics, debug issues, or implement custom behaviors.\n   */\n  onEvent?: (event: McpEvent) => void;\n  /**\n   * Publishes an allowlisted subset of this server's tools to in-page agents\n   * through WebMCP. Load the generated bridge from the MCP route with the\n   * `?webmcp-script` query parameter.\n   *\n   * @experimental WebMCP is an early-stage browser API.\n   */\n  experimental_webMcp?: WebMcpOptions;\n};\n\nexport function initializeMcpApiHandler(\n  initializeServer:\n    | ((server: McpServer) => Promise<void>)\n    | ((server: McpServer) => void),\n  options: McpHandlerOptions = {},\n): (req: Request) => Promise<Response> {\n  const {\n    serverInfo = {\n      name: \"mcp-typescript server on vercel\",\n      version: \"0.1.0\",\n    },\n    verboseLogs = false,\n    onEvent,\n    maxSubscriptions,\n    experimental_webMcp,\n    ...mcpServerOptions\n  } = options;\n\n  // Validate WebMCP configuration when the handler is created rather than on\n  // the first request. The real endpoint is inferred from the script request.\n  if (experimental_webMcp) {\n    createWebMcpScriptHandler({\n      ...experimental_webMcp,\n      endpoint: \"/\",\n    });\n  }\n\n  const emitError = (error: Error) => {\n    if (verboseLogs) {\n      console.error(\"MCP handler error:\", error);\n    }\n    onEvent?.(\n      createEvent<McpErrorEvent>({\n        type: \"ERROR\",\n        error,\n        source: \"request\",\n        severity: \"error\",\n      }),\n    );\n  };\n\n  // The SDK handler serves the 2026-07-28 protocol (stateless, per-request\n  // envelope, server/discover) and falls back to stateless serving for\n  // 2025-era Streamable HTTP clients. A fresh McpServer is constructed per\n  // request via the factory.\n  const sdkHandler = createSdkMcpHandler(\n    async () => {\n      const server = new McpServer(serverInfo, mcpServerOptions);\n      await initializeServer(server);\n      return server;\n    },\n    {\n      legacy: \"stateless\",\n      onerror: emitError,\n      maxSubscriptions,\n    },\n  );\n\n  return async function mcpApiHandler(req: Request): Promise<Response> {\n    if (\n      experimental_webMcp &&\n      (req.method === \"GET\" || req.method === \"HEAD\")\n    ) {\n      const scriptUrl = new URL(req.url);\n      if (scriptUrl.searchParams.has(\"webmcp-script\")) {\n        scriptUrl.searchParams.delete(\"webmcp-script\");\n        return createWebMcpScriptHandler({\n          ...experimental_webMcp,\n          endpoint: scriptUrl.toString(),\n        })(req);\n      }\n    }\n\n    let method: string | undefined;\n    let parsedBody: unknown;\n    const started = Date.now();\n\n    if (\n      req.method === \"POST\" &&\n      (req.headers.get(\"content-type\") || \"\").includes(\"application/json\")\n    ) {\n      try {\n        parsedBody = await req.clone().json();\n        if (\n          typeof parsedBody === \"object\" &&\n          parsedBody !== null &&\n          \"method\" in parsedBody\n        ) {\n          method = String((parsedBody as { method: unknown }).method);\n          onEvent?.(\n            createEvent<McpRequestEvent>({\n              type: \"REQUEST_RECEIVED\",\n              method,\n              parameters: redactEventSecret(parsedBody),\n              status: \"success\",\n            }),\n          );\n        }\n      } catch {\n        // Malformed JSON is rejected by the SDK handler below.\n      }\n    }\n\n    try {\n      // withMcpAuth attaches the verified AuthInfo to this Request. Pass it\n      // explicitly so the SDK exposes it as ctx.http?.authInfo.\n      const response = await sdkHandler.fetch(req, {\n        authInfo: req.auth,\n        parsedBody,\n      });\n\n      if (method) {\n        onEvent?.(\n          createEvent<McpRequestEvent>({\n            type: \"REQUEST_COMPLETED\",\n            method,\n            duration: Date.now() - started,\n            status: response.ok ? \"success\" : \"error\",\n          }),\n        );\n      }\n      return response;\n    } catch (error) {\n      emitError(error instanceof Error ? error : new Error(String(error)));\n      throw error;\n    }\n  };\n}\n\nfunction redactEventSecret(body: object): object {\n  const request = body as { method?: unknown; params?: unknown };\n  if (\n    typeof request.method !== \"string\" ||\n    !request.method.startsWith(\"events/\") ||\n    !request.params ||\n    typeof request.params !== \"object\"\n  )\n    return body;\n  const params = request.params as { delivery?: unknown };\n  if (\n    !params.delivery ||\n    typeof params.delivery !== \"object\" ||\n    !(\"secret\" in params.delivery)\n  )\n    return body;\n  return {\n    ...body,\n    params: {\n      ...params,\n      delivery: { ...params.delivery, secret: \"[REDACTED]\" },\n    },\n  };\n}\n","export type McpEventType =\n  | \"REQUEST_RECEIVED\" // When a request is received from the client\n  | \"REQUEST_COMPLETED\" // When a request completes\n  | \"ERROR\"; // When an error occurs during any operation\n\nexport interface McpEventBase {\n  type: McpEventType;\n  timestamp: number;\n}\n\nexport interface McpRequestEvent extends McpEventBase {\n  type: \"REQUEST_RECEIVED\" | \"REQUEST_COMPLETED\";\n  method: string;\n  parameters?: unknown;\n  result?: unknown;\n  duration?: number; // For REQUEST_COMPLETED events\n  status: \"success\" | \"error\";\n}\n\nexport interface McpErrorEvent extends McpEventBase {\n  type: \"ERROR\";\n  error: Error | string;\n  context?: string;\n  source: \"request\" | \"system\";\n  severity: \"warning\" | \"error\" | \"fatal\";\n}\n\nexport type McpEvent = McpRequestEvent | McpErrorEvent;\n\nexport function createEvent<T extends McpEvent>(\n  event: Omit<T, \"timestamp\">,\n): T {\n  return {\n    ...event,\n    timestamp: Date.now(),\n  } as T;\n}\n","/**\n * Options for the WebMCP bridge script endpoint.\n */\nexport type WebMcpScriptHandlerOptions = {\n  /**\n   * URL of the MCP endpoint the script talks to. May be a path relative to\n   * the page origin (\"/api/mcp\") or an absolute URL.\n   */\n  endpoint: string;\n  /**\n   * Explicit allowlist of tool names exposed to in-page agents. Tools not\n   * listed here are never registered with the browser, even though they\n   * remain reachable through the MCP endpoint itself.\n   */\n  tools: string[];\n  /**\n   * Credentials mode for the tool-call fetches issued from the page.\n   * @default \"same-origin\"\n   */\n  credentials?: \"same-origin\" | \"include\" | \"omit\";\n  /**\n   * Value served in the script response's Cache-Control header.\n   * @default \"public, max-age=300\"\n   */\n  cacheControl?: string;\n};\n\ntype ScriptConfig = {\n  endpoint: string;\n  tools: string[];\n  credentials: string;\n};\n\n/**\n * Returns a Web-standard handler that serves a small browser script. When\n * loaded in a page, the script lists the tools of the MCP endpoint, filters\n * them down to the configured allowlist, and registers each one with the\n * page's WebMCP provider (`navigator.modelContext` / `document.modelContext`)\n * so in-page agents can call them. Tool calls run through `fetch` and carry\n * the user's session according to the configured credentials mode.\n *\n * WebMCP is an early-stage W3C proposal; in browsers without a provider (or\n * polyfill) the script is a no-op.\n */\nexport function createWebMcpScriptHandler(\n  options: WebMcpScriptHandlerOptions,\n): (req: Request) => Response {\n  const {\n    endpoint,\n    tools,\n    credentials = \"same-origin\",\n    cacheControl = \"public, max-age=300\",\n  } = options;\n\n  if (typeof endpoint !== \"string\" || endpoint.length === 0) {\n    throw new Error(\"createWebMcpScriptHandler: `endpoint` is required\");\n  }\n  if (\n    !Array.isArray(tools) ||\n    tools.some((name) => typeof name !== \"string\" || name.length === 0)\n  ) {\n    throw new Error(\n      \"createWebMcpScriptHandler: `tools` must be an array of tool names — only allowlisted tools are exposed to the web\",\n    );\n  }\n\n  const script = buildScript({ endpoint, tools, credentials });\n  const headers = {\n    \"content-type\": \"text/javascript; charset=utf-8\",\n    \"cache-control\": cacheControl,\n  };\n\n  return function webMcpScriptHandler(req: Request): Response {\n    if (req.method === \"HEAD\") {\n      return new Response(null, { status: 200, headers });\n    }\n    if (req.method !== \"GET\") {\n      return new Response(\"Method not allowed\", {\n        status: 405,\n        headers: { allow: \"GET, HEAD\" },\n      });\n    }\n    return new Response(script, { status: 200, headers });\n  };\n}\n\nfunction buildScript(config: ScriptConfig): string {\n  // \"<\" is escaped so the config can never terminate an inline <script> tag.\n  const configJson = JSON.stringify(config).replace(/</g, \"\\\\u003c\");\n\n  return `(() => {\n  \"use strict\";\n  const config = ${configJson};\n  const provider = [\n    typeof document !== \"undefined\" && document.modelContext,\n    typeof navigator !== \"undefined\" && navigator.modelContext,\n  ].find((candidate) => candidate && typeof candidate.registerTool === \"function\");\n  if (!provider || typeof provider.registerTool !== \"function\") {\n    return;\n  }\n\n  let protocolVersion = null;\n  let requestId = 0;\n\n  async function rpc(method, params, isNotification, signal) {\n    const body = { jsonrpc: \"2.0\", method };\n    if (params !== undefined) body.params = params;\n    if (!isNotification) body.id = ++requestId;\n    const headers = {\n      \"content-type\": \"application/json\",\n      accept: \"application/json, text/event-stream\",\n    };\n    if (protocolVersion) headers[\"mcp-protocol-version\"] = protocolVersion;\n    const res = await fetch(config.endpoint, {\n      method: \"POST\",\n      credentials: config.credentials,\n      headers,\n      body: JSON.stringify(body),\n      signal,\n    });\n    if (isNotification) return null;\n    if (!res.ok) {\n      throw new Error(\"MCP request failed: HTTP \" + res.status);\n    }\n    const contentType = res.headers.get(\"content-type\") || \"\";\n    if (contentType.includes(\"text/event-stream\")) {\n      return parseSse(await res.text(), body.id);\n    }\n    return unwrap(await res.json(), body.id);\n  }\n\n  function parseSse(text, id) {\n    for (const event of text.split(/\\\\r?\\\\n\\\\r?\\\\n/)) {\n      const data = event\n        .split(/\\\\r?\\\\n/)\n        .filter((line) => line.startsWith(\"data:\"))\n        .map((line) => line.slice(5).replace(/^ /, \"\"))\n        .join(\"\\\\n\");\n      if (!data) continue;\n      let message;\n      try {\n        message = JSON.parse(data);\n      } catch {\n        continue;\n      }\n      if (\n        message &&\n        message.id === id &&\n        (\"result\" in message || \"error\" in message)\n      ) {\n        return unwrap(message, id);\n      }\n    }\n    throw new Error(\"No MCP response found in event stream\");\n  }\n\n  function unwrap(message, id) {\n    if (message && message.error) {\n      throw new Error(\n        message.error.message || \"MCP error \" + message.error.code,\n      );\n    }\n    if (!message || message.id !== id) {\n      throw new Error(\"Unexpected MCP response\");\n    }\n    return message.result;\n  }\n\n  (async () => {\n    const init = await rpc(\"initialize\", {\n      protocolVersion: \"2025-06-18\",\n      capabilities: {},\n      clientInfo: { name: \"mcp-handler/webmcp\", version: \"1.0.0\" },\n    });\n    protocolVersion = (init && init.protocolVersion) || \"2025-06-18\";\n    await rpc(\"notifications/initialized\", undefined, true).catch(() => null);\n\n    let cursor;\n    do {\n      const listed = await rpc(\"tools/list\", cursor ? { cursor } : {});\n      for (const tool of (listed && listed.tools) || []) {\n        if (!config.tools.includes(tool.name)) continue;\n        try {\n          await provider.registerTool({\n            name: tool.name,\n            title: tool.title || tool.annotations?.title || tool.name,\n            description: tool.description || tool.title || tool.annotations?.title || tool.name,\n            inputSchema: tool.inputSchema,\n            annotations: { readOnlyHint: tool.annotations?.readOnlyHint === true },\n            execute: (args, options) =>\n              rpc(\"tools/call\", { name: tool.name, arguments: args || {} }, false, options?.signal),\n          });\n        } catch (error) {\n          console.warn(\"[mcp-handler/webmcp] failed to register tool \" + tool.name + \":\", error);\n        }\n      }\n      cursor = listed && listed.nextCursor;\n    } while (cursor);\n  })().catch((error) => {\n    console.warn(\"[mcp-handler/webmcp] failed to register tools:\", error);\n  });\n})();\n`;\n}\n","import {\n  initializeMcpApiHandler,\n  type McpHandlerOptions,\n  type WebMcpOptions,\n} from \"./mcp-api-handler\";\nimport type { McpServer } from \"@modelcontextprotocol/server\";\n\nexport type { McpHandlerOptions, WebMcpOptions };\n\n/**\n * Creates a MCP handler that can be used to handle MCP requests.\n *\n * The returned handler is a web-standard `(request: Request) => Promise<Response>`\n * function. It serves every request it receives — routing belongs to the host\n * framework, so mount it at the route you want (a Next.js route handler,\n * Hono, Nitro, ...).\n *\n * @param initializeServer - A function that initializes the MCP server. Use this to access the server instance and register tools, prompts, and resources.\n * @param options - The SDK's server options plus handler extras (`serverInfo`, `verboseLogs`, `onEvent`, `maxSubscriptions`, `experimental_webMcp`).\n * @returns A function that can be used to handle MCP requests.\n */\nexport default function createMcpRouteHandler(\n  initializeServer:\n    | ((server: McpServer) => Promise<void>)\n    | ((server: McpServer) => void),\n  options?: McpHandlerOptions,\n): (request: Request) => Promise<Response> {\n  return initializeMcpApiHandler(initializeServer, options);\n}\n","import {\n  ProtocolError,\n  type McpServer,\n  type ServerCapabilities,\n  type ServerContext,\n} from \"@modelcontextprotocol/server\";\nimport {\n  listParams,\n  subscribeParams,\n  subscriptionState,\n  unsubscribeParams,\n  webhookFailures,\n} from \"./schemas\";\nimport { canonical } from \"./json\";\nimport type {\n  ExperimentalMcpEventContext,\n  ExperimentalMcpEventDefinition,\n  ExperimentalMcpEventsOptions,\n  ExperimentalMcpSubscriptionKey,\n} from \"./types\";\n\nconst registered = new WeakSet<McpServer>();\n\n/**\n * Register the draft MCP Events webhook control methods on the existing MCP\n * endpoint. Storage and delivery must live outside the per-request server.\n *\n * @experimental Follows the experimental MCP Events design sketch, not a stable\n * MCP specification. Poll/stream delivery and model-tool generation are excluded.\n */\nexport function experimental_registerMcpEvents(\n  server: McpServer,\n  options: ExperimentalMcpEventsOptions,\n): void {\n  if (registered.has(server)) throw new Error(\"MCP Events already registered\");\n  const minMs = options.ttl?.minMs ?? 60_000;\n  const defaultMs = options.ttl?.defaultMs ?? 3_600_000;\n  const maxMs = options.ttl?.maxMs ?? 86_400_000;\n  if (\n    ![minMs, defaultMs, maxMs].every(\n      (value) => Number.isSafeInteger(value) && value > 0,\n    ) ||\n    minMs > defaultMs ||\n    defaultMs > maxMs ||\n    maxMs > 8.64e15 - Date.now()\n  )\n    throw new Error(\n      \"MCP Events TTLs must satisfy 0 < minMs <= defaultMs <= maxMs\",\n    );\n  registered.add(server);\n\n  // The SDK preserves extension capabilities but does not yet type events.\n  server.server.registerCapabilities({ events: {} } as ServerCapabilities);\n\n  async function context(\n    ctx: ServerContext,\n  ): Promise<ExperimentalMcpEventContext> {\n    const authInfo = ctx.http?.authInfo;\n    if (\n      !authInfo ||\n      (authInfo.expiresAt !== undefined &&\n        authInfo.expiresAt <= Date.now() / 1000)\n    ) {\n      throw new ProtocolError(-32012, \"Authentication required\");\n    }\n    const principal = await options.getPrincipal(authInfo);\n    if (typeof principal !== \"string\" || !principal.trim()) {\n      throw new ProtocolError(-32012, \"Authenticated principal required\");\n    }\n    return { principal, authInfo, signal: ctx.mcpReq.signal };\n  }\n\n  async function catalog(ctx: ExperimentalMcpEventContext) {\n    const events =\n      typeof options.events === \"function\"\n        ? await options.events(ctx)\n        : options.events;\n    const names = new Set<string>();\n    for (const event of events) {\n      if (!event.name || names.has(event.name))\n        throw new Error(\"Invalid event catalog\");\n      names.add(event.name);\n    }\n    const visible: ExperimentalMcpEventDefinition[] = [];\n    for (const event of events) {\n      ctx.signal.throwIfAborted();\n      // Filter-specific authorize() cannot run until arguments are supplied.\n      if (\n        event.authorizeDiscovery === undefined ||\n        (await event.authorizeDiscovery(ctx)) === true\n      ) {\n        visible.push(event);\n      }\n    }\n    ctx.signal.throwIfAborted();\n    return visible;\n  }\n\n  server.server.setRequestHandler(\n    \"events/list\",\n    { params: listParams },\n    async (params, ctx) =>\n      safe(async () => {\n        const auth = await context(ctx);\n        // This adapter returns the complete account-scoped catalog in one page.\n        if (params.cursor !== undefined)\n          throw new ProtocolError(-32602, \"Invalid catalog cursor\");\n        const events = await catalog(auth);\n        return {\n          events: events.map((event) => ({\n            name: event.name,\n            ...(event.description !== undefined\n              ? { description: event.description }\n              : {}),\n            delivery: [\"webhook\"],\n            inputSchema: event.inputSchema[\"~standard\"].jsonSchema.input({\n              target: \"draft-2020-12\",\n            }),\n            payloadSchema: event.payloadSchema[\"~standard\"].jsonSchema.output({\n              target: \"draft-2020-12\",\n            }),\n          })),\n        };\n      }),\n  );\n\n  server.server.setRequestHandler(\n    \"events/subscribe\",\n    { params: subscribeParams },\n    async (params, ctx) =>\n      safe(async () => {\n        const auth = await context(ctx);\n        if (params.delivery.mode !== \"webhook\") {\n          throw new ProtocolError(-32014, \"Unsupported delivery mode\", {\n            feature: \"deliveryMode\",\n          });\n        }\n        validateUrl(params.delivery.url);\n        validateSecret(params.delivery.secret);\n        const event = (await catalog(auth)).find(\n          (candidate) => candidate.name === params.name,\n        );\n        if (!event)\n          throw new ProtocolError(-32011, \"Event not found\", { kind: \"event\" });\n        const checked = await event.inputSchema[\"~standard\"].validate(\n          params.arguments,\n        );\n        if (\n          checked.issues ||\n          canonical(checked.value) !== canonical(params.arguments)\n        ) {\n          throw new ProtocolError(\n            -32602,\n            \"Arguments must match the event schema without transformation\",\n          );\n        }\n        if (\n          (await event.authorize(params.arguments, {\n            principal: auth.principal,\n            signal: auth.signal,\n          })) !== true\n        ) {\n          throw new ProtocolError(-32012, \"Event arguments are not authorized\");\n        }\n        const key = await subscriptionKey(\n          auth.principal,\n          params.name,\n          params.arguments,\n          params.delivery.url,\n        );\n        auth.signal.throwIfAborted();\n        const operationId = await options.subscriptions.prepare(key, auth);\n        if (typeof operationId !== \"string\" || !operationId.trim()) {\n          throw new Error(\"Invalid subscription operation\");\n        }\n        auth.signal.throwIfAborted();\n        const verification = await options.delivery.verifyEndpoint(\n          { ...key, secret: params.delivery.secret },\n          auth,\n        );\n        if (verification.verified !== true) {\n          const reason = webhookFailures.includes(verification.reason)\n            ? verification.reason\n            : \"challenge_failed\";\n          throw new ProtocolError(-32015, \"Callback verification failed\", {\n            reason,\n          });\n        }\n        auth.signal.throwIfAborted();\n        const ttl =\n          params.ttlMs === null && options.ttl?.allowNoExpiry\n            ? null\n            : Math.max(minMs, Math.min(params.ttlMs ?? defaultMs, maxMs));\n        const refreshBefore =\n          ttl === null ? null : new Date(Date.now() + ttl).toISOString();\n        const state = await options.subscriptions.upsert(\n          {\n            ...key,\n            secret: params.delivery.secret,\n            refreshBefore,\n            cursor: params.cursor ?? null,\n            ...(params.maxAgeMs !== undefined\n              ? { maxAgeMs: params.maxAgeMs }\n              : {}),\n          },\n          auth,\n          operationId,\n        );\n        const result = await subscriptionState[\"~standard\"].validate(state);\n        if (result.issues) throw new Error(\"Invalid subscription state\");\n        return { id: key.id, refreshBefore, ...result.value };\n      }),\n  );\n\n  server.server.setRequestHandler(\n    \"events/unsubscribe\",\n    { params: unsubscribeParams },\n    async (params, ctx) =>\n      safe(async () => {\n        const auth = await context(ctx);\n        validateUrl(params.delivery.url);\n        const key = await subscriptionKey(\n          auth.principal,\n          params.name,\n          params.arguments,\n          params.delivery.url,\n        );\n        // Cleanup must remain possible after an event is removed or its schema changes.\n        auth.signal.throwIfAborted();\n        if (!(await options.subscriptions.remove(key, auth))) {\n          throw new ProtocolError(-32011, \"Subscription not found\", {\n            kind: \"subscription\",\n          });\n        }\n        return {};\n      }),\n  );\n}\n\nfunction validateUrl(value: string): void {\n  try {\n    const url = new URL(value);\n    if (\n      !value.startsWith(\"https://\") ||\n      url.protocol !== \"https:\" ||\n      url.username ||\n      url.password ||\n      url.hash\n    )\n      throw new Error();\n  } catch {\n    throw new ProtocolError(\n      -32602,\n      \"Callback must be an HTTPS URL without credentials or a fragment\",\n    );\n  }\n}\n\nfunction validateSecret(value: string): void {\n  try {\n    if (!/^whsec_[A-Za-z0-9+/]+={0,2}$/.test(value)) throw new Error();\n    const encoded = value.slice(6);\n    const decoded = atob(encoded);\n    if (\n      decoded.length < 24 ||\n      decoded.length > 64 ||\n      btoa(decoded).replace(/=+$/, \"\") !== encoded.replace(/=+$/, \"\")\n    )\n      throw new Error();\n  } catch {\n    throw new ProtocolError(-32602, \"Invalid Standard Webhooks secret\");\n  }\n}\n\nasync function subscriptionKey(\n  principal: string,\n  name: string,\n  args: Record<string, unknown>,\n  url: string,\n): Promise<ExperimentalMcpSubscriptionKey> {\n  const bytes = new TextEncoder().encode(\n    canonical([principal, url, name, args]),\n  );\n  const hash = await crypto.subtle.digest(\"SHA-256\", bytes);\n  const id =\n    \"sub_\" +\n    Array.from(new Uint8Array(hash), (byte) =>\n      byte.toString(16).padStart(2, \"0\"),\n    ).join(\"\");\n  return { id, principal, name, arguments: args, url };\n}\n\nasync function safe<T>(run: () => Promise<T>): Promise<T> {\n  try {\n    return await run();\n  } catch (error) {\n    // Adapter exceptions can contain webhook secrets or endpoint response data.\n    if (\n      error instanceof ProtocolError &&\n      [-32602, -32011, -32012, -32013, -32014, -32015].includes(error.code)\n    ) {\n      const messages: Record<number, string> = {\n        [-32602]: \"Invalid event parameters\",\n        [-32011]: \"Event or subscription not found\",\n        [-32012]: \"Forbidden\",\n        [-32013]: \"Resource exhausted\",\n        [-32014]: \"Unsupported event option\",\n        [-32015]: \"Callback verification failed\",\n      };\n      // Only fixed categories cross the wire, including for intentional adapter errors.\n      const data = error.data as\n        | { reason?: unknown; kind?: unknown; feature?: unknown }\n        | undefined;\n      const detail =\n        error.code === -32015 &&\n        webhookFailures.some((reason) => reason === data?.reason)\n          ? { reason: data!.reason }\n          : error.code === -32011 &&\n            (data?.kind === \"event\" || data?.kind === \"subscription\")\n          ? { kind: data.kind }\n          : error.code === -32014 && data?.feature === \"deliveryMode\"\n          ? { feature: \"deliveryMode\" }\n          : undefined;\n      throw new ProtocolError(error.code, messages[error.code], detail);\n    }\n    throw new ProtocolError(-32603, \"MCP Events operation failed\");\n  }\n}\n","import {\n  fromJsonSchema,\n  type StandardSchemaWithJSON,\n} from \"@modelcontextprotocol/server\";\nimport type { ExperimentalMcpSubscriptionState } from \"./types\";\n\nconst object = { type: \"object\", additionalProperties: true } as const;\nconst name = { type: \"string\", minLength: 1 } as const;\nconst integer = {\n  type: \"integer\",\n  minimum: 1,\n  maximum: Number.MAX_SAFE_INTEGER,\n} as const;\n\nexport const listParams: StandardSchemaWithJSON<{ cursor?: string }> =\n  fromJsonSchema({\n    type: \"object\",\n    properties: { cursor: { type: \"string\" } },\n  });\n\nexport interface SubscriptionParams {\n  name: string;\n  arguments: Record<string, unknown>;\n  delivery: { mode: string; url: string; secret: string };\n  cursor?: string | null;\n  maxAgeMs?: number;\n  ttlMs?: number | null;\n}\n\nexport const subscribeParams: StandardSchemaWithJSON<SubscriptionParams> =\n  fromJsonSchema({\n    type: \"object\",\n    required: [\"name\", \"arguments\", \"delivery\"],\n    properties: {\n      name,\n      arguments: object,\n      delivery: {\n        type: \"object\",\n        required: [\"mode\", \"url\", \"secret\"],\n        properties: { mode: name, url: name, secret: name },\n      },\n      cursor: { type: [\"string\", \"null\"] },\n      maxAgeMs: integer,\n      ttlMs: { ...integer, type: [\"integer\", \"null\"] },\n    },\n  });\n\nexport const unsubscribeParams: StandardSchemaWithJSON<\n  Pick<SubscriptionParams, \"name\" | \"arguments\"> & { delivery: { url: string } }\n> = fromJsonSchema({\n  type: \"object\",\n  required: [\"name\", \"arguments\", \"delivery\"],\n  properties: {\n    name,\n    arguments: object,\n    delivery: {\n      type: \"object\",\n      required: [\"url\"],\n      properties: { url: name },\n    },\n  },\n});\n\nexport const webhookFailures = [\n  \"connection_refused\",\n  \"timeout\",\n  \"tls_error\",\n  \"http_4xx\",\n  \"http_5xx\",\n  \"challenge_failed\",\n] as const;\n\nexport const subscriptionState: StandardSchemaWithJSON<ExperimentalMcpSubscriptionState> =\n  fromJsonSchema({\n    type: \"object\",\n    required: [\"cursor\", \"truncated\"],\n    additionalProperties: false,\n    properties: {\n      cursor: { type: [\"string\", \"null\"] },\n      truncated: { type: \"boolean\" },\n      deliveryStatus: {\n        type: \"object\",\n        required: [\"active\", \"lastError\"],\n        additionalProperties: false,\n        properties: {\n          active: { type: \"boolean\" },\n          lastDeliveryAt: { type: \"string\", format: \"date-time\" },\n          lastError: { enum: [...webhookFailures, null] },\n          failedSince: { type: \"string\", format: \"date-time\" },\n          throttled: { type: \"boolean\" },\n          retryAfterMs: { type: \"integer\", minimum: 0 },\n        },\n      },\n    },\n  });\n","/** Canonicalize plain JSON only; never silently discard or coerce values. */\nexport function canonical(\n  value: unknown,\n  ancestors = new Set<object>(),\n): string {\n  if (value === null) return \"null\";\n  if (typeof value === \"string\" || typeof value === \"boolean\")\n    return JSON.stringify(value);\n  if (typeof value === \"number\" && Number.isFinite(value))\n    return JSON.stringify(value);\n  if (\n    typeof value !== \"object\" ||\n    ancestors.has(value) ||\n    (!Array.isArray(value) &&\n      Object.getPrototypeOf(value) !== Object.prototype &&\n      Object.getPrototypeOf(value) !== null)\n  )\n    throw new Error(\"Invalid JSON value\");\n\n  ancestors.add(value);\n  try {\n    if (Array.isArray(value))\n      return `[${Array.from(value, (item) => canonical(item, ancestors)).join(\n        \",\",\n      )}]`;\n    return `{${Object.keys(value)\n      .sort()\n      .map(\n        (key) =>\n          `${JSON.stringify(key)}:${canonical(\n            (value as Record<string, unknown>)[key],\n            ancestors,\n          )}`,\n      )\n      .join(\",\")}}`;\n  } finally {\n    ancestors.delete(value);\n  }\n}\n","import type { StandardSchemaWithJSON } from \"@modelcontextprotocol/server\";\nimport { canonical } from \"./json\";\nimport type {\n  ExperimentalMcpEventDeliveryErrorCode,\n  ExperimentalMcpEventDeliveryValidationOptions,\n} from \"./types\";\n\nconst messages: Record<ExperimentalMcpEventDeliveryErrorCode, string> = {\n  invalid_subscription: \"A valid stored subscription is required\",\n  event_mismatch: \"Event definition does not match the subscription\",\n  expired: \"Subscription has expired\",\n  invalid_arguments: \"Stored arguments must match the event schema unchanged\",\n  invalid_payload: \"Payload must be JSON matching the event schema unchanged\",\n  forbidden: \"Subscription principal is no longer authorized\",\n};\n\n/** @experimental A validation failure; contains no payload or credentials. */\nexport class ExperimentalMcpEventDeliveryError extends Error {\n  constructor(public readonly code: ExperimentalMcpEventDeliveryErrorCode) {\n    super(messages[code]);\n    this.name = \"ExperimentalMcpEventDeliveryError\";\n  }\n}\n\n/**\n * Validate a candidate event against a current stored subscription. Resolves\n * without modifying/transforming the payload, or throws to prevent delivery.\n *\n * @experimental Does not load state, match source events to filters, sign/send,\n * or coordinate cancellation. The worker must gate dispatch on active state.\n * Authorization/schema backend exceptions and abort reasons propagate unchanged.\n */\nexport async function experimental_validateMcpEventDelivery({\n  event,\n  subscription,\n  payload,\n  signal = new AbortController().signal,\n}: ExperimentalMcpEventDeliveryValidationOptions): Promise<void> {\n  signal.throwIfAborted();\n  if (\n    !subscription ||\n    typeof subscription.principal !== \"string\" ||\n    !subscription.principal.trim() ||\n    typeof subscription.name !== \"string\" ||\n    !subscription.name ||\n    !subscription.arguments ||\n    typeof subscription.arguments !== \"object\" ||\n    Array.isArray(subscription.arguments)\n  )\n    throw new ExperimentalMcpEventDeliveryError(\"invalid_subscription\");\n  if (event.name !== subscription.name)\n    throw new ExperimentalMcpEventDeliveryError(\"event_mismatch\");\n\n  const expiry =\n    subscription.refreshBefore === null\n      ? null\n      : typeof subscription.refreshBefore === \"string\"\n      ? Date.parse(subscription.refreshBefore)\n      : NaN;\n  if (expiry !== null && !Number.isFinite(expiry))\n    throw new ExperimentalMcpEventDeliveryError(\"invalid_subscription\");\n\n  function checkLifetime() {\n    signal.throwIfAborted();\n    if (expiry !== null && expiry <= Date.now())\n      throw new ExperimentalMcpEventDeliveryError(\"expired\");\n  }\n  checkLifetime();\n  await validateUnchanged(\n    event.inputSchema,\n    subscription.arguments,\n    \"invalid_arguments\",\n  );\n  checkLifetime();\n  await validateUnchanged(event.payloadSchema, payload, \"invalid_payload\");\n  checkLifetime();\n  const authorized = await event.authorize(subscription.arguments, {\n    principal: subscription.principal,\n    signal,\n  });\n  // Async schema/policy checks can outlive the grant or worker cancellation.\n  checkLifetime();\n  if (authorized !== true)\n    throw new ExperimentalMcpEventDeliveryError(\"forbidden\");\n}\n\nasync function validateUnchanged(\n  schema: StandardSchemaWithJSON,\n  value: unknown,\n  code: \"invalid_arguments\" | \"invalid_payload\",\n): Promise<void> {\n  function json(input: unknown) {\n    try {\n      return canonical(input);\n    } catch {\n      throw new ExperimentalMcpEventDeliveryError(code);\n    }\n  }\n  const before = json(value);\n  const result = await schema[\"~standard\"].validate(value);\n  if (result.issues || json(result.value) !== before || json(value) !== before)\n    throw new ExperimentalMcpEventDeliveryError(code);\n}\n","import type { AuthInfo } from \"@modelcontextprotocol/server\";\nimport {\n  OAuthError,\n  OAuthErrorCode,\n  bearerAuthChallengeResponse,\n} from \"@modelcontextprotocol/server\";\nimport { getPublicOrigin } from \"../lib/url\";\n\ndeclare global {\n  interface Request {\n    auth?: AuthInfo;\n  }\n}\n\nexport function withMcpAuth(\n  handler: (req: Request) => Response | Promise<Response>,\n  verifyToken: (\n    req: Request,\n    bearerToken?: string,\n  ) => AuthInfo | undefined | Promise<AuthInfo | undefined>,\n  {\n    required = false,\n    resourceMetadataPath = \"/.well-known/oauth-protected-resource\",\n    requiredScopes,\n    resourceUrl,\n  }: {\n    required?: boolean;\n    resourceMetadataPath?: string;\n    requiredScopes?: string[];\n    /**\n     * Explicit resource URL override. When provided, this URL is used as the\n     * origin for constructing the resource_metadata URL. Use this when running\n     * behind a proxy that doesn't set standard forwarding headers, or when you\n     * need to specify a specific public URL.\n     *\n     * If not provided, the origin is automatically detected from proxy headers\n     * (X-Forwarded-Host, X-Forwarded-Proto, Forwarded) or falls back to req.url.\n     */\n    resourceUrl?: string;\n  } = {},\n) {\n  return async (req: Request) => {\n    const origin = resourceUrl ?? getPublicOrigin(req);\n    const resourceMetadataUrl = `${origin}${resourceMetadataPath}`;\n    const challengeOptions = { requiredScopes, resourceMetadataUrl };\n\n    const authHeader = req.headers.get(\"Authorization\");\n    const [type, token] = authHeader?.split(\" \") || [];\n\n    // Only support bearer token as per the MCP spec\n    // https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization#2-6-1-token-requirements\n    const bearerToken = type?.toLowerCase() === \"bearer\" ? token : undefined;\n\n    let authInfo: AuthInfo | undefined;\n    try {\n      authInfo = await verifyToken(req, bearerToken);\n    } catch (error) {\n      console.error(\"Unexpected error authenticating bearer token:\", error);\n      return bearerAuthChallengeResponse(\n        new OAuthError(OAuthErrorCode.InvalidToken, \"Invalid token\"),\n        challengeOptions,\n      );\n    }\n\n    try {\n      if (required && !authInfo) {\n        throw new OAuthError(\n          OAuthErrorCode.InvalidToken,\n          \"No authorization provided\",\n        );\n      }\n\n      if (!authInfo) {\n        return handler(req);\n      }\n\n      // Check if token has the required scopes (if any)\n      if (requiredScopes?.length) {\n        const hasAllScopes = requiredScopes.every((scope) =>\n          authInfo!.scopes.includes(scope),\n        );\n\n        if (!hasAllScopes) {\n          throw new OAuthError(\n            OAuthErrorCode.InsufficientScope,\n            \"Insufficient scope\",\n          );\n        }\n      }\n\n      // Check if the token is expired\n      if (authInfo.expiresAt && authInfo.expiresAt < Date.now() / 1000) {\n        throw new OAuthError(OAuthErrorCode.InvalidToken, \"Token has expired\");\n      }\n\n      // Set auth info on the request object after successful verification\n      req.auth = authInfo;\n\n      return handler(req);\n    } catch (error) {\n      if (!OAuthError.isInstance(error)) {\n        console.error(\"Unexpected error authenticating bearer token:\", error);\n      }\n      // Maps invalid_token → 401, insufficient_scope → 403 (both with a\n      // WWW-Authenticate challenge advertising resource_metadata), anything\n      // unexpected → 500 server_error.\n      return bearerAuthChallengeResponse(error, challengeOptions);\n    }\n  };\n}\n","/**\n * Get the public-facing origin from a request, respecting proxy headers.\n *\n * When running behind a reverse proxy (e.g., nginx, Vercel, Cloudflare),\n * the `req.url` typically reflects the internal URL (e.g., http://localhost:3000).\n * This function reconstructs the public-facing origin using standard proxy headers.\n *\n * Header precedence:\n * 1. X-Forwarded-Host + X-Forwarded-Proto (most common)\n * 2. Forwarded header (RFC 7239)\n * 3. Falls back to req.url origin\n *\n * @param req - The incoming request\n * @returns The public-facing origin (e.g., \"https://example.org\")\n */\nexport function getPublicOrigin(req: Request): string {\n  const forwardedHost = req.headers.get(\"x-forwarded-host\");\n  const forwardedProto = req.headers.get(\"x-forwarded-proto\");\n\n  // If we have X-Forwarded-Host, construct origin from forwarded headers\n  if (forwardedHost) {\n    // X-Forwarded-Host can contain multiple comma-separated values; use the first (leftmost)\n    const host = forwardedHost.split(\",\")[0].trim();\n    // X-Forwarded-Proto can also be comma-separated\n    const proto = forwardedProto?.split(\",\")[0].trim() || \"https\";\n    return `${proto}://${host}`;\n  }\n\n  // Check RFC 7239 Forwarded header (less common but standardized)\n  const forwarded = req.headers.get(\"forwarded\");\n  if (forwarded) {\n    const parsed = parseForwardedHeader(forwarded);\n    if (parsed.host) {\n      const proto = parsed.proto || \"https\";\n      return `${proto}://${parsed.host}`;\n    }\n  }\n\n  // Fallback to req.url origin\n  return new URL(req.url).origin;\n}\n\n/**\n * Get the public-facing URL from a request, respecting proxy headers.\n *\n * @param req - The incoming request\n * @returns The public-facing URL with the correct origin\n */\nexport function getPublicUrl(req: Request): URL {\n  const url = new URL(req.url);\n  const publicOrigin = getPublicOrigin(req);\n\n  // Construct a new URL with the public origin but preserve pathname, search, and hash\n  const result = new URL(url.pathname + url.search + url.hash, publicOrigin);\n  return result;\n}\n\n/**\n * Parse the RFC 7239 Forwarded header.\n * Example: \"for=192.0.2.60;proto=https;host=example.com\"\n */\nfunction parseForwardedHeader(\n  forwarded: string\n): { host?: string; proto?: string } {\n  const result: { host?: string; proto?: string } = {};\n\n  // The header can contain multiple comma-separated forwarded elements; use the first\n  const firstElement = forwarded.split(\",\")[0];\n\n  // Parse key=value pairs separated by semicolons\n  const pairs = firstElement.split(\";\");\n  for (const pair of pairs) {\n    const [key, value] = pair.split(\"=\").map((s) => s.trim().toLowerCase());\n    if (key === \"host\" && value) {\n      // Remove surrounding quotes if present\n      result.host = value.replace(/^\"|\"$/g, \"\");\n    } else if (key === \"proto\" && value) {\n      result.proto = value.replace(/^\"|\"$/g, \"\");\n    }\n  }\n\n  return result;\n}\n","import type { OAuthProtectedResourceMetadata } from \"@modelcontextprotocol/server\";\nimport { getPublicUrl } from \"../lib/url\";\n\n/**\n * CORS headers for OAuth Protected Resource Metadata endpoint.\n * Configured to allow any origin to make the endpoint accessible to web-based MCP clients.\n */\nconst corsHeaders = {\n    \"Access-Control-Allow-Origin\": \"*\",\n    \"Access-Control-Allow-Methods\": \"GET, OPTIONS\",\n    \"Access-Control-Allow-Headers\": \"*\",\n    \"Access-Control-Max-Age\": \"86400\",\n};\n\n/**\n * OAuth 2.0 Protected Resource Metadata endpoint based on RFC 9728.\n * @see https://datatracker.ietf.org/doc/html/rfc9728\n *\n * @param authServerUrls - Array of issuer URLs of the OAuth 2.0 Authorization Servers.\n *                        These should match the \"issuer\" field in the authorization servers'\n *                        OAuth metadata (RFC 8414).\n * @param resourceUrl - Optional explicit resource URL override. When provided, this URL is\n *                      used instead of deriving it from the request. Use this when running\n *                      behind a proxy that doesn't set standard forwarding headers.\n *                      If not provided, the URL is automatically detected from proxy headers\n *                      (X-Forwarded-Host, X-Forwarded-Proto, Forwarded) or falls back to req.url.\n */\nexport function protectedResourceHandler({\n    authServerUrls,\n    resourceUrl: explicitResourceUrl,\n}: {\n    authServerUrls: string[];\n    resourceUrl?: string;\n}) {\n    return (req: Request) => {\n        let resource: string;\n\n        if (explicitResourceUrl) {\n            // Use explicit override if provided\n            resource = explicitResourceUrl;\n        } else {\n            // Auto-detect from proxy headers or req.url\n            const publicUrl = getPublicUrl(req);\n\n            publicUrl.pathname = publicUrl.pathname\n              .replace(/^\\/\\.well-known\\/[^\\/]+/, \"\");\n\n            // The URL class does not allow for empty `pathname` and will replace it\n            // with \"/\". Here, we correct that.\n            resource = publicUrl.pathname === '/'\n              ? publicUrl.toString().replace(/\\/$/, '')\n              : publicUrl.toString();\n        }\n\n        const metadata = generateProtectedResourceMetadata({\n            authServerUrls,\n            resourceUrl: resource,\n        });\n\n        return new Response(JSON.stringify(metadata), {\n            headers: {\n                ...corsHeaders,\n                \"Cache-Control\": \"max-age=3600\",\n                \"Content-Type\": \"application/json\",\n            },\n        });\n    };\n}\n\n/**\n * Generates protected resource metadata for the given auth server URLs and\n * protected resource identifier. The protected resource identifier, as defined\n * in RFC 9728, should be a a URL that uses the https scheme and has no fragment\n * component.\n *\n * @param authServerUrls - Array of issuer URLs of the authorization servers. Each URL should \n *                        match the \"issuer\" field in the respective authorization server's \n *                        OAuth metadata (RFC 8414).\n * @param resourceUrl - the protected resource identifier\n * @param additionalMetadata - Additional metadata fields to include in the response\n * @returns Protected resource metadata, serializable to JSON\n */\nexport function generateProtectedResourceMetadata({\n    authServerUrls,\n    resourceUrl,\n    additionalMetadata,\n}: {\n    authServerUrls: string[];\n    resourceUrl: string;\n    additionalMetadata?: Partial<OAuthProtectedResourceMetadata>;\n}): OAuthProtectedResourceMetadata {\n    return Object.assign(\n        {\n            resource: resourceUrl,\n            authorization_servers: authServerUrls\n        },\n        additionalMetadata\n    );\n}\n\n/**\n * CORS options request handler for OAuth metadata endpoints.\n * Necessary for MCP clients that operate in web browsers.\n */\nexport function metadataCorsOptionsRequestHandler() {\n    return () => {\n        return new Response(null, {\n            status: 200,\n            headers: corsHeaders,\n        });\n    };\n}\n\n"]}