import { type Scope } from '../scope/scope.instance'; import { type WebStandardMcpPair } from './web-standard-mcp'; /** * The host execution context — its `waitUntil` keeps the worker alive past the * `fetch` return so a streaming (SSE) response body can finish. Optional: in * Node there's no isolate teardown, so it's only needed on V8 isolates. */ export interface FetchHandlerCtx { waitUntil?(promise: Promise): void; } /** A Web-standard fetch handler: `(request, ctx?, env?) => Promise`. */ export type WebFetchHandler = (request: Request, ctx?: FetchHandlerCtx, env?: unknown) => Promise; /** * Routes an MCP request to a stateful session host (a Cloudflare Durable Object) * instead of handling it statelessly. Receives the per-request `env` (for the DO * binding). Returns a `Response` when it routed the request, or `undefined` to * fall through to stateless handling (e.g. the binding isn't present). */ export type WebFetchSessionRouter = (request: Request, env: unknown, ctx?: FetchHandlerCtx) => Promise; /** * CORS for the web-fetch adapter — the transport-level analog of the Express * host's `cors` middleware (CORS is an adapter concern, not a flow stage), so a * browser MCP client (e.g. the MCP Inspector in "Direct" mode) can connect. */ export interface WebFetchCorsOptions { /** Allowed origin: `true` reflects the request `Origin`, `'*'` allows any, or a specific origin / list. */ origin?: boolean | string | string[]; /** Allowed methods. Default `GET, POST, OPTIONS, DELETE`. */ methods?: string[]; /** Allowed request headers. Default: reflect `Access-Control-Request-Headers`, else a sensible MCP set. */ headers?: string[]; /** Response headers exposed to the browser. Default `Mcp-Session-Id, WWW-Authenticate`. */ exposeHeaders?: string[]; /** Send `Access-Control-Allow-Credentials: true`. Default `false`. */ credentials?: boolean; /** `Access-Control-Max-Age` (seconds) on the preflight response. */ maxAge?: number; } export interface CreateWebFetchHandlerOptions { /** * Path the MCP endpoint (both Streamable HTTP `POST` and the SSE `GET` * stream) is served at. **Config-driven**: when omitted, it falls back to the * scope's `http.entryPath` (the same gateway prefix the Express host mounts * under), and to the worker root `/` when that too is unset. So one config * decides the path — set `http.entryPath: '/mcp'` for `/mcp`, or leave * it for `mcp.` at root. The worker serves exactly that one path. * * An explicit value here overrides the config. A trailing slash is normalized * (`/mcp/` matches `/mcp`). An array opts into a custom multi-path allow-list. * Requests to any other path (besides {@link * CreateWebFetchHandlerOptions.healthPaths}) get a 404. */ entryPath?: string | string[]; /** * Paths answered with a liveness/readiness 200 instead of being routed to * the MCP transport. Defaults to `/healthz` and `/readyz`. */ healthPaths?: string[]; /** * CORS for browser MCP clients (Inspector "Direct" mode, web apps). A * transport-adapter concern, not a flow stage. **Config-driven**: when * omitted, it mirrors the scope's `http.cors` (the same config the Express * host uses), so `@FrontMcp({ http: { cors } })` covers both. An explicit * value here overrides that. */ cors?: WebFetchCorsOptions; /** * Optional stateful-session router (Cloudflare Durable Object host). When set, * MCP requests at the entry path are offered to it first; if it returns a * `Response` the request was routed to a session DO, otherwise handling falls * through to the stateless path. CORS / health / entry-path routing stay here * in the adapter regardless. */ sessionRouter?: WebFetchSessionRouter; } /** * Build a Web-standard fetch handler for a Scope. * * @example * ```ts * const handler = createWebFetchHandler(scope); * export default { fetch: (request) => handler(request) }; * ``` */ export declare function createWebFetchHandler(scope: Scope, options?: CreateWebFetchHandlerOptions): WebFetchHandler; /** * Run a Web `Request` through the `http:request` flow and render its normalized * output to a Web `Response`. Shared by {@link createWebFetchHandler} (stateless) * and the Durable Object session host (which passes its `persistent` transport * so the GET notification stream + server push work). Returns `undefined` when * the flow produced no response (`next`/`handled`) — the caller decides the * fallback (typically 404). */ export declare function runHttpRequestFlowWeb(scope: Scope, request: Request, opts?: { ctx?: FetchHandlerCtx; persistent?: WebStandardMcpPair; }): Promise; /** * Dispatch a non-entry-path request through the FrontMCP flow that claims it * (auth / well-known / oauth flows match by `middleware.path` + `canActivate`). * Mirrors the Express host's route dispatch for runtimes with no middleware * server (Cloudflare Worker / web-fetch). Returns the rendered Web `Response`, * or `undefined` when no flow matches (caller 404s). */ export declare function runMatchingHttpFlowWeb(scope: Scope, request: Request): Promise; //# sourceMappingURL=web-fetch-handler.d.ts.map