@iworkforces/tracelattice 2.3.5 → 2.4.0

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.
Files changed (85) hide show
  1. package/README.md +18 -5
  2. package/dist/ServerConfig.d.ts +16 -0
  3. package/dist/ServerConfig.d.ts.map +1 -1
  4. package/dist/ServerConfig.js +11 -0
  5. package/dist/ServerConfig.js.map +1 -1
  6. package/dist/cli.js +239 -22
  7. package/dist/cli.js.map +1 -1
  8. package/dist/config/ConfigLoader.d.ts +2 -0
  9. package/dist/config/ConfigLoader.d.ts.map +1 -1
  10. package/dist/config/ConfigLoader.js +2 -0
  11. package/dist/config/ConfigLoader.js.map +1 -1
  12. package/dist/contracts/PersistenceBackend.d.ts +26 -0
  13. package/dist/contracts/PersistenceBackend.d.ts.map +1 -1
  14. package/dist/contracts/persistence-backlog.d.ts +21 -0
  15. package/dist/contracts/persistence-backlog.d.ts.map +1 -0
  16. package/dist/contracts/persistence-backlog.js +1 -0
  17. package/dist/core/HistoryManager.d.ts +15 -1
  18. package/dist/core/HistoryManager.d.ts.map +1 -1
  19. package/dist/core/HistoryManager.js +12 -2
  20. package/dist/core/HistoryManager.js.map +1 -1
  21. package/dist/core/IHistoryManager.d.ts +2 -0
  22. package/dist/core/IHistoryManager.d.ts.map +1 -1
  23. package/dist/core/PersistenceBuffer.d.ts +25 -0
  24. package/dist/core/PersistenceBuffer.d.ts.map +1 -1
  25. package/dist/core/PersistenceBuffer.js +27 -5
  26. package/dist/core/PersistenceBuffer.js.map +1 -1
  27. package/dist/core/PersistenceBufferErrors.d.ts +10 -0
  28. package/dist/core/PersistenceBufferErrors.d.ts.map +1 -1
  29. package/dist/core/PersistenceBufferErrors.js +13 -1
  30. package/dist/core/PersistenceBufferErrors.js.map +1 -1
  31. package/dist/core/PersistenceRestore.d.ts.map +1 -1
  32. package/dist/core/PersistenceRestore.js +25 -30
  33. package/dist/core/PersistenceRestore.js.map +1 -1
  34. package/dist/core/PersistenceWorkQueue.d.ts +9 -0
  35. package/dist/core/PersistenceWorkQueue.d.ts.map +1 -1
  36. package/dist/core/PersistenceWorkQueue.js +18 -0
  37. package/dist/core/PersistenceWorkQueue.js.map +1 -1
  38. package/dist/core/ThoughtEvaluator.d.ts +6 -0
  39. package/dist/core/ThoughtEvaluator.d.ts.map +1 -1
  40. package/dist/core/ThoughtEvaluator.js +15 -1
  41. package/dist/core/ThoughtEvaluator.js.map +1 -1
  42. package/dist/core/ThoughtProcessor.d.ts.map +1 -1
  43. package/dist/core/ThoughtProcessor.js +3 -10
  44. package/dist/core/ThoughtProcessor.js.map +1 -1
  45. package/dist/core/evaluator/VerificationLinks.d.ts +5 -0
  46. package/dist/core/evaluator/VerificationLinks.d.ts.map +1 -1
  47. package/dist/core/evaluator/VerificationLinks.js +47 -53
  48. package/dist/core/evaluator/VerificationLinks.js.map +1 -1
  49. package/dist/core/reasoning/ActiveEvidenceProjection.d.ts.map +1 -1
  50. package/dist/core/reasoning/ActiveEvidenceProjection.js +4 -3
  51. package/dist/core/reasoning/ActiveEvidenceProjection.js.map +1 -1
  52. package/dist/errors.d.ts +1 -0
  53. package/dist/errors.d.ts.map +1 -1
  54. package/dist/errors.js +2 -1
  55. package/dist/errors.js.map +1 -1
  56. package/dist/health/HealthChecker.d.ts +42 -1
  57. package/dist/health/HealthChecker.d.ts.map +1 -1
  58. package/dist/health/HealthChecker.js +60 -8
  59. package/dist/health/HealthChecker.js.map +1 -1
  60. package/dist/lib.d.ts +2 -2
  61. package/dist/lib.d.ts.map +1 -1
  62. package/dist/lib.js +1 -0
  63. package/dist/lib.js.map +1 -1
  64. package/dist/metrics/metrics.impl.js.map +1 -1
  65. package/dist/persistence/FilePersistence.d.ts +2 -1
  66. package/dist/persistence/FilePersistence.d.ts.map +1 -1
  67. package/dist/persistence/FilePersistence.js +6 -1
  68. package/dist/persistence/FilePersistence.js.map +1 -1
  69. package/dist/persistence/FileSnapshotV2.d.ts +2 -0
  70. package/dist/persistence/FileSnapshotV2.d.ts.map +1 -1
  71. package/dist/persistence/FileSnapshotV2.js +39 -1
  72. package/dist/persistence/FileSnapshotV2.js.map +1 -1
  73. package/dist/persistence/MemoryPersistence.d.ts +4 -1
  74. package/dist/persistence/MemoryPersistence.d.ts.map +1 -1
  75. package/dist/persistence/MemoryPersistence.js +30 -0
  76. package/dist/persistence/MemoryPersistence.js.map +1 -1
  77. package/dist/persistence/SqlitePersistence.d.ts +6 -1
  78. package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
  79. package/dist/persistence/SqlitePersistence.js +31 -4
  80. package/dist/persistence/SqlitePersistence.js.map +1 -1
  81. package/dist/transport/StreamableHttpTransport.d.ts +12 -0
  82. package/dist/transport/StreamableHttpTransport.d.ts.map +1 -1
  83. package/dist/transport/StreamableHttpTransport.js +19 -5
  84. package/dist/transport/StreamableHttpTransport.js.map +1 -1
  85. package/package.json +20 -20
@@ -140,6 +140,18 @@ export declare class StreamableHttpTransport extends BaseTransport implements IT
140
140
  */
141
141
  connect(mcpServer: McpServer): Promise<void>;
142
142
  private _recordRequestMetrics;
143
+ /**
144
+ * Validate the request origin and attach CORS headers.
145
+ *
146
+ * @returns false when the origin is rejected and the 403 has been sent
147
+ */
148
+ private _admitCors;
149
+ private _isProbeRoute;
150
+ /**
151
+ * Serve GET /health and GET /ready. These run after Host validation and the shutdown check
152
+ * but ahead of the rate limiter; they keep CORS origin validation and headers.
153
+ */
154
+ private _serveProbe;
143
155
  /**
144
156
  * Route and handle incoming HTTP requests.
145
157
  */
@@ -1 +1 @@
1
- {"version":3,"file":"StreamableHttpTransport.d.ts","sourceRoot":"","sources":["../../src/transport/StreamableHttpTransport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StreamableHttpTransport.d.ts","sourceRoot":"","sources":["../../src/transport/StreamableHttpTransport.ts"],"names":[],"mappings":"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"}
@@ -120,28 +120,42 @@ class StreamableHttpTransport extends BaseTransport {
120
120
  this._metrics?.histogram('streamable_http_request_duration_seconds', durationSeconds, {});
121
121
  });
122
122
  }
