/** * MCP Session Manager -- Mcp-Session-Id lifecycle, eviction, isolation * * Each HTTP session gets its own McpServer + StreamableHTTPServerTransport * pair. This is the primary defense against CVE-2026-25536 (cross-client * response data leak when a single transport is reused across connections). * * INVARIANT: NEVER reuse a single transport instance across multiple * client sessions. Each session is fully isolated. */ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; export interface SessionEntry { readonly sessionId: string; readonly server: McpServer; readonly transport: StreamableHTTPServerTransport; readonly createdAt: number; readonly clientIp: string; lastSeen: number; } export interface SessionManagerOptions { /** Max idle time before eviction (ms). Default: 30 min */ ttlMs?: number; /** Max concurrent sessions. Default: 100 */ maxSessions?: number; /** Max sessions per client IP. Default: 10 */ maxSessionsPerIp?: number; /** Eviction sweep interval (ms). Default: 60s */ sweepIntervalMs?: number; } type ServerFactory = () => McpServer; export declare class SessionManager { private readonly options; private readonly sessions; private readonly ipSessionCount; private readonly ttlMs; private readonly maxSessions; private readonly maxSessionsPerIp; private sweepTimer; constructor(options?: SessionManagerOptions); /** Start periodic eviction sweep */ startSweep(): void; /** Create a new isolated session with its own McpServer + transport */ createSession(serverFactory: ServerFactory, clientIp?: string): Promise; /** Look up an existing session by ID */ getSession(sessionId: string): SessionEntry | undefined; /** Whether an unexpired session exists; unlike getSession(), does not refresh lastSeen. */ hasSession(sessionId: string): boolean; /** Terminate and clean up a specific session */ terminateSession(sessionId: string): Promise; /** Terminate all sessions and stop sweep */ cleanup(): Promise; /** Get current session count */ get size(): number; /** Evict sessions past TTL */ private evictStale; /** Decrement per-IP session count, removing the key when it reaches 0 */ private decrementIpCount; } export {}; //# sourceMappingURL=session-manager.d.ts.map