@iworkforces/tracelattice 2.0.3 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"file":"transport/SseTransport.js","sources":["../../src/transport/SseTransport.ts"],"sourcesContent":["/**\n * SSE (Server-Sent Events) Transport implementation.\n *\n * This transport allows multiple concurrent connections over HTTP using Server-Sent Events,\n * enabling multi-user scenarios and horizontal scaling.\n *\n * When a ConnectionPool is provided, each SSE client gets an isolated session with its own\n * thought history. Without a pool, all clients share a single server instance (backward compatible).\n *\n * @example\n * ```typescript\n * const transport = new SseTransport({\n * port: 3000,\n * host: 'localhost'\n * });\n * await transport.connect(server);\n * ```\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { createServer } from 'node:http';\nimport { randomUUID } from 'node:crypto';\nimport { URL } from 'node:url';\nimport type { McpServer } from 'tmcp';\nimport { safeParse } from 'valibot';\nimport type { IMetrics } from '../contracts/interfaces.js';\nimport type { PersistenceConfig } from '../contracts/PersistenceBackend.js';\nimport type { IConnectionPool } from '../pool/IConnectionPool.js';\nimport { ConfigurationError } from '../errors.js';\nimport { SessionNotActiveError, SessionNotFoundError } from '../pool/PoolErrors.js';\nimport { JsonRpcRequestSchema } from '../schema.js';\nimport { BaseTransport, type TransportOptions } from './BaseTransport.js';\nimport type { ITransport, TransportKind } from '../contracts/transport.js';\nimport { asSessionId, type SessionId } from '../contracts/ids.js';\nimport { runWithContext } from '../context/RequestContext.js';\nimport { assertNever } from '../utils.js';\n\ntype SseRequestRouting = {\n\treadonly url: URL;\n\treadonly params: Record<string, string>;\n};\n\ntype McpRequest = Parameters<McpServer['receive']>[0];\n/**\n * SSE-specific transport options extending base TransportOptions.\n */\nexport interface SseTransportOptions extends TransportOptions {\n\tpath?: string;\n\tmetrics?: IMetrics;\n\t/**\n\t * Optional connection pool for per-session state isolation.\n\t * When provided, each SSE client gets an isolated thought history.\n\t * When omitted, all clients share a single server instance (backward compatible).\n\t */\n\tconnectionPool?: IConnectionPool;\n\treadonly persistence?: PersistenceConfig;\n}\n\n/** Rejects persistence backends that cannot isolate pooled SSE child servers. */\nexport function assertPooledSsePersistence(\n\tpoolingEnabled: boolean,\n\tpersistence: PersistenceConfig | undefined\n): void {\n\tif (\n\t\tpoolingEnabled &&\n\t\tpersistence?.enabled === true &&\n\t\t(persistence.backend === 'file' || persistence.backend === 'sqlite')\n\t) {\n\t\tthrow new ConfigurationError(`pooled SSE does not support ${persistence.backend} persistence`);\n\t}\n}\n\n/**\n * SSE Transport for MCP server over HTTP.\n *\n * This transport uses Server-Sent Events (SSE) to communicate with clients,\n * allowing multiple concurrent connections and web-based clients.\n *\n * @remarks\n * **Security Features:**\n * - Session ID validation (alphanumeric, max 64 chars)\n * - Query parameter sanitization (whitelist allowed keys)\n * - Rate limiting per IP (configurable, default 100 req/min)\n * - CORS origin validation\n *\n * **Rate Limiting:**\n * - Tracks requests per IP address within a time window\n * - Returns 429 Too Many Requests when limit exceeded\n * - Can be disabled via `enableRateLimit: false`\n */\nexport class SseTransport extends BaseTransport implements ITransport {\n\tget kind(): TransportKind {\n\t\treturn 'sse';\n\t}\n\tprivate _server: ReturnType<typeof createServer>;\n\tprivate _path: string;\n\tprivate _clients: Set<ServerResponse> = new Set();\n\tprivate _clientSessionMap: Map<ServerResponse, SessionId> = new Map();\n\tprivate readonly _sessionAttachmentCounts = new Map<SessionId, number>();\n\tprivate readonly _releasePromises = new WeakMap<ServerResponse, Promise<void>>();\n\tprivate readonly _pendingReleases = new Set<Promise<void>>();\n\tprivate readonly _releaseFailures = new Set<unknown>();\n\tprivate _messageQueue: Map<string, unknown[]> = new Map();\n\tprivate _metrics?: IMetrics;\n\tprivate _connectionPool?: IConnectionPool;\n\tprivate _stopPromise: Promise<void> | null = null;\n\n\tconstructor(options: SseTransportOptions = {}) {\n\t\tassertPooledSsePersistence(options.connectionPool !== undefined, options.persistence);\n\t\tsuper(options);\n\t\tthis._path = options.path ?? '/sse';\n\t\tthis._metrics = options.metrics;\n\t\tthis._connectionPool = options.connectionPool;\n\t\tthis._updateActiveConnectionsMetric();\n\n\t\tthis._server = createServer((req, res) => this._handleRequest(req, res));\n\t}\n\n\t/**\n\t * Connect MCP server to this transport.\n\t *\n\t * @param mcpServer - The MCP server instance\n\t */\n\tasync connect(mcpServer: McpServer): Promise<void> {\n\t\tthis._mcpServer = mcpServer;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst cleanup = (): void => {\n\t\t\t\tthis._server.off('error', onError);\n\t\t\t\tthis._server.off('listening', onListening);\n\t\t\t};\n\t\t\tconst onError = (error: Error): void => {\n\t\t\t\tcleanup();\n\t\t\t\treject(error);\n\t\t\t};\n\t\t\tconst onListening = (): void => {\n\t\t\t\tcleanup();\n\t\t\t\tthis.log('info', `SSE transport listening on http://${this._host}:${this._port}`);\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tthis._server.once('error', onError);\n\t\t\tthis._server.once('listening', onListening);\n\t\t\ttry {\n\t\t\t\tthis._server.listen(this._port, this._host);\n\t\t\t} catch (error) {\n\t\t\t\tcleanup();\n\t\t\t\treject(error);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate _mcpServer: McpServer | null = null;\n\n\t/**\n\t * Handle incoming HTTP requests\n\t */\n\tprivate async _handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n\t\tconst routing = this._prepareRequest(req, res);\n\t\tif (!routing) return;\n\n\t\tif (this._enableCors && req.method === 'OPTIONS') {\n\t\t\tres.writeHead(204);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\n\t\tif (routing.url.pathname === this._path && req.method === 'GET') {\n\t\t\tawait this._handleSseConnection(req, res, routing.params);\n\t\t\treturn;\n\t\t}\n\n\t\tif (routing.url.pathname === `${this._path}/message` && req.method === 'POST') {\n\t\t\tawait this._handleMessage(req, res, routing.params);\n\t\t\treturn;\n\t\t}\n\n\t\tif (routing.url.pathname === '/health') {\n\t\t\tthis._handleHealthCheck(res);\n\t\t\treturn;\n\t\t}\n\n\t\tif (routing.url.pathname === '/ready') {\n\t\t\tawait this._handleReadinessCheck(res);\n\t\t\treturn;\n\t\t}\n\n\t\tres.writeHead(404, { 'Content-Type': 'text/plain' });\n\t\tres.end('Not Found');\n\t}\n\n\tprivate _prepareRequest(\n\t\treq: IncomingMessage,\n\t\tres: ServerResponse\n\t): SseRequestRouting | undefined {\n\t\tconst startTime = Date.now();\n\t\tconst requestPath = req.url || '/';\n\t\tconst requestMethod = req.method || 'GET';\n\t\tthis._metrics?.counter(\n\t\t\t'http_requests_total',\n\t\t\t1,\n\t\t\t{ transport: 'sse', method: requestMethod, path: requestPath },\n\t\t\t'Total HTTP requests'\n\t\t);\n\t\tres.once('finish', () => {\n\t\t\tconst durationSeconds = (Date.now() - startTime) / 1000;\n\t\t\tthis._metrics?.histogram('http_request_duration_seconds', durationSeconds, {\n\t\t\t\ttransport: 'sse',\n\t\t\t\tpath: requestPath,\n\t\t\t});\n\t\t});\n\t\tif (!this.validateHostHeader(req)) {\n\t\t\tthis._metrics?.counter(\n\t\t\t\t'http_request_errors_total',\n\t\t\t\t1,\n\t\t\t\t{ transport: 'sse', error_type: 'forbidden' },\n\t\t\t\t'Total HTTP request errors'\n\t\t\t);\n\t\t\tres.writeHead(403, { 'Content-Type': 'application/json' });\n\t\t\tres.end(JSON.stringify({ error: 'Forbidden - invalid host header' }));\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || '', `http://${req.headers.host}`);\n\n\t\t// Check rate limit first\n\t\tconst clientIp = this.getClientIp(req);\n\t\tif (this.checkRateLimit(clientIp)) {\n\t\t\tthis._metrics?.counter(\n\t\t\t\t'http_request_errors_total',\n\t\t\t\t1,\n\t\t\t\t{ transport: 'sse', error_type: 'rate_limit' },\n\t\t\t\t'Total HTTP request errors'\n\t\t\t);\n\t\t\tres.writeHead(429, {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t'Retry-After': '60',\n\t\t\t});\n\t\t\tres.end(JSON.stringify({ error: 'Too many requests' }));\n\t\t\treturn;\n\t\t}\n\n\t\t// Validate CORS origin\n\t\tif (!this.validateCorsOrigin(req)) {\n\t\t\tthis._metrics?.counter(\n\t\t\t\t'http_request_errors_total',\n\t\t\t\t1,\n\t\t\t\t{ transport: 'sse', error_type: 'forbidden' },\n\t\t\t\t'Total HTTP request errors'\n\t\t\t);\n\t\t\tres.writeHead(403, { 'Content-Type': 'application/json' });\n\t\t\tres.end(JSON.stringify({ error: 'Forbidden - invalid origin' }));\n\t\t\treturn;\n\t\t}\n\n\t\t// Set CORS headers\n\t\tthis.setCorsHeaders(res);\n\n\t\t// Sanitize query parameters\n\t\tconst sanitizedParams = this.sanitizeQueryParams(url);\n\n\t\t// Validate session ID if present\n\t\tconst requestSessionId = sanitizedParams.session ?? sanitizedParams.sessionId;\n\t\tif (requestSessionId !== undefined && !this.validateSessionId(requestSessionId)) {\n\t\t\tthis._metrics?.counter(\n\t\t\t\t'http_request_errors_total',\n\t\t\t\t1,\n\t\t\t\t{ transport: 'sse', error_type: 'validation' },\n\t\t\t\t'Total HTTP request errors'\n\t\t\t);\n\t\t\tres.writeHead(400, { 'Content-Type': 'application/json' });\n\t\t\tres.end(JSON.stringify({ error: 'Invalid session ID format' }));\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn { url, params: sanitizedParams };\n\t}\n\n\t/**\n\t * Handle health check (liveness) endpoint\n\t */\n\tprivate _handleHealthCheck(res: ServerResponse): void {\n\t\tconst healthData: Record<string, unknown> = { status: 'healthy', clients: this._clients.size };\n\t\tif (this._connectionPool) {\n\t\t\tconst poolStats = this._connectionPool.getStats();\n\t\t\thealthData.pool = poolStats;\n\t\t}\n\t\tif (this._healthChecker) {\n\t\t\tconst liveness = this._healthChecker.checkLiveness();\n\t\t\thealthData.liveness = liveness;\n\t\t}\n\t\tres.writeHead(200, { 'Content-Type': 'application/json' });\n\t\tres.end(JSON.stringify(healthData));\n\t}\n\n\t/**\n\t * Handle readiness check endpoint\n\t */\n\tprivate async _handleReadinessCheck(res: ServerResponse): Promise<void> {\n\t\tif (this._healthChecker) {\n\t\t\tconst readiness = await this._healthChecker.checkReadiness();\n\t\t\tconst statusCode = readiness.status === 'ok' ? 200 : 503;\n\t\t\tres.writeHead(statusCode, { 'Content-Type': 'application/json' });\n\t\t\tres.end(JSON.stringify(readiness));\n\t\t} else {\n\t\t\tres.writeHead(200, { 'Content-Type': 'application/json' });\n\t\t\tres.end(\n\t\t\t\tJSON.stringify({ status: 'ok', timestamp: new Date().toISOString(), components: {} })\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Handle new SSE connection\n\t */\n\tprivate async _handleSseConnection(\n\t\treq: IncomingMessage,\n\t\tres: ServerResponse,\n\t\tparams: Record<string, string>\n\t): Promise<void> {\n\t\t// Set SSE headers\n\t\tres.writeHead(200, {\n\t\t\t'Content-Type': 'text/event-stream',\n\t\t\t'Cache-Control': 'no-cache',\n\t\t\tConnection: 'keep-alive',\n\t\t});\n\n\t\t// Resolve session ID when pool is active\n\t\tlet sessionId: SessionId | undefined;\n\t\tif (this._connectionPool) {\n\t\t\tconst requestedSession = params.session ?? params.sessionId;\n\t\t\tconst requestedSessionId = requestedSession ? asSessionId(requestedSession) : undefined;\n\t\t\tif (requestedSessionId && this._connectionPool.getSessionInfo(requestedSessionId)) {\n\t\t\t\tsessionId = requestedSessionId;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tsessionId = await this._connectionPool.createSession();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tres.write(`event: error\\n`);\n\t\t\t\t\tres.write(\n\t\t\t\t\t\t`data: ${JSON.stringify({ error: error instanceof Error ? error.message : 'Failed to create session' })}\\n\\n`\n\t\t\t\t\t);\n\t\t\t\t\tres.end();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._clientSessionMap.set(res, sessionId);\n\t\t\tthis._sessionAttachmentCounts.set(\n\t\t\t\tsessionId,\n\t\t\t\t(this._sessionAttachmentCounts.get(sessionId) ?? 0) + 1\n\t\t\t);\n\t\t\tthis._updatePoolMetrics();\n\t\t}\n\n\t\tthis._clients.add(res);\n\t\tthis._updateActiveConnectionsMetric();\n\t\tconst release = (): void => this._releaseAfterDisconnect(res);\n\t\treq.once('close', release);\n\t\tres.once('close', release);\n\t\tres.once('error', release);\n\n\t\t// Send initial connection event\n\t\tconst connectedPayload: Record<string, unknown> = { timestamp: Date.now() };\n\t\tif (sessionId) {\n\t\t\tconnectedPayload.sessionId = sessionId;\n\t\t}\n\t\tthis._sendSseEvent(res, 'connected', connectedPayload);\n\n\t\t// Send any queued messages\n\t\tconst clientId = this._generateClientId();\n\t\tconst queued = this._messageQueue.get(clientId);\n\t\tif (queued) {\n\t\t\tfor (const message of queued) {\n\t\t\t\tthis._sendSseEvent(res, 'message', message);\n\t\t\t}\n\t\t\tthis._messageQueue.delete(clientId);\n\t\t}\n\t}\n\n\t/**\n\t * Handle incoming message from client\n\t */\n\tprivate async _handleMessage(\n\t\treq: IncomingMessage,\n\t\tres: ServerResponse,\n\t\tparams: Record<string, string>\n\t): Promise<void> {\n\t\tlet pooledOwner: SessionId | undefined;\n\t\tif (this._connectionPool) {\n\t\t\tconst correlation = params.session ?? params.sessionId;\n\t\t\tif (correlation === undefined) {\n\t\t\t\tres.writeHead(400, { 'Content-Type': 'application/json' });\n\t\t\t\tres.end(JSON.stringify({ error: 'Missing session ID' }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpooledOwner = asSessionId(correlation);\n\t\t}\n\n\t\tconst jsonRpcRequest = await this._parseMessage(req, res);\n\t\tif (!jsonRpcRequest) return;\n\n\t\tconst mcpServer = this._mcpServer;\n\t\tif (!mcpServer) {\n\t\t\tthis._metrics?.counter(\n\t\t\t\t'http_request_errors_total',\n\t\t\t\t1,\n\t\t\t\t{ transport: 'sse', error_type: 'server_not_ready' },\n\t\t\t\t'Total HTTP request errors'\n\t\t\t);\n\t\t\tres.writeHead(503, { 'Content-Type': 'application/json' });\n\t\t\tres.end(JSON.stringify({ error: 'Server not ready' }));\n\t\t\treturn;\n\t\t}\n\n\t\tconst owner = pooledOwner ?? `sse-${randomUUID()}`;\n\t\tconst receive = () =>\n\t\t\trunWithContext({ requestId: randomUUID(), owner }, () =>\n\t\t\t\tmcpServer.receive(jsonRpcRequest, { sessionInfo: {} })\n\t\t\t);\n\t\ttry {\n\t\t\tlet response: Awaited<ReturnType<McpServer['receive']>>;\n\t\t\tif (this._connectionPool && pooledOwner) {\n\t\t\t\tif (typeof this._connectionPool.runWithSession !== 'function') {\n\t\t\t\t\tthis._writeSessionUnavailable(res);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst result = await this._connectionPool.runWithSession(pooledOwner, receive);\n\t\t\t\tswitch (result.status) {\n\t\t\t\t\tcase 'completed':\n\t\t\t\t\t\tresponse = result.value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'inactive':\n\t\t\t\t\tcase 'missing':\n\t\t\t\t\t\tthis._writeSessionUnavailable(res);\n\t\t\t\t\t\treturn;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn assertNever(result);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresponse = await receive();\n\t\t\t}\n\t\t\tres.writeHead(200, { 'Content-Type': 'application/json' });\n\t\t\tres.end(\n\t\t\t\tJSON.stringify(\n\t\t\t\t\tresponse ?? {\n\t\t\t\t\t\tjsonrpc: '2.0',\n\t\t\t\t\t\tid: 'id' in jsonRpcRequest ? jsonRpcRequest.id : null,\n\t\t\t\t\t\tresult: null,\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (error instanceof SessionNotFoundError || error instanceof SessionNotActiveError) {\n\t\t\t\tthis._writeSessionUnavailable(res);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async _parseMessage(\n\t\treq: IncomingMessage,\n\t\tres: ServerResponse\n\t): Promise<McpRequest | undefined> {\n\t\tlet body = '';\n\n\t\tfor await (const chunk of req) {\n\t\t\tbody += chunk.toString();\n\t\t}\n\n\t\tlet rawBody: unknown;\n\t\ttry {\n\t\t\trawBody = JSON.parse(body) as unknown;\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof SyntaxError)) throw error;\n\t\t\tthis._metrics?.counter(\n\t\t\t\t'http_request_errors_total',\n\t\t\t\t1,\n\t\t\t\t{ transport: 'sse', error_type: 'parse_error' },\n\t\t\t\t'Total HTTP request errors'\n\t\t\t);\n\t\t\tres.writeHead(400, { 'Content-Type': 'application/json' });\n\t\t\tres.end(JSON.stringify({ error: 'Invalid JSON' }));\n\t\t\treturn;\n\t\t}\n\n\t\tconst parseResult = safeParse(JsonRpcRequestSchema, rawBody);\n\t\tconst rawId =\n\t\t\trawBody && typeof rawBody === 'object' && 'id' in rawBody\n\t\t\t\t? ((rawBody as { id?: unknown }).id ?? null)\n\t\t\t\t: null;\n\t\tif (!parseResult.success) {\n\t\t\tthis._metrics?.counter(\n\t\t\t\t'http_request_errors_total',\n\t\t\t\t1,\n\t\t\t\t{ transport: 'sse', error_type: 'validation' },\n\t\t\t\t'Total HTTP request errors'\n\t\t\t);\n\t\t\tres.writeHead(200, { 'Content-Type': 'application/json' });\n\t\t\tres.end(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tjsonrpc: '2.0',\n\t\t\t\t\tid: rawId,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: -32600,\n\t\t\t\t\t\tmessage: 'Invalid Request',\n\t\t\t\t\t\tdata: parseResult.issues,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\treturn parseResult.output as McpRequest;\n\t}\n\n\tprivate _writeSessionUnavailable(res: ServerResponse): void {\n\t\tres.writeHead(404, { 'Content-Type': 'application/json' });\n\t\tres.end(JSON.stringify({ error: 'Session not found' }));\n\t}\n\n\tprivate _releaseClient(res: ServerResponse): Promise<void> {\n\t\tconst existing = this._releasePromises.get(res);\n\t\tif (existing) {\n\t\t\treturn existing;\n\t\t}\n\n\t\tthis._clients.delete(res);\n\t\tconst sessionId = this._clientSessionMap.get(res);\n\t\tthis._clientSessionMap.delete(res);\n\t\tthis._updateActiveConnectionsMetric();\n\n\t\tlet releasePromise = Promise.resolve();\n\t\tif (sessionId && this._connectionPool) {\n\t\t\tconst attachmentCount = this._sessionAttachmentCounts.get(sessionId);\n\t\t\tif (attachmentCount !== undefined && attachmentCount > 1) {\n\t\t\t\tthis._sessionAttachmentCounts.set(sessionId, attachmentCount - 1);\n\t\t\t} else {\n\t\t\t\tthis._sessionAttachmentCounts.delete(sessionId);\n\t\t\t\treleasePromise = this._connectionPool.closeSession(sessionId).catch((error: unknown) => {\n\t\t\t\t\tif (error instanceof SessionNotFoundError) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t});\n\t\t\t}\n\t\t\tthis._updatePoolMetrics();\n\t\t}\n\n\t\tthis._releasePromises.set(res, releasePromise);\n\t\tthis._pendingReleases.add(releasePromise);\n\t\tvoid releasePromise.then(\n\t\t\t() => this._pendingReleases.delete(releasePromise),\n\t\t\t(error: unknown) => {\n\t\t\t\tthis._pendingReleases.delete(releasePromise);\n\t\t\t\tthis._releaseFailures.add(error);\n\t\t\t}\n\t\t);\n\t\treturn releasePromise;\n\t}\n\n\tprivate _releaseAfterDisconnect(res: ServerResponse): void {\n\t\tvoid this._releaseClient(res).catch((error: unknown) => {\n\t\t\tthis.log('error', 'SSE pooled session release failed', { error });\n\t\t});\n\t}\n\n\t/**\n\t * Send an SSE event to a specific client\n\t */\n\tprivate _sendSseEvent(res: ServerResponse, event: string, data: unknown): void {\n\t\ttry {\n\t\t\tres.write(`event: ${event}\\n`);\n\t\t\tres.write(`data: ${JSON.stringify(data)}\\n\\n`);\n\t\t} catch {\n\t\t\tthis._releaseAfterDisconnect(res);\n\t\t}\n\t}\n\n\tprivate _updateActiveConnectionsMetric(): void {\n\t\tthis._metrics?.gauge(\n\t\t\t'sse_active_connections',\n\t\t\tthis._clients.size,\n\t\t\t{},\n\t\t\t'Current active SSE connections'\n\t\t);\n\t}\n\n\tprivate _updatePoolMetrics(): void {\n\t\tif (!this._connectionPool || !this._metrics) {\n\t\t\treturn;\n\t\t}\n\t\tconst stats = this._connectionPool.getStats();\n\t\tthis._metrics.gauge(\n\t\t\t'sse_pool_active_sessions',\n\t\t\tstats.activeSessions,\n\t\t\t{},\n\t\t\t'Active sessions in connection pool'\n\t\t);\n\t\tthis._metrics.gauge(\n\t\t\t'sse_pool_total_sessions',\n\t\t\tstats.totalSessions,\n\t\t\t{},\n\t\t\t'Total sessions in connection pool'\n\t\t);\n\t\tthis._metrics.gauge(\n\t\t\t'sse_pool_max_sessions',\n\t\t\tstats.maxSessions,\n\t\t\t{},\n\t\t\t'Maximum sessions in connection pool'\n\t\t);\n\t}\n\n\t/**\n\t * Broadcast a message to all connected clients\n\t */\n\tbroadcast(event: string, data: unknown): void {\n\t\tfor (const client of this._clients) {\n\t\t\tthis._sendSseEvent(client, event, data);\n\t\t}\n\t}\n\n\t/**\n\t * Generate a unique client ID\n\t */\n\tprivate _generateClientId(): string {\n\t\treturn `client_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n\t}\n\n\t/**\n\t * Get number of connected clients\n\t */\n\tget clientCount(): number {\n\t\treturn this._clients.size;\n\t}\n\n\t/**\n\t * Get the connection pool, if one was configured.\n\t */\n\tget connectionPool(): IConnectionPool | undefined {\n\t\treturn this._connectionPool;\n\t}\n\n\t/**\n\t * Stop the transport server with graceful shutdown.\n\t *\n\t * @param timeout - Maximum time to wait for requests to drain (not used for SSE)\n\t * @returns Promise that resolves when shutdown is complete\n\t */\n\tstop(_timeout?: number): Promise<void> {\n\t\tif (this._stopPromise) {\n\t\t\treturn this._stopPromise;\n\t\t}\n\n\t\tconst completion = Promise.withResolvers<void>();\n\t\tthis._stopPromise = completion.promise;\n\t\tthis._isShuttingDown = true;\n\t\tthis._stopRateLimitCleanup();\n\n\t\tconst operations = new Set<Promise<void>>();\n\t\tfor (const client of Array.from(this._clients)) {\n\t\t\toperations.add(this._releaseClient(client));\n\t\t\ttry {\n\t\t\t\tclient.end();\n\t\t\t} catch (error) {\n\t\t\t\toperations.add(\n\t\t\t\t\tPromise.reject(\n\t\t\t\t\t\terror instanceof Error ? error : new AggregateError([error], 'SSE client close failed')\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tfor (const release of this._pendingReleases) {\n\t\t\toperations.add(release);\n\t\t}\n\t\tif (this._connectionPool) {\n\t\t\toperations.add(this._connectionPool.terminate());\n\t\t}\n\t\toperations.add(\n\t\t\tthis._server.listening\n\t\t\t\t? new Promise<void>((resolve, reject) => {\n\t\t\t\t\t\tthis._server.close((error) => (error ? reject(error) : resolve()));\n\t\t\t\t\t})\n\t\t\t\t: Promise.resolve()\n\t\t);\n\n\t\tvoid Promise.allSettled(operations).then((outcomes) => {\n\t\t\tconst failures = new Set<unknown>(this._releaseFailures);\n\t\t\tfor (const outcome of outcomes) {\n\t\t\t\tif (outcome.status !== 'rejected') {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (outcome.reason instanceof AggregateError) {\n\t\t\t\t\tfor (const error of outcome.reason.errors) failures.add(error);\n\t\t\t\t} else {\n\t\t\t\t\tfailures.add(outcome.reason);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._clients.clear();\n\t\t\tthis._clientSessionMap.clear();\n\t\t\tthis._sessionAttachmentCounts.clear();\n\t\t\tthis._updateActiveConnectionsMetric();\n\t\t\tthis._updatePoolMetrics();\n\t\t\tif (failures.size > 0) {\n\t\t\t\tcompletion.reject(new AggregateError(failures, 'SSE transport shutdown failed'));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.log('info', 'SSE transport stopped');\n\t\t\tcompletion.resolve();\n\t\t});\n\n\t\treturn completion.promise;\n\t}\n}\n\n/**\n * Create an SSE transport with given options.\n *\n * @param options - Transport configuration\n * @returns A configured SSE transport\n *\n * @example\n * ```typescript\n * const transport = createSseTransport({ port: 3000 });\n * await transport.connect(mcpServer);\n * ```\n */\nexport function createSseTransport(options: SseTransportOptions = {}): SseTransport {\n\treturn new SseTransport(options);\n}\n"],"names":["assertPooledSsePersistence","poolingEnabled","persistence","ConfigurationError","SseTransport","BaseTransport","Set","Map","WeakMap","options","undefined","createServer","req","res","mcpServer","Promise","resolve","reject","cleanup","onError","onListening","error","routing","startTime","Date","requestPath","requestMethod","durationSeconds","JSON","url","URL","clientIp","sanitizedParams","requestSessionId","healthData","poolStats","liveness","readiness","statusCode","params","sessionId","requestedSession","requestedSessionId","asSessionId","Error","release","connectedPayload","clientId","queued","message","pooledOwner","correlation","jsonRpcRequest","owner","randomUUID","receive","runWithContext","response","result","assertNever","SessionNotFoundError","SessionNotActiveError","body","chunk","rawBody","SyntaxError","parseResult","safeParse","JsonRpcRequestSchema","rawId","existing","releasePromise","attachmentCount","event","data","stats","client","Math","_timeout","completion","operations","Array","AggregateError","outcomes","failures","outcome","createSseTransport"],"mappings":"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"}