123
+ _admitCors(req, res) {
124
+ if (!this.validateCorsOrigin(req)) {
125
+ this._sendJsonRpcError(res, 403, -32000, 'Forbidden - invalid origin');
126
+ return false;
127
+ }
128
+ this.setCorsHeaders(res);
129
+ return true;
130
+ }
131
+ _isProbeRoute(req, urlPath) {
132
+ return 'GET' === req.method && ('/health' === urlPath || '/ready' === urlPath);
133
+ }
134
+ async _serveProbe(req, res, urlPath) {
135
+ if (!this._admitCors(req, res)) return;
136
+ if ('/health' === urlPath) this._handleHealthCheck(res);
137
+ else await this._handleReadinessCheck(res);
138
+ }
123
139
  async _handleRequest(req, res) {
124
140
  this._recordRequestMetrics(res);
125
141
  if (!this.validateHostHeader(req)) return void this._sendJsonRpcError(res, 403, -32000, 'Forbidden - invalid host header');
126
142
  if (this.isShuttingDown) return void this._sendJsonRpcError(res, 503, -32603, 'Server is shutting down');
143
+ const urlPath = req.url?.split('?')[0] ?? '/';
144
+ if (this._isProbeRoute(req, urlPath)) return void await this._serveProbe(req, res, urlPath);
127
145
  const clientIp = this.getClientIp(req);
128
146
  if (this.checkRateLimit(clientIp)) {
129
147
  res.setHeader('Retry-After', '60');
130
148
  this._sendJsonRpcError(res, 429, -32000, 'Too many requests');
131
149
  return;
132
150
  }
133
- if (!this.validateCorsOrigin(req)) return void this._sendJsonRpcError(res, 403, -32000, 'Forbidden - invalid origin');
134
- this.setCorsHeaders(res);
151
+ if (!this._admitCors(req, res)) return;
135
152
  if ('OPTIONS' === req.method) {
136
153
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Mcp-Session-Id');
137
154
  res.writeHead(204);
138
155
  res.end();
139
156
  return;
140
157
  }
141
- const urlPath = req.url?.split('?')[0] ?? '/';
142
158
  if ('GET' === req.method && '/metrics' === urlPath) return void this._handleMetrics(res);
143
- if ('GET' === req.method && '/health' === urlPath) return void this._handleHealthCheck(res);
144
- if ('GET' === req.method && '/ready' === urlPath) return void await this._handleReadinessCheck(res);
145
159
  if (urlPath === this._path) {
146
160
  if ('POST' === req.method) {
147
161
  const lease = this._preDispatch.acquire();
@@ -1 +1 @@
1
- {"version":3,"file":"transport/StreamableHttpTransport.js","sources":["../../src/transport/StreamableHttpTransport.ts"],"sourcesContent":["/**\n * Streamable HTTP Transport implementation (MCP spec recommended transport).\n *\n * Key features:\n * - POST /mcp for JSON-RPC requests (main MCP endpoint)\n * - Session management via Mcp-Session-Id header\n * - Supports both stateful (session-based) and stateless (per-request) modes\n * - Health endpoints (/health, /ready)\n *\n * @example\n * ```typescript\n * const transport = new StreamableHttpTransport({\n * port: 3000,\n * host: 'localhost',\n * stateful: true,\n * });\n * await transport.connect(server);\n * ```\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http';\nimport type { McpServer } from 'tmcp';\nimport { safeParse } from 'valibot';\nimport type { IMetrics } from '../contracts/interfaces.js';\nimport { getErrorMessage } from '../errors.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 { readRequestBody } from './HttpHelpers.js';\nimport { runWithContext } from '../context/RequestContext.js';\nimport {\n\tAcceptedWorkTracker,\n\tLifecycleFailureReporter,\n\tPreDispatchTracker,\n\tResponseFinalizer,\n\ttype PreDispatchLease,\n} from './HttpRequestLifecycle.js';\n\n/**\n * MCP Streamable HTTP transport options extending base TransportOptions.\n */\nexport interface StreamableHttpTransportOptions extends TransportOptions {\n\t/**\n\t * Path for the MCP endpoint\n\t * @default '/mcp'\n\t */\n\tpath?: string;\n\n\t/**\n\t * Metrics collector for transport telemetry\n\t */\n\tmetrics?: IMetrics;\n\n\t/**\n\t * Prometheus metrics provider function\n\t */\n\tmetricsProvider?: () => string;\n\n\t/**\n\t * Enable stateful session-based mode.\n\t * When true, sessions are tracked via Mcp-Session-Id header.\n\t * When false, each request is processed independently (stateless).\n\t * @default true\n\t */\n\tstateful?: boolean;\n\n\t/**\n\t * Custom session ID generator function.\n\t * @default () => randomUUID()\n\t */\n\tsessionIdGenerator?: () => string;\n\n\t/**\n\t * Enable request body size limit\n\t * @default true\n\t */\n\tenableBodySizeLimit?: boolean;\n\n\t/**\n\t * Maximum request body size in bytes\n\t * @default 10485760 (10MB)\n\t */\n\tmaxBodySize?: number;\n\n\t/**\n\t * Request timeout in milliseconds\n\t * @default 30000 (30 seconds)\n\t */\n\trequestTimeout?: number;\n\n\t/** Maximum retained sessions when idle expiry is enabled. */\n\tmaxSessions?: number;\n\n\t/** Idle duration before an unpinned session expires. */\n\tsessionIdleTimeoutMs?: number;\n\n\t/** Interval between idle-session sweeps. */\n\tsessionSweepIntervalMs?: number;\n}\n\ntype SessionRetentionOptions = {\n\treadonly maxSessions: number;\n\treadonly sessionIdleTimeoutMs: number;\n\treadonly sessionSweepIntervalMs: number;\n};\n\nfunction parseSessionRetentionOptions(\n\toptions: StreamableHttpTransportOptions\n): SessionRetentionOptions | null {\n\tconst { maxSessions, sessionIdleTimeoutMs, sessionSweepIntervalMs } = options;\n\tif (\n\t\tmaxSessions === undefined &&\n\t\tsessionIdleTimeoutMs === undefined &&\n\t\tsessionSweepIntervalMs === undefined\n\t) {\n\t\treturn null;\n\t}\n\tif (\n\t\tmaxSessions === undefined ||\n\t\t!Number.isFinite(maxSessions) ||\n\t\t!Number.isInteger(maxSessions) ||\n\t\tmaxSessions <= 0 ||\n\t\tsessionIdleTimeoutMs === undefined ||\n\t\t!Number.isFinite(sessionIdleTimeoutMs) ||\n\t\t!Number.isInteger(sessionIdleTimeoutMs) ||\n\t\tsessionIdleTimeoutMs <= 0 ||\n\t\tsessionSweepIntervalMs === undefined ||\n\t\t!Number.isFinite(sessionSweepIntervalMs) ||\n\t\t!Number.isInteger(sessionSweepIntervalMs) ||\n\t\tsessionSweepIntervalMs <= 0\n\t) {\n\t\tthrow new TypeError(\n\t\t\t'maxSessions, sessionIdleTimeoutMs, and sessionSweepIntervalMs must be provided together as positive integers'\n\t\t);\n\t}\n\treturn {\n\t\tmaxSessions,\n\t\tsessionIdleTimeoutMs,\n\t\tsessionSweepIntervalMs,\n\t};\n}\n\n/**\n * Internal session state for stateful mode.\n */\ninterface SessionState {\n\t/** Unique session identifier */\n\tid: SessionId;\n\t/** Timestamp when the session was created */\n\tcreatedAt: number;\n\t/** Timestamp of the last activity */\n\tlastActivityAt: number;\n\tacceptedPostCount: number;\n}\n\ntype SessionError = {\n\treadonly statusCode: number;\n\treadonly code: number;\n\treadonly message: string;\n};\n\ntype AcceptedPostSession = {\n\treadonly id: string | undefined;\n\treadonly state: SessionState | null;\n};\n\n/**\n * Streamable HTTP Transport for MCP server.\n *\n * This transport implements the MCP Streamable HTTP specification,\n * providing JSON-RPC over HTTP with optional session management.\n *\n * @remarks\n * **Security Features (inherited from BaseTransport):**\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 * - Host header validation\n *\n * **MCP Streamable HTTP Spec Compliance:**\n * - POST /mcp — JSON-RPC method calls\n * - Mcp-Session-Id header for session management\n * - Content-Type: application/json for JSON-RPC responses\n *\n * **HTTP Status Code Mapping:**\n * - 200: Success (JSON-RPC response)\n * - 202: Accepted (JSON-RPC notification, no response body)\n * - 204: CORS Preflight (empty body)\n * - 400: Bad Request (invalid JSON, invalid session ID)\n * - 403: Forbidden (invalid CORS, invalid host)\n * - 404: Not Found\n * - 405: Method Not Allowed\n * - 413: Payload Too Large\n * - 429: Too Many Requests\n * - 500: Internal Server Error\n * - 503: Server Not Ready / Shutting Down\n */\nexport class StreamableHttpTransport extends BaseTransport implements ITransport {\n\tget kind(): TransportKind {\n\t\treturn 'streamable-http';\n\t}\n\tprivate _server: Server | null = null;\n\tprivate _mcpServer: McpServer | null = null;\n\tprivate _path: string;\n\tprivate _stateful: boolean;\n\tprivate _sessionIdGenerator: () => string;\n\tprivate _sessions: Map<SessionId, SessionState> = new Map();\n\tprivate _requestCount: number = 0;\n\tprivate _activeRequests: number = 0;\n\tprivate _bodySizeLimitEnabled: boolean;\n\tprivate _maxBodySize: number;\n\tprivate _requestTimeout: number;\n\tprivate _metrics?: IMetrics;\n\tprivate _metricsProvider: (() => string) | null;\n\tprivate readonly _lifecycleFailureReporter: LifecycleFailureReporter;\n\tprivate readonly _acceptedWork: AcceptedWorkTracker;\n\tprivate readonly _preDispatch = new PreDispatchTracker();\n\tprivate readonly _sessionRetention: SessionRetentionOptions | null;\n\tprivate _sessionSweepIntervalId: NodeJS.Timeout | null = null;\n\tprivate _stopPromise: Promise<void> | null = null;\n\n\tconstructor(options: StreamableHttpTransportOptions = {}) {\n\t\tconst sessionRetention = parseSessionRetentionOptions(options);\n\t\tsuper(options);\n\n\t\tthis._path = options.path ?? '/mcp';\n\t\tthis._stateful = options.stateful ?? true;\n\t\tthis._sessionIdGenerator = options.sessionIdGenerator ?? (() => randomUUID());\n\t\tthis._bodySizeLimitEnabled = options.enableBodySizeLimit ?? true;\n\t\tthis._maxBodySize = options.maxBodySize ?? 10 * 1024 * 1024;\n\t\tthis._requestTimeout = options.requestTimeout ?? 30000;\n\t\tthis._metrics = options.metrics;\n\t\tthis._metricsProvider = options.metricsProvider ?? null;\n\t\tthis._sessionRetention = sessionRetention;\n\t\tthis._lifecycleFailureReporter = new LifecycleFailureReporter((error) => {\n\t\t\tthis.log('error', 'Streamable HTTP request lifecycle failed', {\n\t\t\t\terror: getErrorMessage(error),\n\t\t\t});\n\t\t});\n\t\tthis._acceptedWork = new AcceptedWorkTracker(this._lifecycleFailureReporter);\n\t\tif (this._stateful && sessionRetention) {\n\t\t\tthis._sessionSweepIntervalId = setInterval(\n\t\t\t\t() => this._sweepExpiredSessions(),\n\t\t\t\tsessionRetention.sessionSweepIntervalMs\n\t\t\t);\n\t\t\tthis._sessionSweepIntervalId.unref();\n\t\t}\n\t}\n\n\tprivate _requireMcpServer(): McpServer {\n\t\tif (!this._mcpServer) {\n\t\t\tthrow new Error('MCP server not initialized. Did you call connect()?');\n\t\t}\n\t\treturn this._mcpServer;\n\t}\n\n\t/**\n\t * Get number of active sessions (stateful) or active requests (stateless).\n\t */\n\tget clientCount(): number {\n\t\treturn this._stateful ? this._sessions.size : this._activeRequests;\n\t}\n\n\t/**\n\t * Get the total number of requests handled.\n\t */\n\tget requestCount(): number {\n\t\treturn this._requestCount;\n\t}\n\n\t/**\n\t * Connects MCP server to this transport and starts listening.\n\t */\n\tasync connect(mcpServer: McpServer): Promise<void> {\n\t\tthis._mcpServer = mcpServer;\n\t\tconst server = createServer((req, res) => {\n\t\t\tconst responseFinalizer = new ResponseFinalizer(res, this._lifecycleFailureReporter);\n\t\t\tvoid this._handleRequest(req, res).catch((error: unknown) => {\n\t\t\t\tthis._lifecycleFailureReporter.report(error);\n\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\tthis._sendJsonRpcError(response, 500, -32603, 'Internal error', null, {\n\t\t\t\t\t\tdata: getErrorMessage(error),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\tthis._server = server;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst cleanup = (): void => {\n\t\t\t\tserver.off('error', onError);\n\t\t\t\tserver.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(\n\t\t\t\t\t'info',\n\t\t\t\t\t`Streamable HTTP transport listening on http://${this._host}:${this._port}`\n\t\t\t\t);\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tserver.once('error', onError);\n\t\t\tserver.once('listening', onListening);\n\t\t\ttry {\n\t\t\t\tserver.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 _recordRequestMetrics(res: ServerResponse): void {\n\t\tconst startTime = Date.now();\n\t\tthis._metrics?.counter(\n\t\t\t'streamable_http_requests_total',\n\t\t\t1,\n\t\t\t{},\n\t\t\t'Total Streamable HTTP transport requests'\n\t\t);\n\t\tres.once('finish', () => {\n\t\t\tconst durationSeconds = (Date.now() - startTime) / 1000;\n\t\t\tthis._metrics?.histogram('streamable_http_request_duration_seconds', durationSeconds, {});\n\t\t});\n\t}\n\n\t/**\n\t * Route and handle incoming HTTP requests.\n\t */\n\tprivate async _handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n\t\tthis._recordRequestMetrics(res);\n\n\t\t// Host validation\n\t\tif (!this.validateHostHeader(req)) {\n\t\t\tthis._sendJsonRpcError(res, 403, -32000, 'Forbidden - invalid host header');\n\t\t\treturn;\n\t\t}\n\n\t\t// Shutdown check\n\t\tif (this.isShuttingDown) {\n\t\t\tthis._sendJsonRpcError(res, 503, -32603, 'Server is shutting down');\n\t\t\treturn;\n\t\t}\n\n\t\t// Rate limiting\n\t\tconst clientIp = this.getClientIp(req);\n\t\tif (this.checkRateLimit(clientIp)) {\n\t\t\tres.setHeader('Retry-After', '60');\n\t\t\tthis._sendJsonRpcError(res, 429, -32000, 'Too many requests');\n\t\t\treturn;\n\t\t}\n\n\t\t// CORS validation\n\t\tif (!this.validateCorsOrigin(req)) {\n\t\t\tthis._sendJsonRpcError(res, 403, -32000, 'Forbidden - invalid origin');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.setCorsHeaders(res);\n\n\t\t// CORS preflight\n\t\tif (req.method === 'OPTIONS') {\n\t\t\tres.setHeader('Access-Control-Allow-Headers', 'Content-Type, Mcp-Session-Id');\n\t\t\tres.writeHead(204);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\n\t\t// Parse URL path\n\t\tconst urlPath = req.url?.split('?')[0] ?? '/';\n\n\t\t// Metrics endpoint\n\t\tif (req.method === 'GET' && urlPath === '/metrics') {\n\t\t\tthis._handleMetrics(res);\n\t\t\treturn;\n\t\t}\n\n\t\t// Health check (liveness)\n\t\tif (req.method === 'GET' && urlPath === '/health') {\n\t\t\tthis._handleHealthCheck(res);\n\t\t\treturn;\n\t\t}\n\n\t\t// Readiness check\n\t\tif (req.method === 'GET' && urlPath === '/ready') {\n\t\t\tawait this._handleReadinessCheck(res);\n\t\t\treturn;\n\t\t}\n\n\t\t// MCP endpoint routing\n\t\tif (urlPath === this._path) {\n\t\t\tif (req.method === 'POST') {\n\t\t\t\tconst lease = this._preDispatch.acquire();\n\t\t\t\tif (!lease) {\n\t\t\t\t\tconst responseFinalizer = new ResponseFinalizer(res, this._lifecycleFailureReporter);\n\t\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\t\tthis._sendJsonRpcError(response, 503, -32603, 'Server is shutting down');\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tawait this._handleMcpPost(req, res, lease);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tres.writeHead(405, { 'Content-Type': 'application/json', Allow: 'POST' });\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: null,\n\t\t\t\t\terror: { code: -32601, message: 'Method not allowed' },\n\t\t\t\t})\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// 404 for unknown paths\n\t\tthis._sendJsonRpcError(res, 404, -32601, 'Not Found');\n\t}\n\n\t/**\n\t * Send a JSON-RPC error response.\n\t */\n\tprivate _sendJsonRpcError(\n\t\tres: ServerResponse,\n\t\tstatusCode: number,\n\t\tcode: number,\n\t\tmessage: string,\n\t\tid: unknown = null,\n\t\textra?: Record<string, unknown>\n\t): void {\n\t\tconst error: Record<string, unknown> = { code, message };\n\t\tif (extra) {\n\t\t\tObject.assign(error, extra);\n\t\t}\n\t\tres.writeHead(statusCode, { 'Content-Type': 'application/json' });\n\t\tres.end(JSON.stringify({ jsonrpc: '2.0', id, error }));\n\t}\n\n\tprivate _parseJsonRpcRequest(\n\t\tbody: string,\n\t\tresponseFinalizer: ResponseFinalizer\n\t): Parameters<McpServer['receive']>[0] | null {\n\t\tlet rawBody: unknown;\n\t\ttry {\n\t\t\trawBody = JSON.parse(body) as unknown;\n\t\t} catch {\n\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(response, 200, -32700, 'Parse error');\n\t\t\t});\n\t\t\treturn null;\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\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(\n\t\t\t\t\tresponse,\n\t\t\t\t\t200,\n\t\t\t\t\t-32600,\n\t\t\t\t\t'Invalid Request',\n\t\t\t\t\trawId as string | number | null,\n\t\t\t\t\t{ data: parseResult.issues }\n\t\t\t\t);\n\t\t\t});\n\t\t\treturn null;\n\t\t}\n\t\treturn parseResult.output as Parameters<McpServer['receive']>[0];\n\t}\n\n\t/**\n\t * Handle POST /mcp — JSON-RPC method calls.\n\t *\n\t * Per the MCP Streamable HTTP spec:\n\t * - Accepts JSON-RPC request bodies\n\t * - Returns Mcp-Session-Id header for new sessions (stateful mode)\n\t * - Validates Mcp-Session-Id for existing sessions (stateful mode)\n\t * - Content-Type: application/json for responses\n\t */\n\tprivate async _handleMcpPost(\n\t\treq: IncomingMessage,\n\t\tres: ServerResponse,\n\t\tlease: PreDispatchLease\n\t): Promise<void> {\n\t\tthis._requestCount++;\n\t\tthis._activeRequests++;\n\t\tconst responseFinalizer = new ResponseFinalizer(res, this._lifecycleFailureReporter);\n\t\tlet acceptedSession: SessionState | null = null;\n\t\tconst onAborted = (): void => lease.cancel('peer');\n\t\treq.once('aborted', onAborted);\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(response, 500, -32603, 'Request timeout');\n\t\t\t});\n\t\t\tlease.cancel('timeout');\n\t\t}, this._requestTimeout);\n\t\ttry {\n\t\t\t// Read request body with size limit\n\t\t\tconst body = await readRequestBody(\n\t\t\t\treq,\n\t\t\t\tthis._bodySizeLimitEnabled ? this._maxBodySize : 0,\n\t\t\t\tlease.signal\n\t\t\t);\n\t\t\tif (body === null) {\n\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\tthis._sendJsonRpcError(response, 413, -32000, 'Request body too large');\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst jsonRpcRequest = this._parseJsonRpcRequest(body, responseFinalizer);\n\t\t\tif (jsonRpcRequest === null) return;\n\n\t\t\tconst session = this._acceptPostSession(req, responseFinalizer);\n\t\t\tif (!session) return;\n\t\t\tacceptedSession = session.state;\n\n\t\t\t// Check if MCP server is ready\n\t\t\tif (!this._mcpServer) {\n\t\t\t\tconst requestId = 'id' in jsonRpcRequest ? (jsonRpcRequest.id ?? null) : null;\n\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\tthis._sendJsonRpcError(response, 503, -32603, 'Server not ready', requestId);\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\treq.off('aborted', onAborted);\n\t\t\tconst acceptedWork = this._acceptedWork.transfer(lease, () =>\n\t\t\t\tthis._receiveAndFinalize(jsonRpcRequest, session.id, responseFinalizer).catch(\n\t\t\t\t\t(error: unknown) => {\n\t\t\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\t\t\tthis._sendJsonRpcError(response, 200, -32603, 'Internal error', null, {\n\t\t\t\t\t\t\t\tdata: getErrorMessage(error),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t);\n\t\t\tawait acceptedWork;\n\t\t} catch (error) {\n\t\t\tif (lease.signal.aborted) {\n\t\t\t\tif (lease.cancellationReason === 'shutdown') {\n\t\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\t\tthis._sendJsonRpcError(response, 503, -32603, 'Server is shutting down');\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(response, 200, -32603, 'Internal error', null, {\n\t\t\t\t\tdata: getErrorMessage(error),\n\t\t\t\t});\n\t\t\t});\n\t\t} finally {\n\t\t\treq.off('aborted', onAborted);\n\t\t\tlease.release();\n\t\t\tif (acceptedSession) acceptedSession.acceptedPostCount--;\n\t\t\tclearTimeout(timeout);\n\t\t\tthis._activeRequests--;\n\t\t}\n\t}\n\n\tprivate _acceptPostSession(\n\t\treq: IncomingMessage,\n\t\tresponseFinalizer: ResponseFinalizer\n\t): AcceptedPostSession | null {\n\t\tif (!this._stateful) return { id: undefined, state: null };\n\t\tif (this.isShuttingDown) {\n\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(response, 503, -32603, 'Server is shutting down');\n\t\t\t});\n\t\t\treturn null;\n\t\t}\n\t\tconst session = this._resolveSession(req);\n\t\tif (!('state' in session)) {\n\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(response, session.statusCode, session.code, session.message);\n\t\t\t});\n\t\t\treturn null;\n\t\t}\n\t\tsession.state.acceptedPostCount++;\n\t\treturn { id: session.id, state: session.state };\n\t}\n\n\tprivate async _receiveAndFinalize(\n\t\tjsonRpcRequest: Parameters<McpServer['receive']>[0],\n\t\tsessionId: string | undefined,\n\t\tresponseFinalizer: ResponseFinalizer\n\t): Promise<void> {\n\t\tconst owner = this._stateful ? (sessionId ?? randomUUID()) : randomUUID();\n\t\tconst response = await runWithContext({ requestId: randomUUID(), owner }, () =>\n\t\t\tthis._requireMcpServer().receive(jsonRpcRequest, { sessionInfo: {} })\n\t\t);\n\t\tconst responseHeaders: Record<string, string> = { 'Content-Type': 'application/json' };\n\t\tif (sessionId) responseHeaders['Mcp-Session-Id'] = sessionId;\n\n\t\tresponseFinalizer.finalize((httpResponse) => {\n\t\t\tif (response) {\n\t\t\t\thttpResponse.writeHead(200, responseHeaders);\n\t\t\t\thttpResponse.end(JSON.stringify(response));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (sessionId) httpResponse.setHeader('Mcp-Session-Id', sessionId);\n\t\t\thttpResponse.writeHead(202);\n\t\t\thttpResponse.end();\n\t\t});\n\t}\n\n\t/**\n\t * Resolve or create a session for a stateful request.\n\t *\n\t * @returns Session ID string on success, or the response error to finalize.\n\t */\n\tprivate _resolveSession(\n\t\treq: IncomingMessage\n\t): { readonly id: SessionId; readonly state: SessionState } | SessionError {\n\t\tconst headerSessionId = this._getSessionIdFromHeader(req);\n\n\t\tif (headerSessionId) {\n\t\t\t// Validate format\n\t\t\tif (!this.validateSessionId(headerSessionId)) {\n\t\t\t\treturn {\n\t\t\t\t\tstatusCode: 400,\n\t\t\t\t\tcode: -32600,\n\t\t\t\t\tmessage: 'Invalid Mcp-Session-Id format',\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Check if session exists\n\t\t\tconst session = this._sessions.get(asSessionId(headerSessionId));\n\t\t\tif (session) {\n\t\t\t\tsession.lastActivityAt = Date.now();\n\t\t\t\treturn { id: session.id, state: session };\n\t\t\t}\n\n\t\t\t// Unknown session ID — per spec, return 404\n\t\t\treturn { statusCode: 404, code: -32001, message: 'Session not found' };\n\t\t}\n\n\t\t// No session header — create new session\n\t\tif (this._sessionRetention && this._sessions.size >= this._sessionRetention.maxSessions) {\n\t\t\treturn { statusCode: 503, code: -32000, message: 'Session capacity reached' };\n\t\t}\n\t\tconst newSessionId = asSessionId(this._sessionIdGenerator());\n\t\tconst now = Date.now();\n\t\tconst sessionState: SessionState = {\n\t\t\tid: newSessionId,\n\t\t\tcreatedAt: now,\n\t\t\tlastActivityAt: now,\n\t\t\tacceptedPostCount: 0,\n\t\t};\n\t\tthis._sessions.set(newSessionId, sessionState);\n\t\tthis.log('info', `New session created: ${newSessionId}`);\n\t\tthis._updateSessionMetrics();\n\n\t\treturn { id: newSessionId, state: sessionState };\n\t}\n\n\tprivate _sweepExpiredSessions(): void {\n\t\tif (!this._sessionRetention) return;\n\t\tconst now = Date.now();\n\t\tfor (const [sessionId, session] of this._sessions) {\n\t\t\tif (\n\t\t\t\tsession.acceptedPostCount === 0 &&\n\t\t\t\tnow - session.lastActivityAt >= this._sessionRetention.sessionIdleTimeoutMs\n\t\t\t) {\n\t\t\t\tthis._disposeSession(sessionId);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _disposeSession(sessionId: SessionId): void {\n\t\tif (!this._sessions.delete(sessionId)) return;\n\t\tthis._updateSessionMetrics();\n\t}\n\n\tprivate _stopSessionSweep(): void {\n\t\tconst interval = this._sessionSweepIntervalId;\n\t\tif (!interval) return;\n\t\tinterval.unref();\n\t\tclearInterval(interval);\n\t\tthis._sessionSweepIntervalId = null;\n\t}\n\n\t/**\n\t * Extract Mcp-Session-Id from request headers.\n\t */\n\tprivate _getSessionIdFromHeader(req: IncomingMessage): string | undefined {\n\t\tconst value = req.headers['mcp-session-id'];\n\t\tif (typeof value === 'string' && value.length > 0) {\n\t\t\treturn value;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Handle GET /metrics endpoint.\n\t */\n\tprivate _handleMetrics(res: ServerResponse): void {\n\t\tif (!this._metricsProvider) {\n\t\t\tres.writeHead(404, { 'Content-Type': 'text/plain' });\n\t\t\tres.end('Not Found');\n\t\t\treturn;\n\t\t}\n\n\t\tres.writeHead(200, { 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8' });\n\t\tres.end(this._metricsProvider());\n\t}\n\n\t/**\n\t * Handle GET /health — Liveness check.\n\t */\n\tprivate _handleHealthCheck(res: ServerResponse): void {\n\t\tconst healthData: Record<string, unknown> = {\n\t\t\tstatus: 'healthy',\n\t\t\trequests: this._requestCount,\n\t\t\tsessions: this._sessions.size,\n\t\t\ttransport: 'streamable-http',\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 GET /ready — Readiness check.\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({\n\t\t\t\t\tstatus: 'ok',\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t\tcomponents: {},\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Update session-related metrics.\n\t */\n\tprivate _updateSessionMetrics(): void {\n\t\tthis._metrics?.gauge(\n\t\t\t'streamable_http_active_sessions',\n\t\t\tthis._sessions.size,\n\t\t\t{},\n\t\t\t'Active Streamable HTTP sessions'\n\t\t);\n\t}\n\n\t/**\n\t * Stop transport server with graceful shutdown.\n\t *\n\t * @param timeout - Maximum time before force-closing HTTP connections (default: 30s)\n\t */\n\tstop(timeout?: number): Promise<void> {\n\t\tif (this._stopPromise) return this._stopPromise;\n\t\tthis._isShuttingDown = true;\n\t\tthis._preDispatch.closeAdmission('shutdown');\n\t\tthis._stopRateLimitCleanup();\n\t\tthis._stopSessionSweep();\n\n\t\tconst shutdownTimeout = timeout ?? 30000;\n\n\t\tfor (const sessionId of this._sessions.keys()) {\n\t\t\tthis._disposeSession(sessionId);\n\t\t}\n\n\t\tconst server = this._server;\n\t\tconst serverClosed = new Promise<void>((resolve, reject) => {\n\t\t\tif (!server?.listening) {\n\t\t\t\tresolve();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet settled = false;\n\t\t\tlet forceClose: NodeJS.Timeout | null = null;\n\t\t\tserver.close((error) => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tif (forceClose) clearTimeout(forceClose);\n\t\t\t\tif (error) {\n\t\t\t\t\treject(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tresolve();\n\t\t\t});\n\t\t\tif (settled) return;\n\t\t\tforceClose = setTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tthis.log('warn', 'Streamable HTTP transport force-closing after timeout');\n\t\t\t\tserver.closeAllConnections();\n\t\t\t\tresolve();\n\t\t\t}, shutdownTimeout);\n\t\t});\n\t\tconst stopPromise = Promise.all([\n\t\t\tserverClosed,\n\t\t\tthis._preDispatch.join().then(() => this._acceptedWork.join()),\n\t\t]).then(() => {\n\t\t\tthis.log('info', 'Streamable HTTP transport stopped');\n\t\t});\n\t\tthis._stopPromise = stopPromise;\n\t\tvoid stopPromise.catch(() => {\n\t\t\tif (this._stopPromise === stopPromise) this._stopPromise = null;\n\t\t});\n\t\treturn stopPromise;\n\t}\n}\n\n/**\n * Create a Streamable HTTP transport with given options.\n *\n * @param options - Transport configuration\n * @returns A configured Streamable HTTP transport\n *\n * @example\n * ```typescript\n * const transport = createStreamableHttpTransport({ port: 3000, stateful: true });\n * await transport.connect(server);\n * ```\n */\nexport function createStreamableHttpTransport(\n\toptions: StreamableHttpTransportOptions = {}\n): StreamableHttpTransport {\n\treturn new StreamableHttpTransport(options);\n}\n"],"names":["parseSessionRetentionOptions","options","maxSessions","sessionIdleTimeoutMs","sessionSweepIntervalMs","undefined","Number","TypeError","StreamableHttpTransport","BaseTransport","Map","PreDispatchTracker","sessionRetention","randomUUID","LifecycleFailureReporter","error","getErrorMessage","AcceptedWorkTracker","setInterval","Error","mcpServer","server","createServer","req","res","responseFinalizer","ResponseFinalizer","response","Promise","resolve","reject","cleanup","onError","onListening","startTime","Date","durationSeconds","clientIp","urlPath","lease","JSON","statusCode","code","message","id","extra","Object","body","rawBody","parseResult","safeParse","JsonRpcRequestSchema","rawId","acceptedSession","onAborted","timeout","setTimeout","readRequestBody","jsonRpcRequest","session","requestId","acceptedWork","clearTimeout","sessionId","owner","runWithContext","responseHeaders","httpResponse","headerSessionId","asSessionId","newSessionId","now","sessionState","interval","clearInterval","value","healthData","liveness","readiness","shutdownTimeout","serverClosed","settled","forceClose","stopPromise","createStreamableHttpTransport"],"mappings":"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"}
1
+ {"version":3,"file":"transport/StreamableHttpTransport.js","sources":["../../src/transport/StreamableHttpTransport.ts"],"sourcesContent":["/**\n * Streamable HTTP Transport implementation (MCP spec recommended transport).\n *\n * Key features:\n * - POST /mcp for JSON-RPC requests (main MCP endpoint)\n * - Session management via Mcp-Session-Id header\n * - Supports both stateful (session-based) and stateless (per-request) modes\n * - Health endpoints (/health, /ready)\n *\n * @example\n * ```typescript\n * const transport = new StreamableHttpTransport({\n * port: 3000,\n * host: 'localhost',\n * stateful: true,\n * });\n * await transport.connect(server);\n * ```\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http';\nimport type { McpServer } from 'tmcp';\nimport { safeParse } from 'valibot';\nimport type { IMetrics } from '../contracts/interfaces.js';\nimport { getErrorMessage } from '../errors.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 { readRequestBody } from './HttpHelpers.js';\nimport { runWithContext } from '../context/RequestContext.js';\nimport {\n\tAcceptedWorkTracker,\n\tLifecycleFailureReporter,\n\tPreDispatchTracker,\n\tResponseFinalizer,\n\ttype PreDispatchLease,\n} from './HttpRequestLifecycle.js';\n\n/**\n * MCP Streamable HTTP transport options extending base TransportOptions.\n */\nexport interface StreamableHttpTransportOptions extends TransportOptions {\n\t/**\n\t * Path for the MCP endpoint\n\t * @default '/mcp'\n\t */\n\tpath?: string;\n\n\t/**\n\t * Metrics collector for transport telemetry\n\t */\n\tmetrics?: IMetrics;\n\n\t/**\n\t * Prometheus metrics provider function\n\t */\n\tmetricsProvider?: () => string;\n\n\t/**\n\t * Enable stateful session-based mode.\n\t * When true, sessions are tracked via Mcp-Session-Id header.\n\t * When false, each request is processed independently (stateless).\n\t * @default true\n\t */\n\tstateful?: boolean;\n\n\t/**\n\t * Custom session ID generator function.\n\t * @default () => randomUUID()\n\t */\n\tsessionIdGenerator?: () => string;\n\n\t/**\n\t * Enable request body size limit\n\t * @default true\n\t */\n\tenableBodySizeLimit?: boolean;\n\n\t/**\n\t * Maximum request body size in bytes\n\t * @default 10485760 (10MB)\n\t */\n\tmaxBodySize?: number;\n\n\t/**\n\t * Request timeout in milliseconds\n\t * @default 30000 (30 seconds)\n\t */\n\trequestTimeout?: number;\n\n\t/** Maximum retained sessions when idle expiry is enabled. */\n\tmaxSessions?: number;\n\n\t/** Idle duration before an unpinned session expires. */\n\tsessionIdleTimeoutMs?: number;\n\n\t/** Interval between idle-session sweeps. */\n\tsessionSweepIntervalMs?: number;\n}\n\ntype SessionRetentionOptions = {\n\treadonly maxSessions: number;\n\treadonly sessionIdleTimeoutMs: number;\n\treadonly sessionSweepIntervalMs: number;\n};\n\nfunction parseSessionRetentionOptions(\n\toptions: StreamableHttpTransportOptions\n): SessionRetentionOptions | null {\n\tconst { maxSessions, sessionIdleTimeoutMs, sessionSweepIntervalMs } = options;\n\tif (\n\t\tmaxSessions === undefined &&\n\t\tsessionIdleTimeoutMs === undefined &&\n\t\tsessionSweepIntervalMs === undefined\n\t) {\n\t\treturn null;\n\t}\n\tif (\n\t\tmaxSessions === undefined ||\n\t\t!Number.isFinite(maxSessions) ||\n\t\t!Number.isInteger(maxSessions) ||\n\t\tmaxSessions <= 0 ||\n\t\tsessionIdleTimeoutMs === undefined ||\n\t\t!Number.isFinite(sessionIdleTimeoutMs) ||\n\t\t!Number.isInteger(sessionIdleTimeoutMs) ||\n\t\tsessionIdleTimeoutMs <= 0 ||\n\t\tsessionSweepIntervalMs === undefined ||\n\t\t!Number.isFinite(sessionSweepIntervalMs) ||\n\t\t!Number.isInteger(sessionSweepIntervalMs) ||\n\t\tsessionSweepIntervalMs <= 0\n\t) {\n\t\tthrow new TypeError(\n\t\t\t'maxSessions, sessionIdleTimeoutMs, and sessionSweepIntervalMs must be provided together as positive integers'\n\t\t);\n\t}\n\treturn {\n\t\tmaxSessions,\n\t\tsessionIdleTimeoutMs,\n\t\tsessionSweepIntervalMs,\n\t};\n}\n\n/**\n * Internal session state for stateful mode.\n */\ninterface SessionState {\n\t/** Unique session identifier */\n\tid: SessionId;\n\t/** Timestamp when the session was created */\n\tcreatedAt: number;\n\t/** Timestamp of the last activity */\n\tlastActivityAt: number;\n\tacceptedPostCount: number;\n}\n\ntype SessionError = {\n\treadonly statusCode: number;\n\treadonly code: number;\n\treadonly message: string;\n};\n\ntype AcceptedPostSession = {\n\treadonly id: string | undefined;\n\treadonly state: SessionState | null;\n};\n\n/**\n * Streamable HTTP Transport for MCP server.\n *\n * This transport implements the MCP Streamable HTTP specification,\n * providing JSON-RPC over HTTP with optional session management.\n *\n * @remarks\n * **Security Features (inherited from BaseTransport):**\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 * - Host header validation\n *\n * **MCP Streamable HTTP Spec Compliance:**\n * - POST /mcp — JSON-RPC method calls\n * - Mcp-Session-Id header for session management\n * - Content-Type: application/json for JSON-RPC responses\n *\n * **HTTP Status Code Mapping:**\n * - 200: Success (JSON-RPC response)\n * - 202: Accepted (JSON-RPC notification, no response body)\n * - 204: CORS Preflight (empty body)\n * - 400: Bad Request (invalid JSON, invalid session ID)\n * - 403: Forbidden (invalid CORS, invalid host)\n * - 404: Not Found\n * - 405: Method Not Allowed\n * - 413: Payload Too Large\n * - 429: Too Many Requests\n * - 500: Internal Server Error\n * - 503: Server Not Ready / Shutting Down\n */\nexport class StreamableHttpTransport extends BaseTransport implements ITransport {\n\tget kind(): TransportKind {\n\t\treturn 'streamable-http';\n\t}\n\tprivate _server: Server | null = null;\n\tprivate _mcpServer: McpServer | null = null;\n\tprivate _path: string;\n\tprivate _stateful: boolean;\n\tprivate _sessionIdGenerator: () => string;\n\tprivate _sessions: Map<SessionId, SessionState> = new Map();\n\tprivate _requestCount: number = 0;\n\tprivate _activeRequests: number = 0;\n\tprivate _bodySizeLimitEnabled: boolean;\n\tprivate _maxBodySize: number;\n\tprivate _requestTimeout: number;\n\tprivate _metrics?: IMetrics;\n\tprivate _metricsProvider: (() => string) | null;\n\tprivate readonly _lifecycleFailureReporter: LifecycleFailureReporter;\n\tprivate readonly _acceptedWork: AcceptedWorkTracker;\n\tprivate readonly _preDispatch = new PreDispatchTracker();\n\tprivate readonly _sessionRetention: SessionRetentionOptions | null;\n\tprivate _sessionSweepIntervalId: NodeJS.Timeout | null = null;\n\tprivate _stopPromise: Promise<void> | null = null;\n\n\tconstructor(options: StreamableHttpTransportOptions = {}) {\n\t\tconst sessionRetention = parseSessionRetentionOptions(options);\n\t\tsuper(options);\n\n\t\tthis._path = options.path ?? '/mcp';\n\t\tthis._stateful = options.stateful ?? true;\n\t\tthis._sessionIdGenerator = options.sessionIdGenerator ?? (() => randomUUID());\n\t\tthis._bodySizeLimitEnabled = options.enableBodySizeLimit ?? true;\n\t\tthis._maxBodySize = options.maxBodySize ?? 10 * 1024 * 1024;\n\t\tthis._requestTimeout = options.requestTimeout ?? 30000;\n\t\tthis._metrics = options.metrics;\n\t\tthis._metricsProvider = options.metricsProvider ?? null;\n\t\tthis._sessionRetention = sessionRetention;\n\t\tthis._lifecycleFailureReporter = new LifecycleFailureReporter((error) => {\n\t\t\tthis.log('error', 'Streamable HTTP request lifecycle failed', {\n\t\t\t\terror: getErrorMessage(error),\n\t\t\t});\n\t\t});\n\t\tthis._acceptedWork = new AcceptedWorkTracker(this._lifecycleFailureReporter);\n\t\tif (this._stateful && sessionRetention) {\n\t\t\tthis._sessionSweepIntervalId = setInterval(\n\t\t\t\t() => this._sweepExpiredSessions(),\n\t\t\t\tsessionRetention.sessionSweepIntervalMs\n\t\t\t);\n\t\t\tthis._sessionSweepIntervalId.unref();\n\t\t}\n\t}\n\n\tprivate _requireMcpServer(): McpServer {\n\t\tif (!this._mcpServer) {\n\t\t\tthrow new Error('MCP server not initialized. Did you call connect()?');\n\t\t}\n\t\treturn this._mcpServer;\n\t}\n\n\t/**\n\t * Get number of active sessions (stateful) or active requests (stateless).\n\t */\n\tget clientCount(): number {\n\t\treturn this._stateful ? this._sessions.size : this._activeRequests;\n\t}\n\n\t/**\n\t * Get the total number of requests handled.\n\t */\n\tget requestCount(): number {\n\t\treturn this._requestCount;\n\t}\n\n\t/**\n\t * Connects MCP server to this transport and starts listening.\n\t */\n\tasync connect(mcpServer: McpServer): Promise<void> {\n\t\tthis._mcpServer = mcpServer;\n\t\tconst server = createServer((req, res) => {\n\t\t\tconst responseFinalizer = new ResponseFinalizer(res, this._lifecycleFailureReporter);\n\t\t\tvoid this._handleRequest(req, res).catch((error: unknown) => {\n\t\t\t\tthis._lifecycleFailureReporter.report(error);\n\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\tthis._sendJsonRpcError(response, 500, -32603, 'Internal error', null, {\n\t\t\t\t\t\tdata: getErrorMessage(error),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\tthis._server = server;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst cleanup = (): void => {\n\t\t\t\tserver.off('error', onError);\n\t\t\t\tserver.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(\n\t\t\t\t\t'info',\n\t\t\t\t\t`Streamable HTTP transport listening on http://${this._host}:${this._port}`\n\t\t\t\t);\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tserver.once('error', onError);\n\t\t\tserver.once('listening', onListening);\n\t\t\ttry {\n\t\t\t\tserver.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 _recordRequestMetrics(res: ServerResponse): void {\n\t\tconst startTime = Date.now();\n\t\tthis._metrics?.counter(\n\t\t\t'streamable_http_requests_total',\n\t\t\t1,\n\t\t\t{},\n\t\t\t'Total Streamable HTTP transport requests'\n\t\t);\n\t\tres.once('finish', () => {\n\t\t\tconst durationSeconds = (Date.now() - startTime) / 1000;\n\t\t\tthis._metrics?.histogram('streamable_http_request_duration_seconds', durationSeconds, {});\n\t\t});\n\t}\n\n\t/**\n\t * Validate the request origin and attach CORS headers.\n\t *\n\t * @returns false when the origin is rejected and the 403 has been sent\n\t */\n\tprivate _admitCors(req: IncomingMessage, res: ServerResponse): boolean {\n\t\tif (!this.validateCorsOrigin(req)) {\n\t\t\tthis._sendJsonRpcError(res, 403, -32000, 'Forbidden - invalid origin');\n\t\t\treturn false;\n\t\t}\n\t\tthis.setCorsHeaders(res);\n\t\treturn true;\n\t}\n\n\tprivate _isProbeRoute(req: IncomingMessage, urlPath: string): boolean {\n\t\treturn req.method === 'GET' && (urlPath === '/health' || urlPath === '/ready');\n\t}\n\n\t/**\n\t * Serve GET /health and GET /ready. These run after Host validation and the shutdown check\n\t * but ahead of the rate limiter; they keep CORS origin validation and headers.\n\t */\n\tprivate async _serveProbe(\n\t\treq: IncomingMessage,\n\t\tres: ServerResponse,\n\t\turlPath: string\n\t): Promise<void> {\n\t\tif (!this._admitCors(req, res)) {\n\t\t\treturn;\n\t\t}\n\t\tif (urlPath === '/health') {\n\t\t\tthis._handleHealthCheck(res);\n\t\t} else {\n\t\t\tawait this._handleReadinessCheck(res);\n\t\t}\n\t}\n\n\t/**\n\t * Route and handle incoming HTTP requests.\n\t */\n\tprivate async _handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n\t\tthis._recordRequestMetrics(res);\n\n\t\t// Host validation\n\t\tif (!this.validateHostHeader(req)) {\n\t\t\tthis._sendJsonRpcError(res, 403, -32000, 'Forbidden - invalid host header');\n\t\t\treturn;\n\t\t}\n\n\t\t// Shutdown check\n\t\tif (this.isShuttingDown) {\n\t\t\tthis._sendJsonRpcError(res, 503, -32603, 'Server is shutting down');\n\t\t\treturn;\n\t\t}\n\n\t\t// Parse URL path\n\t\tconst urlPath = req.url?.split('?')[0] ?? '/';\n\n\t\t// Probes (/health, /ready) precede rate limiting so polling never spends the client budget\n\t\tif (this._isProbeRoute(req, urlPath)) {\n\t\t\tawait this._serveProbe(req, res, urlPath);\n\t\t\treturn;\n\t\t}\n\n\t\t// Rate limiting\n\t\tconst clientIp = this.getClientIp(req);\n\t\tif (this.checkRateLimit(clientIp)) {\n\t\t\tres.setHeader('Retry-After', '60');\n\t\t\tthis._sendJsonRpcError(res, 429, -32000, 'Too many requests');\n\t\t\treturn;\n\t\t}\n\n\t\t// CORS validation\n\t\tif (!this._admitCors(req, res)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// CORS preflight\n\t\tif (req.method === 'OPTIONS') {\n\t\t\tres.setHeader('Access-Control-Allow-Headers', 'Content-Type, Mcp-Session-Id');\n\t\t\tres.writeHead(204);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\n\t\t// Metrics endpoint\n\t\tif (req.method === 'GET' && urlPath === '/metrics') {\n\t\t\tthis._handleMetrics(res);\n\t\t\treturn;\n\t\t}\n\n\t\t// MCP endpoint routing\n\t\tif (urlPath === this._path) {\n\t\t\tif (req.method === 'POST') {\n\t\t\t\tconst lease = this._preDispatch.acquire();\n\t\t\t\tif (!lease) {\n\t\t\t\t\tconst responseFinalizer = new ResponseFinalizer(res, this._lifecycleFailureReporter);\n\t\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\t\tthis._sendJsonRpcError(response, 503, -32603, 'Server is shutting down');\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tawait this._handleMcpPost(req, res, lease);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tres.writeHead(405, { 'Content-Type': 'application/json', Allow: 'POST' });\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: null,\n\t\t\t\t\terror: { code: -32601, message: 'Method not allowed' },\n\t\t\t\t})\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// 404 for unknown paths\n\t\tthis._sendJsonRpcError(res, 404, -32601, 'Not Found');\n\t}\n\n\t/**\n\t * Send a JSON-RPC error response.\n\t */\n\tprivate _sendJsonRpcError(\n\t\tres: ServerResponse,\n\t\tstatusCode: number,\n\t\tcode: number,\n\t\tmessage: string,\n\t\tid: unknown = null,\n\t\textra?: Record<string, unknown>\n\t): void {\n\t\tconst error: Record<string, unknown> = { code, message };\n\t\tif (extra) {\n\t\t\tObject.assign(error, extra);\n\t\t}\n\t\tres.writeHead(statusCode, { 'Content-Type': 'application/json' });\n\t\tres.end(JSON.stringify({ jsonrpc: '2.0', id, error }));\n\t}\n\n\tprivate _parseJsonRpcRequest(\n\t\tbody: string,\n\t\tresponseFinalizer: ResponseFinalizer\n\t): Parameters<McpServer['receive']>[0] | null {\n\t\tlet rawBody: unknown;\n\t\ttry {\n\t\t\trawBody = JSON.parse(body) as unknown;\n\t\t} catch {\n\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(response, 200, -32700, 'Parse error');\n\t\t\t});\n\t\t\treturn null;\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\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(\n\t\t\t\t\tresponse,\n\t\t\t\t\t200,\n\t\t\t\t\t-32600,\n\t\t\t\t\t'Invalid Request',\n\t\t\t\t\trawId as string | number | null,\n\t\t\t\t\t{ data: parseResult.issues }\n\t\t\t\t);\n\t\t\t});\n\t\t\treturn null;\n\t\t}\n\t\treturn parseResult.output as Parameters<McpServer['receive']>[0];\n\t}\n\n\t/**\n\t * Handle POST /mcp — JSON-RPC method calls.\n\t *\n\t * Per the MCP Streamable HTTP spec:\n\t * - Accepts JSON-RPC request bodies\n\t * - Returns Mcp-Session-Id header for new sessions (stateful mode)\n\t * - Validates Mcp-Session-Id for existing sessions (stateful mode)\n\t * - Content-Type: application/json for responses\n\t */\n\tprivate async _handleMcpPost(\n\t\treq: IncomingMessage,\n\t\tres: ServerResponse,\n\t\tlease: PreDispatchLease\n\t): Promise<void> {\n\t\tthis._requestCount++;\n\t\tthis._activeRequests++;\n\t\tconst responseFinalizer = new ResponseFinalizer(res, this._lifecycleFailureReporter);\n\t\tlet acceptedSession: SessionState | null = null;\n\t\tconst onAborted = (): void => lease.cancel('peer');\n\t\treq.once('aborted', onAborted);\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(response, 500, -32603, 'Request timeout');\n\t\t\t});\n\t\t\tlease.cancel('timeout');\n\t\t}, this._requestTimeout);\n\t\ttry {\n\t\t\t// Read request body with size limit\n\t\t\tconst body = await readRequestBody(\n\t\t\t\treq,\n\t\t\t\tthis._bodySizeLimitEnabled ? this._maxBodySize : 0,\n\t\t\t\tlease.signal\n\t\t\t);\n\t\t\tif (body === null) {\n\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\tthis._sendJsonRpcError(response, 413, -32000, 'Request body too large');\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst jsonRpcRequest = this._parseJsonRpcRequest(body, responseFinalizer);\n\t\t\tif (jsonRpcRequest === null) return;\n\n\t\t\tconst session = this._acceptPostSession(req, responseFinalizer);\n\t\t\tif (!session) return;\n\t\t\tacceptedSession = session.state;\n\n\t\t\t// Check if MCP server is ready\n\t\t\tif (!this._mcpServer) {\n\t\t\t\tconst requestId = 'id' in jsonRpcRequest ? (jsonRpcRequest.id ?? null) : null;\n\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\tthis._sendJsonRpcError(response, 503, -32603, 'Server not ready', requestId);\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\treq.off('aborted', onAborted);\n\t\t\tconst acceptedWork = this._acceptedWork.transfer(lease, () =>\n\t\t\t\tthis._receiveAndFinalize(jsonRpcRequest, session.id, responseFinalizer).catch(\n\t\t\t\t\t(error: unknown) => {\n\t\t\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\t\t\tthis._sendJsonRpcError(response, 200, -32603, 'Internal error', null, {\n\t\t\t\t\t\t\t\tdata: getErrorMessage(error),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t);\n\t\t\tawait acceptedWork;\n\t\t} catch (error) {\n\t\t\tif (lease.signal.aborted) {\n\t\t\t\tif (lease.cancellationReason === 'shutdown') {\n\t\t\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\t\t\tthis._sendJsonRpcError(response, 503, -32603, 'Server is shutting down');\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(response, 200, -32603, 'Internal error', null, {\n\t\t\t\t\tdata: getErrorMessage(error),\n\t\t\t\t});\n\t\t\t});\n\t\t} finally {\n\t\t\treq.off('aborted', onAborted);\n\t\t\tlease.release();\n\t\t\tif (acceptedSession) acceptedSession.acceptedPostCount--;\n\t\t\tclearTimeout(timeout);\n\t\t\tthis._activeRequests--;\n\t\t}\n\t}\n\n\tprivate _acceptPostSession(\n\t\treq: IncomingMessage,\n\t\tresponseFinalizer: ResponseFinalizer\n\t): AcceptedPostSession | null {\n\t\tif (!this._stateful) return { id: undefined, state: null };\n\t\tif (this.isShuttingDown) {\n\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(response, 503, -32603, 'Server is shutting down');\n\t\t\t});\n\t\t\treturn null;\n\t\t}\n\t\tconst session = this._resolveSession(req);\n\t\tif (!('state' in session)) {\n\t\t\tresponseFinalizer.finalize((response) => {\n\t\t\t\tthis._sendJsonRpcError(response, session.statusCode, session.code, session.message);\n\t\t\t});\n\t\t\treturn null;\n\t\t}\n\t\tsession.state.acceptedPostCount++;\n\t\treturn { id: session.id, state: session.state };\n\t}\n\n\tprivate async _receiveAndFinalize(\n\t\tjsonRpcRequest: Parameters<McpServer['receive']>[0],\n\t\tsessionId: string | undefined,\n\t\tresponseFinalizer: ResponseFinalizer\n\t): Promise<void> {\n\t\tconst owner = this._stateful ? (sessionId ?? randomUUID()) : randomUUID();\n\t\tconst response = await runWithContext({ requestId: randomUUID(), owner }, () =>\n\t\t\tthis._requireMcpServer().receive(jsonRpcRequest, { sessionInfo: {} })\n\t\t);\n\t\tconst responseHeaders: Record<string, string> = { 'Content-Type': 'application/json' };\n\t\tif (sessionId) responseHeaders['Mcp-Session-Id'] = sessionId;\n\n\t\tresponseFinalizer.finalize((httpResponse) => {\n\t\t\tif (response) {\n\t\t\t\thttpResponse.writeHead(200, responseHeaders);\n\t\t\t\thttpResponse.end(JSON.stringify(response));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (sessionId) httpResponse.setHeader('Mcp-Session-Id', sessionId);\n\t\t\thttpResponse.writeHead(202);\n\t\t\thttpResponse.end();\n\t\t});\n\t}\n\n\t/**\n\t * Resolve or create a session for a stateful request.\n\t *\n\t * @returns Session ID string on success, or the response error to finalize.\n\t */\n\tprivate _resolveSession(\n\t\treq: IncomingMessage\n\t): { readonly id: SessionId; readonly state: SessionState } | SessionError {\n\t\tconst headerSessionId = this._getSessionIdFromHeader(req);\n\n\t\tif (headerSessionId) {\n\t\t\t// Validate format\n\t\t\tif (!this.validateSessionId(headerSessionId)) {\n\t\t\t\treturn {\n\t\t\t\t\tstatusCode: 400,\n\t\t\t\t\tcode: -32600,\n\t\t\t\t\tmessage: 'Invalid Mcp-Session-Id format',\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Check if session exists\n\t\t\tconst session = this._sessions.get(asSessionId(headerSessionId));\n\t\t\tif (session) {\n\t\t\t\tsession.lastActivityAt = Date.now();\n\t\t\t\treturn { id: session.id, state: session };\n\t\t\t}\n\n\t\t\t// Unknown session ID — per spec, return 404\n\t\t\treturn { statusCode: 404, code: -32001, message: 'Session not found' };\n\t\t}\n\n\t\t// No session header — create new session\n\t\tif (this._sessionRetention && this._sessions.size >= this._sessionRetention.maxSessions) {\n\t\t\treturn { statusCode: 503, code: -32000, message: 'Session capacity reached' };\n\t\t}\n\t\tconst newSessionId = asSessionId(this._sessionIdGenerator());\n\t\tconst now = Date.now();\n\t\tconst sessionState: SessionState = {\n\t\t\tid: newSessionId,\n\t\t\tcreatedAt: now,\n\t\t\tlastActivityAt: now,\n\t\t\tacceptedPostCount: 0,\n\t\t};\n\t\tthis._sessions.set(newSessionId, sessionState);\n\t\tthis.log('info', `New session created: ${newSessionId}`);\n\t\tthis._updateSessionMetrics();\n\n\t\treturn { id: newSessionId, state: sessionState };\n\t}\n\n\tprivate _sweepExpiredSessions(): void {\n\t\tif (!this._sessionRetention) return;\n\t\tconst now = Date.now();\n\t\tfor (const [sessionId, session] of this._sessions) {\n\t\t\tif (\n\t\t\t\tsession.acceptedPostCount === 0 &&\n\t\t\t\tnow - session.lastActivityAt >= this._sessionRetention.sessionIdleTimeoutMs\n\t\t\t) {\n\t\t\t\tthis._disposeSession(sessionId);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _disposeSession(sessionId: SessionId): void {\n\t\tif (!this._sessions.delete(sessionId)) return;\n\t\tthis._updateSessionMetrics();\n\t}\n\n\tprivate _stopSessionSweep(): void {\n\t\tconst interval = this._sessionSweepIntervalId;\n\t\tif (!interval) return;\n\t\tinterval.unref();\n\t\tclearInterval(interval);\n\t\tthis._sessionSweepIntervalId = null;\n\t}\n\n\t/**\n\t * Extract Mcp-Session-Id from request headers.\n\t */\n\tprivate _getSessionIdFromHeader(req: IncomingMessage): string | undefined {\n\t\tconst value = req.headers['mcp-session-id'];\n\t\tif (typeof value === 'string' && value.length > 0) {\n\t\t\treturn value;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Handle GET /metrics endpoint.\n\t */\n\tprivate _handleMetrics(res: ServerResponse): void {\n\t\tif (!this._metricsProvider) {\n\t\t\tres.writeHead(404, { 'Content-Type': 'text/plain' });\n\t\t\tres.end('Not Found');\n\t\t\treturn;\n\t\t}\n\n\t\tres.writeHead(200, { 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8' });\n\t\tres.end(this._metricsProvider());\n\t}\n\n\t/**\n\t * Handle GET /health — Liveness check.\n\t */\n\tprivate _handleHealthCheck(res: ServerResponse): void {\n\t\tconst healthData: Record<string, unknown> = {\n\t\t\tstatus: 'healthy',\n\t\t\trequests: this._requestCount,\n\t\t\tsessions: this._sessions.size,\n\t\t\ttransport: 'streamable-http',\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 GET /ready — Readiness check.\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({\n\t\t\t\t\tstatus: 'ok',\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t\tcomponents: {},\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Update session-related metrics.\n\t */\n\tprivate _updateSessionMetrics(): void {\n\t\tthis._metrics?.gauge(\n\t\t\t'streamable_http_active_sessions',\n\t\t\tthis._sessions.size,\n\t\t\t{},\n\t\t\t'Active Streamable HTTP sessions'\n\t\t);\n\t}\n\n\t/**\n\t * Stop transport server with graceful shutdown.\n\t *\n\t * @param timeout - Maximum time before force-closing HTTP connections (default: 30s)\n\t */\n\tstop(timeout?: number): Promise<void> {\n\t\tif (this._stopPromise) return this._stopPromise;\n\t\tthis._isShuttingDown = true;\n\t\tthis._preDispatch.closeAdmission('shutdown');\n\t\tthis._stopRateLimitCleanup();\n\t\tthis._stopSessionSweep();\n\n\t\tconst shutdownTimeout = timeout ?? 30000;\n\n\t\tfor (const sessionId of this._sessions.keys()) {\n\t\t\tthis._disposeSession(sessionId);\n\t\t}\n\n\t\tconst server = this._server;\n\t\tconst serverClosed = new Promise<void>((resolve, reject) => {\n\t\t\tif (!server?.listening) {\n\t\t\t\tresolve();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet settled = false;\n\t\t\tlet forceClose: NodeJS.Timeout | null = null;\n\t\t\tserver.close((error) => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tif (forceClose) clearTimeout(forceClose);\n\t\t\t\tif (error) {\n\t\t\t\t\treject(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tresolve();\n\t\t\t});\n\t\t\tif (settled) return;\n\t\t\tforceClose = setTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tthis.log('warn', 'Streamable HTTP transport force-closing after timeout');\n\t\t\t\tserver.closeAllConnections();\n\t\t\t\tresolve();\n\t\t\t}, shutdownTimeout);\n\t\t});\n\t\tconst stopPromise = Promise.all([\n\t\t\tserverClosed,\n\t\t\tthis._preDispatch.join().then(() => this._acceptedWork.join()),\n\t\t]).then(() => {\n\t\t\tthis.log('info', 'Streamable HTTP transport stopped');\n\t\t});\n\t\tthis._stopPromise = stopPromise;\n\t\tvoid stopPromise.catch(() => {\n\t\t\tif (this._stopPromise === stopPromise) this._stopPromise = null;\n\t\t});\n\t\treturn stopPromise;\n\t}\n}\n\n/**\n * Create a Streamable HTTP transport with given options.\n *\n * @param options - Transport configuration\n * @returns A configured Streamable HTTP transport\n *\n * @example\n * ```typescript\n * const transport = createStreamableHttpTransport({ port: 3000, stateful: true });\n * await transport.connect(server);\n * ```\n */\nexport function createStreamableHttpTransport(\n\toptions: StreamableHttpTransportOptions = {}\n): StreamableHttpTransport {\n\treturn new StreamableHttpTransport(options);\n}\n"],"names":["parseSessionRetentionOptions","options","maxSessions","sessionIdleTimeoutMs","sessionSweepIntervalMs","undefined","Number","TypeError","StreamableHttpTransport","BaseTransport","Map","PreDispatchTracker","sessionRetention","randomUUID","LifecycleFailureReporter","error","getErrorMessage","AcceptedWorkTracker","setInterval","Error","mcpServer","server","createServer","req","res","responseFinalizer","ResponseFinalizer","response","Promise","resolve","reject","cleanup","onError","onListening","startTime","Date","durationSeconds","urlPath","clientIp","lease","JSON","statusCode","code","message","id","extra","Object","body","rawBody","parseResult","safeParse","JsonRpcRequestSchema","rawId","acceptedSession","onAborted","timeout","setTimeout","readRequestBody","jsonRpcRequest","session","requestId","acceptedWork","clearTimeout","sessionId","owner","runWithContext","responseHeaders","httpResponse","headerSessionId","asSessionId","newSessionId","now","sessionState","interval","clearInterval","value","healthData","liveness","readiness","shutdownTimeout","serverClosed","settled","forceClose","stopPromise","createStreamableHttpTransport"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iworkforces/tracelattice",
3
- "version": "2.3.5",
3
+ "version": "2.4.0",
4
4
  "description": "Semantic Sequential Thinking Layer For AI Agents.",
5
5
  "type": "module",
6
6
  "main": "dist/lib.js",
@@ -36,7 +36,7 @@
36
36
  "format:check": "prettier --check \"src/**/*.ts\" \"*.{json,md}\"",
37
37
  "type-check": "tsc --noEmit",
38
38
  "verify:library": "npm run type-check && npm run lint && npm run build && npm run test:coverage",
39
- "verify:native": "npm ls better-sqlite3@13.0.3 --depth=0 && npm run test:native",
39
+ "verify:native": "npm ls better-sqlite3@13.1.1 --depth=0 && npm run test:native",
40
40
  "verify:packed": "node scripts/verify-packed-cli.mjs",
41
41
  "verify:release": "npm run verify:library && npm run verify:native && npm run verify:packed",
42
42
  "prepublishOnly": "npm run verify:release"
@@ -72,36 +72,36 @@
72
72
  },
73
73
  "homepage": "https://github.com/iworkforces/TraceLattice#readme",
74
74
  "dependencies": {
75
- "@tmcp/adapter-valibot": "^0.1.6",
76
- "@tmcp/transport-stdio": "^0.5.0",
77
- "@tsconfig/node26": "^26.0.1",
75
+ "@tmcp/adapter-valibot": "^0.1.7",
76
+ "@tmcp/transport-stdio": "^0.5.1",
77
+ "@tsconfig/node26": "^26.0.2",
78
78
  "@valibot/to-json-schema": "^1.8.0",
79
79
  "chalk": "^6.0.1",
80
- "chokidar": "^5.0.0",
80
+ "chokidar": "^6.0.0",
81
81
  "or": "^0.2.0",
82
- "tmcp": "^1.20.0",
82
+ "tmcp": "^1.20.1",
83
83
  "valibot": "^1.5.0",
84
84
  "yaml": "^2.9.1"
85
85
  },
86
86
  "devDependencies": {
87
87
  "@changesets/cli": "^3.0.3",
88
88
  "@eslint/js": "^10.0.1",
89
- "@rsbuild/core": "^2.2.12",
90
- "@rslib/core": "^1.0.3",
91
- "@types/node": "^26.6.4",
92
- "@typescript-eslint/eslint-plugin": "^8.71.1",
93
- "@typescript-eslint/parser": "^8.71.1",
94
- "@vitest/coverage-v8": "^5.0.3",
95
- "better-sqlite3": "13.0.3",
96
- "eslint": "^10.12.0",
97
- "globals": "^17.13.0",
98
- "prettier": "^3.9.9",
89
+ "@rsbuild/core": "^2.3.2",
90
+ "@rslib/core": "^1.0.7",
91
+ "@types/node": "^26.6.6",
92
+ "@typescript-eslint/eslint-plugin": "^8.72.2",
93
+ "@typescript-eslint/parser": "^8.72.2",
94
+ "@vitest/coverage-v8": "^5.1.0",
95
+ "better-sqlite3": "13.1.1",
96
+ "eslint": "^10.14.0",
97
+ "globals": "^17.14.0",
98
+ "prettier": "^3.10.1",
99
99
  "typescript": "npm:@typescript/typescript6@^6.0.2",
100
- "typescript-eslint": "^8.71.1",
101
- "vitest": "^5.0.3"
100
+ "typescript-eslint": "^8.72.2",
101
+ "vitest": "^5.1.0"
102
102
  },
103
103
  "allowScripts": {
104
104
  "fsevents@2.3.3": true,
105
- "better-sqlite3@13.0.3": true
105
+ "better-sqlite3@13.1.1": true
106
106
  }
107
107
  }