/** * Streamable HTTP server helper for `@revealui/mcp` (Stage 1 PR-1.1). * * Wraps `@modelcontextprotocol/sdk`'s `StreamableHTTPServerTransport` with * session routing: one `MCP Server` + transport pair per concurrent client, * identified by the `Mcp-Session-Id` header. Initialize requests without a * session header allocate a new server via `createServer()`; subsequent * requests route to the matching session. * * Returns a Node `(req, res) => Promise` handler suitable for use with * `http.createServer`, Express, Fastify, or any framework that exposes the * raw Node request/response pair. A Web-Standard (Request → Response) * variant can layer on top later — the session-routing logic is independent * of the concrete transport flavour. * * The SDK's `StreamableHTTPServerTransport` is a one-session-per-instance * primitive (see the `this.sessionId` field in its implementation). That's * why we maintain an external `Map` and * not rely on a single transport to multiplex. */ import type { IncomingMessage, ServerResponse } from 'node:http'; import type { Server } from '@modelcontextprotocol/sdk/server/index.js'; export type StreamableHttpHandlerOptions = { /** * Called once per new session — returns a fresh `Server` instance to * connect to the session's transport. Keep this function pure; do not * share Server instances across sessions. */ createServer: () => Server | Promise; /** Generate session IDs. Default: `crypto.randomUUID()`. */ sessionIdGenerator?: () => string; /** Called when a new session is initialized. */ onSessionInitialized?: (sessionId: string) => void | Promise; /** Called when a session is terminated (DELETE or transport close). */ onSessionClosed?: (sessionId: string) => void | Promise; /** * Allowed `Origin` headers for DNS rebinding protection. If set, requests * with other origins are rejected. Mirrors the SDK's option. */ allowedOrigins?: string[]; /** * Allowed `Host` headers for DNS rebinding protection. If set, requests * with other hosts are rejected. */ allowedHosts?: string[]; /** * If true, responses are raw JSON instead of SSE streams. Useful for * deployments that can't hold open long-lived connections (many * serverless request/response platforms). Default: false. */ enableJsonResponse?: boolean; }; export type StreamableHttpHandler = (req: IncomingMessage, res: ServerResponse) => Promise; /** * Build a Node HTTP request handler that routes MCP Streamable HTTP traffic * to per-session `Server` + `Transport` pairs, allocating new sessions on * InitializeRequest and reusing them on follow-up requests via the * `Mcp-Session-Id` header. * * ```ts * import { createServer as createHttpServer } from 'node:http'; * import { createNodeStreamableHttpHandler } from '@revealui/mcp/streamable-http'; * * const mcpHandler = createNodeStreamableHttpHandler({ * createServer: () => makeMyMcpServer(), * }); * * createHttpServer(mcpHandler).listen(3000); * ``` */ export declare function createNodeStreamableHttpHandler(options: StreamableHttpHandlerOptions): StreamableHttpHandler; //# sourceMappingURL=streamable-http.d.ts.map