tracelattice 1.3.2 → 1.3.3

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 (148) hide show
  1. package/README.md +25 -25
  2. package/dist/ServerConfig.d.ts +2 -23
  3. package/dist/ServerConfig.d.ts.map +1 -1
  4. package/dist/ServerConfig.js.map +1 -1
  5. package/dist/__tests__/eval/fixtures/scenarios.d.ts.map +1 -1
  6. package/dist/__tests__/helpers/factories.d.ts +13 -1
  7. package/dist/__tests__/helpers/factories.d.ts.map +1 -1
  8. package/dist/cache/DiscoveryCache.d.ts +1 -1
  9. package/dist/cache/DiscoveryCache.d.ts.map +1 -1
  10. package/dist/cache/DiscoveryCache.js.map +1 -1
  11. package/dist/cli.js +3483 -8
  12. package/dist/config/ConfigLoader.d.ts +2 -2
  13. package/dist/config/ConfigLoader.d.ts.map +1 -1
  14. package/dist/config/ConfigLoader.js +6 -4
  15. package/dist/config/ConfigLoader.js.map +1 -1
  16. package/dist/contracts/PersistenceBackend.d.ts.map +1 -0
  17. package/dist/contracts/features.d.ts +39 -0
  18. package/dist/contracts/features.d.ts.map +1 -0
  19. package/dist/contracts/features.js +15 -0
  20. package/dist/contracts/features.js.map +1 -0
  21. package/dist/contracts/ids.d.ts +58 -0
  22. package/dist/contracts/ids.d.ts.map +1 -0
  23. package/dist/contracts/ids.js +31 -0
  24. package/dist/contracts/ids.js.map +1 -0
  25. package/dist/contracts/interfaces.d.ts +6 -3
  26. package/dist/contracts/interfaces.d.ts.map +1 -1
  27. package/dist/contracts/strategy.d.ts +2 -2
  28. package/dist/contracts/strategy.d.ts.map +1 -1
  29. package/dist/contracts/suspension.d.ts +3 -2
  30. package/dist/contracts/suspension.d.ts.map +1 -1
  31. package/dist/contracts/transport.d.ts +25 -0
  32. package/dist/contracts/transport.d.ts.map +1 -0
  33. package/dist/core/HistoryManager.d.ts +2 -3
  34. package/dist/core/HistoryManager.d.ts.map +1 -1
  35. package/dist/core/HistoryManager.js.map +1 -1
  36. package/dist/core/IHistoryManager.d.ts +10 -0
  37. package/dist/core/IHistoryManager.d.ts.map +1 -1
  38. package/dist/core/IThoughtFormatter.d.ts +51 -0
  39. package/dist/core/IThoughtFormatter.d.ts.map +1 -0
  40. package/dist/core/IThoughtFormatter.js +1 -0
  41. package/dist/core/InputNormalizer.d.ts.map +1 -1
  42. package/dist/core/InputNormalizer.js +4 -3
  43. package/dist/core/InputNormalizer.js.map +1 -1
  44. package/dist/core/PersistenceBuffer.d.ts +1 -1
  45. package/dist/core/PersistenceBuffer.d.ts.map +1 -1
  46. package/dist/core/PersistenceBuffer.js.map +1 -1
  47. package/dist/core/ThoughtFormatter.d.ts +2 -1
  48. package/dist/core/ThoughtFormatter.d.ts.map +1 -1
  49. package/dist/core/ThoughtFormatter.js +3 -0
  50. package/dist/core/ThoughtFormatter.js.map +1 -1
  51. package/dist/core/ThoughtProcessor.d.ts +2 -2
  52. package/dist/core/ThoughtProcessor.d.ts.map +1 -1
  53. package/dist/core/ThoughtProcessor.js +8 -3
  54. package/dist/core/ThoughtProcessor.js.map +1 -1
  55. package/dist/core/compression/CompressionService.js +3 -3
  56. package/dist/core/compression/CompressionService.js.map +1 -1
  57. package/dist/core/compression/Summary.d.ts +4 -3
  58. package/dist/core/compression/Summary.d.ts.map +1 -1
  59. package/dist/core/graph/Edge.d.ts +11 -4
  60. package/dist/core/graph/Edge.d.ts.map +1 -1
  61. package/dist/core/graph/EdgeEmitter.js +5 -5
  62. package/dist/core/graph/EdgeEmitter.js.map +1 -1
  63. package/dist/core/reasoning/strategies/StrategyFactory.d.ts +1 -1
  64. package/dist/core/reasoning/strategies/StrategyFactory.d.ts.map +1 -1
  65. package/dist/core/reasoning/strategies/StrategyFactory.js.map +1 -1
  66. package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts.map +1 -1
  67. package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js +5 -0
  68. package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js.map +1 -1
  69. package/dist/core/reasoning.d.ts +8 -1
  70. package/dist/core/reasoning.d.ts.map +1 -1
  71. package/dist/core/step.d.ts +5 -0
  72. package/dist/core/step.d.ts.map +1 -1
  73. package/dist/core/thought.d.ts +4 -3
  74. package/dist/core/thought.d.ts.map +1 -1
  75. package/dist/core/tools/InMemorySuspensionStore.d.ts +3 -1
  76. package/dist/core/tools/InMemorySuspensionStore.d.ts.map +1 -1
  77. package/dist/core/tools/InMemorySuspensionStore.js +2 -2
  78. package/dist/core/tools/InMemorySuspensionStore.js.map +1 -1
  79. package/dist/di/Container.d.ts +6 -3
  80. package/dist/di/Container.d.ts.map +1 -1
  81. package/dist/di/Container.js.map +1 -1
  82. package/dist/di/ServiceRegistry.d.ts +3 -3
  83. package/dist/di/ServiceRegistry.d.ts.map +1 -1
  84. package/dist/errors.d.ts +36 -2
  85. package/dist/errors.d.ts.map +1 -1
  86. package/dist/errors.js +49 -22
  87. package/dist/errors.js.map +1 -1
  88. package/dist/health/HealthChecker.d.ts +1 -1
  89. package/dist/health/HealthChecker.d.ts.map +1 -1
  90. package/dist/health/HealthChecker.js.map +1 -1
  91. package/dist/lib.d.ts +60 -2
  92. package/dist/lib.d.ts.map +1 -1
  93. package/dist/lib.js.map +1 -1
  94. package/dist/persistence/FilePersistence.d.ts +2 -2
  95. package/dist/persistence/FilePersistence.d.ts.map +1 -1
  96. package/dist/persistence/FilePersistence.js.map +1 -1
  97. package/dist/persistence/MemoryPersistence.d.ts +1 -1
  98. package/dist/persistence/MemoryPersistence.d.ts.map +1 -1
  99. package/dist/persistence/MemoryPersistence.js.map +1 -1
  100. package/dist/persistence/PersistenceFactory.d.ts +1 -1
  101. package/dist/persistence/PersistenceFactory.d.ts.map +1 -1
  102. package/dist/persistence/PersistenceFactory.js.map +1 -1
  103. package/dist/persistence/SqlitePersistence.d.ts +1 -1
  104. package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
  105. package/dist/persistence/SqlitePersistence.js.map +1 -1
  106. package/dist/pool/ConnectionPool.d.ts +11 -13
  107. package/dist/pool/ConnectionPool.d.ts.map +1 -1
  108. package/dist/pool/ConnectionPool.js.map +1 -1
  109. package/dist/pool/IConnectionPool.d.ts +100 -0
  110. package/dist/pool/IConnectionPool.d.ts.map +1 -0
  111. package/dist/pool/IConnectionPool.js +1 -0
  112. package/dist/registry/BaseRegistry.d.ts +1 -1
  113. package/dist/registry/BaseRegistry.d.ts.map +1 -1
  114. package/dist/registry/BaseRegistry.js.map +1 -1
  115. package/dist/schema.d.ts.map +1 -1
  116. package/dist/schema.js.map +1 -1
  117. package/dist/transport/BaseTransport.d.ts +3 -2
  118. package/dist/transport/BaseTransport.d.ts.map +1 -1
  119. package/dist/transport/BaseTransport.js +1 -1
  120. package/dist/transport/BaseTransport.js.map +1 -1
  121. package/dist/transport/HttpTransport.d.ts +4 -2
  122. package/dist/transport/HttpTransport.d.ts.map +1 -1
  123. package/dist/transport/HttpTransport.js +4 -1
  124. package/dist/transport/HttpTransport.js.map +1 -1
  125. package/dist/transport/SseTransport.d.ts +4 -2
  126. package/dist/transport/SseTransport.d.ts.map +1 -1
  127. package/dist/transport/SseTransport.js +3 -0
  128. package/dist/transport/SseTransport.js.map +1 -1
  129. package/dist/transport/StreamableHttpTransport.d.ts +4 -2
  130. package/dist/transport/StreamableHttpTransport.d.ts.map +1 -1
  131. package/dist/transport/StreamableHttpTransport.js +4 -1
  132. package/dist/transport/StreamableHttpTransport.js.map +1 -1
  133. package/dist/types/skill.d.ts +5 -0
  134. package/dist/types/skill.d.ts.map +1 -1
  135. package/dist/types/tool.d.ts +5 -0
  136. package/dist/types/tool.d.ts.map +1 -1
  137. package/package.json +11 -11
  138. package/dist/__tests__/helpers/index.d.ts +0 -3
  139. package/dist/__tests__/helpers/index.d.ts.map +0 -1
  140. package/dist/contracts/index.d.ts +0 -14
  141. package/dist/contracts/index.d.ts.map +0 -1
  142. package/dist/index.d.ts +0 -2
  143. package/dist/index.d.ts.map +0 -1
  144. package/dist/index.js +0 -1
  145. package/dist/persistence/PersistenceBackend.d.ts.map +0 -1
  146. /package/dist/{persistence → contracts}/PersistenceBackend.d.ts +0 -0
  147. /package/dist/{persistence → contracts}/PersistenceBackend.js +0 -0
  148. /package/dist/contracts/{index.js → transport.js} +0 -0
package/dist/cli.js CHANGED
@@ -1,5 +1,1054 @@
1
1
  #!/usr/bin/env bun
2
- import*as e from"./lib.js";import*as t from"node:crypto";import*as s from"node:http";import*as i from"node:url";import*as n from"valibot";import{ValibotJsonSchemaAdapter as o}from"@tmcp/adapter-valibot";import{StdioTransport as r}from"@tmcp/transport-stdio";import{readFileSync as a}from"node:fs";import{dirname as l,join as c}from"node:path";import{McpServer as h}from"tmcp";import{AsyncLocalStorage as p}from"node:async_hooks";var d={787(e,t,s){s.d(t,{Ag:()=>o,m_:()=>a,qA:()=>n,u1:()=>l,yM:()=>r});class i extends Error{code;constructor(e,t){super(e),this.code=t,this.name="SequentialThinkingError",Error.captureStackTrace(this,this.constructor)}}class n extends i{constructor(e){super(`Session '${e}' is not active`,"SESSION_NOT_ACTIVE"),this.name="SessionNotActiveError"}}class o extends i{constructor(e){super(`Session not found: ${e}`,"SESSION_NOT_FOUND"),this.name="SessionNotFoundError"}}class r extends i{constructor(e){super(`Max sessions (${e}) reached. Wait for a session to close or increase maxSessions.`,"MAX_SESSIONS_REACHED"),this.name="MaxSessionsReachedError"}}class a extends i{constructor(){super("ConnectionPool has been terminated","POOL_TERMINATED"),this.name="PoolTerminatedError"}}function l(e){return e instanceof Error?e.message:String(e)}},527(e,t,s){s.d(t,{createConnectionPool:()=>r});var i=s(787);class n{_server;_id;_createdAt;_lastActivityAt;_isActiveValue;_timeout;_cleanupTimer=null;_logger;constructor(e,t,s,i){this._server=t,this._id=e,this._createdAt=Date.now(),this._lastActivityAt=this._createdAt,this._isActiveValue=!0,this._timeout=s,this._logger=i,this._startTimeout()}get isActive(){return this._isActiveValue}async process(e){if(!this.isActive)throw new i.qA(this._id);return this._lastActivityAt=Date.now(),this._resetTimeout(),this._server.processThought(e)}getInfo(){return{id:this._id,server:this._server,createdAt:this._createdAt,lastActivityAt:this._lastActivityAt,isActive:this.isActive}}isTimedOut(){return Date.now()-this._lastActivityAt>this._timeout}async close(){this._isActiveValue=!1,this._cleanupTimer&&(clearTimeout(this._cleanupTimer),this._cleanupTimer=null),this._server.stop()}_startTimeout(){this._cleanupTimer&&clearTimeout(this._cleanupTimer),this._cleanupTimer=setTimeout(()=>{this.isTimedOut()&&(this._logger.warn(`Session ${this._id} timed out, closing`),this.close().catch(e=>{this._logger.error(`Error closing timed out session ${this._id}:`,e)}))},this._timeout)}_resetTimeout(){this._startTimeout()}}class o{_sessions=new Map;_createSessionLock=null;_maxSessions;_sessionTimeout;_autoCleanup;_cleanupInterval;_cleanupTimerId=null;_terminated=!1;_logger;_serverFactory;constructor(e={}){this._maxSessions=e.maxSessions??100,this._sessionTimeout=e.sessionTimeout??3e5,this._autoCleanup=e.autoCleanup??!0,this._cleanupInterval=e.cleanupInterval??6e4,this._serverFactory=e.serverFactory??null,this._logger=e.logger??this._createNoopLogger(),this._autoCleanup&&this._startCleanup()}_createNoopLogger(){return{info:()=>{},warn:()=>{},error:()=>{},debug:()=>{},setLevel:()=>{},getLevel:()=>"info"}}async createSession(){let e;for(;this._createSessionLock;)await this._createSessionLock;if(this._terminated)throw new i.m_;if(this._sessions.size>=this._maxSessions)throw new i.yM(this._maxSessions);if(!this._serverFactory)throw Error("ConnectionPool requires a serverFactory option to create sessions");this._createSessionLock=new Promise(t=>{e=t});try{let e=`session_${Date.now()}_${Math.random().toString(36).substring(2,11)}`,t=await this._serverFactory(),s=new n(e,t,this._sessionTimeout,this._logger);return this._sessions.set(e,s),this._logger.info(`Created session ${e} (${this._sessions.size}/${this._maxSessions} active sessions)`),e}finally{e(),this._createSessionLock=null}}async process(e,t){let s=this._sessions.get(e);if(!s)throw new i.Ag(e);return s.process(t)}async closeSession(e){let t=this._sessions.get(e);if(!t)throw new i.Ag(e);await t.close(),this._sessions.delete(e),this._logger.info(`Closed session ${e} (${this._sessions.size}/${this._maxSessions} active sessions)`)}getSessionInfo(e){var t;return null==(t=this._sessions.get(e))?void 0:t.getInfo()}getActiveSessions(){return Array.from(this._sessions.values()).filter(e=>e.isActive).map(e=>e.getInfo())}getStats(){let e=this.getActiveSessions();return{totalSessions:this._sessions.size,activeSessions:e.length,maxSessions:this._maxSessions,cleanupEnabled:this._autoCleanup,sessionTimeout:this._sessionTimeout}}_startCleanup(){null!==this._cleanupTimerId&&clearInterval(this._cleanupTimerId),this._cleanupTimerId=setInterval(()=>{this._cleanupTimedOutSessions()},this._cleanupInterval)}_cleanupTimedOutSessions(){let e=0;for(let[t,s]of this._sessions.entries())s.isTimedOut()&&(s.close().catch(e=>{this._logger.error(`Error closing timed out session ${t}:`,e)}),this._sessions.delete(t),e++);e>0&&this._logger.info(`Cleaned ${e} timed-out sessions (${this._sessions.size}/${this._maxSessions} active sessions)`)}async terminate(){if(this._terminated)return;this._terminated=!0,null!==this._cleanupTimerId&&(clearInterval(this._cleanupTimerId),this._cleanupTimerId=null);let e=Array.from(this._sessions.values()).map(e=>e.close().catch(t=>{this._logger.error(`Error closing session ${e.getInfo().id}:`,t)}));await Promise.all(e),this._sessions.clear(),this._logger.info("ConnectionPool terminated")}async dispose(){await this.terminate()}isRunning(){return!this._terminated}}function r(e){return new o(e)}},555(e,t,s){s.d(t,{Uv:()=>d,ZK:()=>h,iV:()=>p});var i=s(821);let n=`A detailed tool for dynamic and reflective problem-solving through thoughts.
2
+ import * as __rspack_external__lib_js_262c9725 from "./lib.js";
3
+ import * as __rspack_external_node_crypto_9ba42079 from "node:crypto";
4
+ import * as __rspack_external_node_http_2dc67212 from "node:http";
5
+ import * as __rspack_external_node_url_e96de089 from "node:url";
6
+ import * as __rspack_external_valibot from "valibot";
7
+ import { ValibotJsonSchemaAdapter } from "@tmcp/adapter-valibot";
8
+ import { StdioTransport } from "@tmcp/transport-stdio";
9
+ import { readFileSync } from "node:fs";
10
+ import { dirname, join } from "node:path";
11
+ import { McpServer } from "tmcp";
12
+ import { AsyncLocalStorage } from "node:async_hooks";
13
+ var __webpack_modules__ = ({
14
+ 937(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
15
+ __webpack_require__.d(__webpack_exports__, {
16
+ Ag: () => (SessionNotFoundError),
17
+ m_: () => (PoolTerminatedError),
18
+ qA: () => (SessionNotActiveError),
19
+ u1: () => (getErrorMessage),
20
+ yM: () => (MaxSessionsReachedError)
21
+ });
22
+ /**
23
+ * Custom error types for the TraceLattice server.
24
+ *
25
+ * This module defines a hierarchy of error classes for handling various
26
+ * error conditions that can occur in the sequential thinking server.
27
+ * All errors extend the base `SequentialThinkingError` class with
28
+ * specific error codes for programmatic handling.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * import { ToolNotFoundError, SkillDiscoveryError } from './errors.js';
33
+ *
34
+ * // Throw a tool not found error
35
+ * throw new ToolNotFoundError('my-tool');
36
+ *
37
+ * // Catch and handle specific errors
38
+ * try {
39
+ * await discoverSkills(dir);
40
+ * } catch (error) {
41
+ * if (error instanceof SkillDiscoveryError) {
42
+ * console.error(`Failed to discover skills: ${error.message}`);
43
+ * console.error(`Error code: ${error.code}`);
44
+ * }
45
+ * }
46
+ * ```
47
+ * @module errors
48
+ */ /**
49
+ * All known error codes as a const object for exhaustive switching.
50
+ */ const ERROR_CODES = {
51
+ CONFIGURATION_ERROR: 'CONFIGURATION_ERROR',
52
+ TOOL_NOT_FOUND: 'TOOL_NOT_FOUND',
53
+ SKILL_NOT_FOUND: 'SKILL_NOT_FOUND',
54
+ INVALID_THOUGHT: 'INVALID_THOUGHT',
55
+ SKILL_DISCOVERY_FAILED: 'SKILL_DISCOVERY_FAILED',
56
+ HISTORY_LIMIT_EXCEEDED: 'HISTORY_LIMIT_EXCEEDED',
57
+ DUPLICATE_SKILL: 'DUPLICATE_SKILL',
58
+ INVALID_SKILL: 'INVALID_SKILL',
59
+ DUPLICATE_TOOL: 'DUPLICATE_TOOL',
60
+ INVALID_TOOL: 'INVALID_TOOL',
61
+ SESSION_NOT_ACTIVE: 'SESSION_NOT_ACTIVE',
62
+ SESSION_NOT_FOUND: 'SESSION_NOT_FOUND',
63
+ MAX_SESSIONS_REACHED: 'MAX_SESSIONS_REACHED',
64
+ POOL_TERMINATED: 'POOL_TERMINATED',
65
+ VALIDATION_ERROR: 'VALIDATION_ERROR',
66
+ INVALID_EDGE: 'INVALID_EDGE',
67
+ CYCLE_DETECTED: 'CYCLE_DETECTED',
68
+ SUSPENSION_NOT_FOUND: 'SUSPENSION_NOT_FOUND',
69
+ SUSPENSION_EXPIRED: 'SUSPENSION_EXPIRED',
70
+ INVALID_TOOL_CALL: 'INVALID_TOOL_CALL',
71
+ INVALID_BACKTRACK: 'INVALID_BACKTRACK',
72
+ DUPLICATE_SUMMARY: 'DUPLICATE_SUMMARY'
73
+ };
74
+ /**
75
+ * Base error class for all Sequential Thinking server errors.
76
+ *
77
+ * This error extends the native `Error` class and adds a `code` property
78
+ * for programmatic error identification and handling. All specific error
79
+ * types in the system extend this base class.
80
+ *
81
+ * @remarks
82
+ * **Error Codes:**
83
+ * - `TOOL_NOT_FOUND` - A requested tool was not found
84
+ * - `SKILL_NOT_FOUND` - A requested skill was not found
85
+ * - `INVALID_THOUGHT` - Thought validation failed
86
+ * - `SKILL_DISCOVERY_FAILED` - Skill discovery operation failed
87
+ * - `HISTORY_LIMIT_EXCEEDED` - History size limit was exceeded
88
+ * - `INVALID_EDGE` - An invalid edge operation was attempted
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * // Throw a custom sequential thinking error
93
+ * throw new SequentialThinkingError('Custom error message', 'CUSTOM_CODE');
94
+ *
95
+ * // Check if an error is a SequentialThinkingError
96
+ * if (error instanceof SequentialThinkingError) {
97
+ * console.error(`Error [${error.code}]: ${error.message}`);
98
+ * }
99
+ * ```
100
+ */ class SequentialThinkingError extends Error {
101
+ /** The error code for programmatic identification. */ code;
102
+ /**
103
+ * Creates a new SequentialThinkingError.
104
+ *
105
+ * @param message - Human-readable error message
106
+ * @param code - Error code for programmatic handling
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * const error = new SequentialThinkingError(
111
+ * 'Something went wrong',
112
+ * 'CUSTOM_ERROR'
113
+ * );
114
+ * console.log(error.code); // 'CUSTOM_ERROR'
115
+ * ```
116
+ */ constructor(message, code){
117
+ super(message);
118
+ this.code = code;
119
+ this.name = 'SequentialThinkingError';
120
+ Error.captureStackTrace(this, this.constructor);
121
+ }
122
+ }
123
+ class ConfigurationError extends SequentialThinkingError {
124
+ constructor(message){
125
+ super(message, ERROR_CODES.CONFIGURATION_ERROR);
126
+ this.name = 'ConfigurationError';
127
+ }
128
+ }
129
+ /**
130
+ * Error thrown when a requested tool is not found in the registry.
131
+ *
132
+ * This error is thrown when attempting to retrieve, update, or delete
133
+ * a tool that doesn't exist in the tool registry.
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * const tool = registry.getTool('non-existent-tool');
138
+ * if (!tool) {
139
+ * throw new ToolNotFoundError('non-existent-tool');
140
+ * }
141
+ * ```
142
+ */ class ToolNotFoundError extends SequentialThinkingError {
143
+ /**
144
+ * Creates a new ToolNotFoundError.
145
+ *
146
+ * @param toolName - The name of the tool that was not found
147
+ * @param action - Optional action being performed (e.g., 'remove', 'update')
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * throw new ToolNotFoundError('my-custom-tool');
152
+ * // Error: tool 'my-custom-tool' not found
153
+ *
154
+ * throw new ToolNotFoundError('my-custom-tool', 'remove');
155
+ * // Error: tool 'my-custom-tool' not found, cannot remove
156
+ * // Code: TOOL_NOT_FOUND
157
+ * ```
158
+ */ constructor(toolName, action){
159
+ const message = action ? `Tool '${toolName}' not found, cannot ${action}` : `Tool '${toolName}' not found`;
160
+ super(message, ERROR_CODES.TOOL_NOT_FOUND);
161
+ this.name = 'ToolNotFoundError';
162
+ }
163
+ }
164
+ /**
165
+ * Error thrown when a requested skill is not found in the registry.
166
+ *
167
+ * This error is thrown when attempting to retrieve, update, or delete
168
+ * a skill that doesn't exist in the skill registry.
169
+ *
170
+ * @example
171
+ * ```typescript
172
+ * const skill = registry.getSkill('non-existent-skill');
173
+ * if (!skill) {
174
+ * throw new SkillNotFoundError('non-existent-skill');
175
+ * }
176
+ * ```
177
+ */ class SkillNotFoundError extends SequentialThinkingError {
178
+ /**
179
+ * Creates a new SkillNotFoundError.
180
+ *
181
+ * @param skillName - The name of the skill that was not found
182
+ * @param action - Optional action being performed (e.g., 'remove', 'update')
183
+ *
184
+ * @example
185
+ * ```typescript
186
+ * throw new SkillNotFoundError('my-custom-skill');
187
+ * // Error: skill 'my-custom-skill' not found
188
+ *
189
+ * throw new SkillNotFoundError('my-custom-skill', 'remove');
190
+ * // Error: skill 'my-custom-skill' not found, cannot remove
191
+ * // Code: SKILL_NOT_FOUND
192
+ * ```
193
+ */ constructor(skillName, action){
194
+ const message = action ? `Skill '${skillName}' not found, cannot ${action}` : `Skill '${skillName}' not found`;
195
+ super(message, ERROR_CODES.SKILL_NOT_FOUND);
196
+ this.name = 'SkillNotFoundError';
197
+ }
198
+ }
199
+ /**
200
+ * Error thrown when thought validation fails.
201
+ *
202
+ * This error is thrown when a thought fails validation, typically due to
203
+ * invalid values, missing required fields, or constraint violations.
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * // Validate thought number
208
+ * if (thought.thought_number < 1) {
209
+ * throw new InvalidThoughtError(thought.thought_number, 'thought_number must be >= 1');
210
+ * }
211
+ * ```
212
+ */ class InvalidThoughtError extends SequentialThinkingError {
213
+ /**
214
+ * Creates a new InvalidThoughtError.
215
+ *
216
+ * @param thoughtNumber - The thought number that failed validation
217
+ * @param reason - Human-readable explanation of why validation failed
218
+ *
219
+ * @example
220
+ * ```typescript
221
+ * throw new InvalidThoughtError(5, 'thought_number exceeds total_thoughts');
222
+ * // Error: Invalid thought 5: thought_number exceeds total_thoughts
223
+ * // Code: INVALID_THOUGHT
224
+ * ```
225
+ */ constructor(thoughtNumber, reason){
226
+ super(`Invalid thought ${thoughtNumber}: ${reason}`, ERROR_CODES.INVALID_THOUGHT);
227
+ this.name = 'InvalidThoughtError';
228
+ }
229
+ }
230
+ /**
231
+ * Error thrown when skill discovery fails.
232
+ *
233
+ * This error is thrown when the skill discovery process encounters an issue,
234
+ * such as filesystem errors, invalid skill files, or parsing failures.
235
+ *
236
+ * @remarks
237
+ * The original error that caused the discovery failure is preserved in the
238
+ * `cause` property for debugging purposes.
239
+ *
240
+ * @example
241
+ * ```typescript
242
+ * try {
243
+ * await discoverSkills('./skills');
244
+ * } catch (error) {
245
+ * throw new SkillDiscoveryError('./skills', error as Error);
246
+ * }
247
+ * ```
248
+ */ class SkillDiscoveryError extends SequentialThinkingError {
249
+ /** The underlying error that caused the discovery failure. */ cause;
250
+ /**
251
+ * Creates a new SkillDiscoveryError.
252
+ *
253
+ * @param directory - The directory where discovery failed
254
+ * @param cause - The underlying error that caused the failure
255
+ *
256
+ * @example
257
+ * ```typescript
258
+ * try {
259
+ * const skills = await loadSkills('./invalid-directory');
260
+ * } catch (error) {
261
+ * throw new SkillDiscoveryError('./invalid-directory', error as Error);
262
+ * }
263
+ * ```
264
+ */ constructor(directory, cause){
265
+ super(`Failed to discover skills in ${directory}: ${cause.message}`, ERROR_CODES.SKILL_DISCOVERY_FAILED);
266
+ this.name = 'SkillDiscoveryError';
267
+ this.cause = cause;
268
+ }
269
+ }
270
+ /**
271
+ * Error thrown when history size exceeds the configured limit.
272
+ *
273
+ * This error is thrown when an operation would cause the history size
274
+ * to exceed the maximum configured size limit.
275
+ *
276
+ * @example
277
+ * ```typescript
278
+ * if (history.length >= maxSize) {
279
+ * throw new HistoryLimitExceededError(history.length, maxSize);
280
+ * }
281
+ * ```
282
+ */ class HistoryLimitExceededError extends SequentialThinkingError {
283
+ /**
284
+ * Creates a new HistoryLimitExceededError.
285
+ *
286
+ * @param currentSize - The current history size
287
+ * @param maxSize - The maximum allowed size
288
+ *
289
+ * @example
290
+ * ```typescript
291
+ * throw new HistoryLimitExceededError(1500, 1000);
292
+ * // Error: History size 1500 exceeds limit 1000
293
+ * // Code: HISTORY_LIMIT_EXCEEDED
294
+ * ```
295
+ */ constructor(currentSize, maxSize){
296
+ super(`History size ${currentSize} exceeds limit ${maxSize}`, ERROR_CODES.HISTORY_LIMIT_EXCEEDED);
297
+ this.name = 'HistoryLimitExceededError';
298
+ }
299
+ }
300
+ /**
301
+ * Error thrown when attempting to add a skill that already exists.
302
+ *
303
+ * This error is thrown when trying to register a skill with a name that
304
+ * is already present in the skill registry.
305
+ *
306
+ * @example
307
+ * ```typescript
308
+ * if (registry.hasSkill(skill.name)) {
309
+ * throw new DuplicateSkillError(skill.name);
310
+ * }
311
+ * ```
312
+ */ class DuplicateSkillError extends SequentialThinkingError {
313
+ /**
314
+ * Creates a new DuplicateSkillError.
315
+ *
316
+ * @param skillName - The name of the duplicate skill
317
+ *
318
+ * @example
319
+ * ```typescript
320
+ * throw new DuplicateSkillError('my-skill');
321
+ * // Error: skill 'my-skill' already exists
322
+ * // Code: DUPLICATE_SKILL
323
+ * ```
324
+ */ constructor(skillName){
325
+ super(`skill '${skillName}' already exists`, ERROR_CODES.DUPLICATE_SKILL);
326
+ this.name = 'DuplicateSkillError';
327
+ }
328
+ }
329
+ /**
330
+ * Error thrown when a skill has invalid data.
331
+ *
332
+ * This error is thrown when a skill fails validation, typically due to
333
+ * missing required fields or invalid values.
334
+ *
335
+ * @example
336
+ * ```typescript
337
+ * if (!skill.name) {
338
+ * throw new InvalidSkillError('Skill must have a valid name');
339
+ * }
340
+ * ```
341
+ */ class InvalidSkillError extends SequentialThinkingError {
342
+ /**
343
+ * Creates a new InvalidSkillError.
344
+ *
345
+ * @param reason - The reason for the validation failure
346
+ *
347
+ * @example
348
+ * ```typescript
349
+ * throw new InvalidSkillError('Skill must have a valid name');
350
+ * // Error: Invalid skill: Skill must have a valid name
351
+ * // Code: INVALID_SKILL
352
+ * ```
353
+ */ constructor(reason){
354
+ super(`Invalid skill: ${reason}`, ERROR_CODES.INVALID_SKILL);
355
+ this.name = 'InvalidSkillError';
356
+ }
357
+ }
358
+ /**
359
+ * Error thrown when attempting to add a tool that already exists.
360
+ *
361
+ * This error is thrown when trying to register a tool with a name that
362
+ * is already present in the tool registry.
363
+ *
364
+ * @example
365
+ * ```typescript
366
+ * if (registry.hasTool(tool.name)) {
367
+ * throw new DuplicateToolError(tool.name);
368
+ * }
369
+ * ```
370
+ */ class DuplicateToolError extends SequentialThinkingError {
371
+ /**
372
+ * Creates a new DuplicateToolError.
373
+ *
374
+ * @param toolName - The name of the duplicate tool
375
+ *
376
+ * @example
377
+ * ```typescript
378
+ * throw new DuplicateToolError('my-tool');
379
+ * // Error: tool 'my-tool' already exists
380
+ * // Code: DUPLICATE_TOOL
381
+ * ```
382
+ */ constructor(toolName){
383
+ super(`tool '${toolName}' already exists`, ERROR_CODES.DUPLICATE_TOOL);
384
+ this.name = 'DuplicateToolError';
385
+ }
386
+ }
387
+ /**
388
+ * Error thrown when a tool has invalid data.
389
+ *
390
+ * This error is thrown when a tool fails validation, typically due to
391
+ * missing required fields or invalid values.
392
+ *
393
+ * @example
394
+ * ```typescript
395
+ * if (!tool.name) {
396
+ * throw new InvalidToolError('Tool must have a valid name');
397
+ * }
398
+ * ```
399
+ */ class InvalidToolError extends SequentialThinkingError {
400
+ /**
401
+ * Creates a new InvalidToolError.
402
+ *
403
+ * @param reason - The reason for the validation failure
404
+ *
405
+ * @example
406
+ * ```typescript
407
+ * throw new InvalidToolError('Tool must have a valid name');
408
+ * // Error: Invalid tool: Tool must have a valid name
409
+ * // Code: INVALID_TOOL
410
+ * ```
411
+ */ constructor(reason){
412
+ super(`Invalid tool: ${reason}`, ERROR_CODES.INVALID_TOOL);
413
+ this.name = 'InvalidToolError';
414
+ }
415
+ }
416
+ /**
417
+ * Error thrown when attempting to process a session that is not active.
418
+ *
419
+ * This error is thrown when trying to use a session that has been closed
420
+ * or deactivated.
421
+ *
422
+ * @example
423
+ * ```typescript
424
+ * if (!session.isActive) {
425
+ * throw new SessionNotActiveError(sessionId);
426
+ * }
427
+ * ```
428
+ */ class SessionNotActiveError extends SequentialThinkingError {
429
+ /**
430
+ * Creates a new SessionNotActiveError.
431
+ *
432
+ * @param sessionId - The ID of the inactive session
433
+ *
434
+ * @example
435
+ * ```typescript
436
+ * throw new SessionNotActiveError('session-123');
437
+ * // Error: Session 'session-123' is not active
438
+ * // Code: SESSION_NOT_ACTIVE
439
+ * ```
440
+ */ constructor(sessionId){
441
+ super(`Session '${sessionId}' is not active`, ERROR_CODES.SESSION_NOT_ACTIVE);
442
+ this.name = 'SessionNotActiveError';
443
+ }
444
+ }
445
+ /**
446
+ * Error thrown when a requested session is not found in the pool.
447
+ *
448
+ * This error is thrown when attempting to retrieve, process, or close
449
+ * a session that doesn't exist in the session pool.
450
+ *
451
+ * @example
452
+ * ```typescript
453
+ * const session = pool.getSession('non-existent-session');
454
+ * if (!session) {
455
+ * throw new SessionNotFoundError('non-existent-session');
456
+ * }
457
+ * ```
458
+ */ class SessionNotFoundError extends SequentialThinkingError {
459
+ /**
460
+ * Creates a new SessionNotFoundError.
461
+ *
462
+ * @param sessionId - The ID of the session that was not found
463
+ *
464
+ * @example
465
+ * ```typescript
466
+ * throw new SessionNotFoundError('session-123');
467
+ * // Error: Session not found: session-123
468
+ * // Code: SESSION_NOT_FOUND
469
+ * ```
470
+ */ constructor(sessionId){
471
+ super(`Session not found: ${sessionId}`, ERROR_CODES.SESSION_NOT_FOUND);
472
+ this.name = 'SessionNotFoundError';
473
+ }
474
+ }
475
+ /**
476
+ * Error thrown when the maximum number of sessions has been reached.
477
+ *
478
+ * This error is thrown when trying to create a new session when the
479
+ * pool has reached its configured maximum session limit.
480
+ *
481
+ * @example
482
+ * ```typescript
483
+ * if (pool.sessionCount >= pool.maxSessions) {
484
+ * throw new MaxSessionsReachedError(pool.maxSessions);
485
+ * }
486
+ * ```
487
+ */ class MaxSessionsReachedError extends SequentialThinkingError {
488
+ /**
489
+ * Creates a new MaxSessionsReachedError.
490
+ *
491
+ * @param maxSessions - The maximum number of sessions allowed
492
+ *
493
+ * @example
494
+ * ```typescript
495
+ * throw new MaxSessionsReachedError(100);
496
+ * // Error: Max sessions (100) reached. Wait for a session to close or increase maxSessions.
497
+ * // Code: MAX_SESSIONS_REACHED
498
+ * ```
499
+ */ constructor(maxSessions){
500
+ super(`Max sessions (${maxSessions}) reached. Wait for a session to close or increase maxSessions.`, ERROR_CODES.MAX_SESSIONS_REACHED);
501
+ this.name = 'MaxSessionsReachedError';
502
+ }
503
+ }
504
+ /**
505
+ * Error thrown when attempting to use a terminated connection pool.
506
+ *
507
+ * This error is thrown when trying to create sessions or process requests
508
+ * after the connection pool has been terminated.
509
+ *
510
+ * @example
511
+ * ```typescript
512
+ * if (pool.isTerminated) {
513
+ * throw new PoolTerminatedError();
514
+ * }
515
+ * ```
516
+ */ class PoolTerminatedError extends SequentialThinkingError {
517
+ /**
518
+ * Creates a new PoolTerminatedError.
519
+ *
520
+ * @example
521
+ * ```typescript
522
+ * throw new PoolTerminatedError();
523
+ * // Error: ConnectionPool has been terminated
524
+ * // Code: POOL_TERMINATED
525
+ * ```
526
+ */ constructor(){
527
+ super('ConnectionPool has been terminated', ERROR_CODES.POOL_TERMINATED);
528
+ this.name = 'PoolTerminatedError';
529
+ }
530
+ }
531
+ /**
532
+ * Error thrown when input validation fails due to invalid or malicious data.
533
+ *
534
+ * This error is thrown when user input fails security or format validation,
535
+ * such as path traversal attempts or invalid identifier formats.
536
+ *
537
+ * @example
538
+ * ```typescript
539
+ * if (!BRANCH_ID_PATTERN.test(branchId)) {
540
+ * throw new ValidationError('branchId', 'Invalid format');
541
+ * }
542
+ * ```
543
+ */ class ValidationError extends SequentialThinkingError {
544
+ /** The field that failed validation. */ field;
545
+ constructor(field, reason){
546
+ super(`Validation failed for '${field}': ${reason}`, ERROR_CODES.VALIDATION_ERROR);
547
+ this.name = 'ValidationError';
548
+ this.field = field;
549
+ }
550
+ }
551
+ /**
552
+ * Error thrown when an invalid edge operation is attempted.
553
+ *
554
+ * This error is thrown when attempting to add an edge that violates
555
+ * structural invariants of the thought DAG, such as a self-edge
556
+ * (where `from` and `to` reference the same thought).
557
+ *
558
+ * @example
559
+ * ```typescript
560
+ * if (edge.from === edge.to) {
561
+ * throw new InvalidEdgeError(
562
+ * `Self-edge not allowed: from and to are the same (${edge.from})`
563
+ * );
564
+ * }
565
+ * ```
566
+ */ class InvalidEdgeError extends SequentialThinkingError {
567
+ /**
568
+ * Creates a new InvalidEdgeError.
569
+ *
570
+ * @param message - Human-readable explanation of the invalid edge
571
+ *
572
+ * @example
573
+ * ```typescript
574
+ * throw new InvalidEdgeError('Self-edge not allowed: from and to are the same (t1)');
575
+ * // Code: INVALID_EDGE
576
+ * ```
577
+ */ constructor(message){
578
+ super(message, ERROR_CODES.INVALID_EDGE);
579
+ this.name = 'InvalidEdgeError';
580
+ }
581
+ }
582
+ /**
583
+ * Error thrown when a cycle is detected during graph traversal.
584
+ *
585
+ * This error is thrown by graph algorithms (such as topological sort)
586
+ * when the thought DAG contains a cycle, violating the acyclic invariant.
587
+ *
588
+ * @example
589
+ * ```typescript
590
+ * try {
591
+ * const order = graphView.topological(sessionId);
592
+ * } catch (error) {
593
+ * if (error instanceof CycleDetectedError) {
594
+ * console.error('Cycle in thought graph:', error.message);
595
+ * }
596
+ * }
597
+ * ```
598
+ */ class CycleDetectedError extends SequentialThinkingError {
599
+ /**
600
+ * Creates a new CycleDetectedError.
601
+ *
602
+ * @param message - Human-readable explanation of the cycle
603
+ *
604
+ * @example
605
+ * ```typescript
606
+ * throw new CycleDetectedError('Cycle detected in session s1');
607
+ * // Code: CYCLE_DETECTED
608
+ * ```
609
+ */ constructor(message){
610
+ super(message, ERROR_CODES.CYCLE_DETECTED);
611
+ this.name = 'CycleDetectedError';
612
+ }
613
+ }
614
+ /**
615
+ * Error thrown when a suspension record is not found.
616
+ *
617
+ * This error is thrown when attempting to resume a tool interleave
618
+ * suspension that does not exist in the suspension store.
619
+ */ class SuspensionNotFoundError extends SequentialThinkingError {
620
+ constructor(message){
621
+ super(message, ERROR_CODES.SUSPENSION_NOT_FOUND);
622
+ this.name = 'SuspensionNotFoundError';
623
+ }
624
+ }
625
+ /**
626
+ * Error thrown when a suspension record has expired.
627
+ *
628
+ * This error is thrown when attempting to resume a tool interleave
629
+ * suspension whose TTL has elapsed.
630
+ */ class SuspensionExpiredError extends SequentialThinkingError {
631
+ constructor(message){
632
+ super(message, ERROR_CODES.SUSPENSION_EXPIRED);
633
+ this.name = 'SuspensionExpiredError';
634
+ }
635
+ }
636
+ /**
637
+ * Error thrown when a tool call payload is invalid.
638
+ *
639
+ * This error is thrown when a tool interleave invocation has malformed
640
+ * arguments, missing identifiers, or otherwise fails validation.
641
+ */ class InvalidToolCallError extends SequentialThinkingError {
642
+ constructor(message){
643
+ super(message, ERROR_CODES.INVALID_TOOL_CALL);
644
+ this.name = 'InvalidToolCallError';
645
+ }
646
+ }
647
+ /**
648
+ * Error thrown when a backtrack operation is invalid.
649
+ *
650
+ * This error is thrown when an attempt to backtrack the reasoning
651
+ * chain references an unreachable thought or violates DAG invariants.
652
+ */ class InvalidBacktrackError extends SequentialThinkingError {
653
+ constructor(message){
654
+ super(message, ERROR_CODES.INVALID_BACKTRACK);
655
+ this.name = 'InvalidBacktrackError';
656
+ }
657
+ }
658
+ /**
659
+ * Type guard to check if an error has a specific error code.
660
+ */ function isErrorCode(err, code) {
661
+ return err instanceof SequentialThinkingError && err.code === code;
662
+ }
663
+ /**
664
+ * Extract a human-readable message from an unknown error value.
665
+ *
666
+ * Standardizes the common `error instanceof Error ? error.message : String(error)`
667
+ * pattern used in catch blocks across the codebase.
668
+ *
669
+ * @param error - The unknown error value to extract a message from
670
+ * @returns The error message string
671
+ *
672
+ * @example
673
+ * ```typescript
674
+ * try {
675
+ * await doSomething();
676
+ * } catch (error) {
677
+ * logger.error('Failed', { error: getErrorMessage(error) });
678
+ * }
679
+ * ```
680
+ */ function getErrorMessage(error) {
681
+ return error instanceof Error ? error.message : String(error);
682
+ }
683
+
684
+
685
+ },
686
+ 789(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
687
+ __webpack_require__.d(__webpack_exports__, {
688
+ createConnectionPool: () => (createConnectionPool)
689
+ });
690
+ /* import */ var _errors_js__rspack_import_0 = __webpack_require__(937);
691
+ /**
692
+ * Connection Pool for managing concurrent user sessions.
693
+ *
694
+ * This module provides session management for multi-user scenarios,
695
+ * allowing multiple concurrent clients to each have isolated state.
696
+ *
697
+ * @example
698
+ * ```typescript
699
+ * const pool = new ConnectionPool({
700
+ * maxSessions: 100,
701
+ * sessionTimeout: 300000 // 5 minutes
702
+ * });
703
+ *
704
+ * const sessionId = await pool.createSession();
705
+ * await pool.process(sessionId, thought);
706
+ * await pool.closeSession(sessionId);
707
+ * ```
708
+ */
709
+ /**
710
+ * Represents a user session with its own server instance.
711
+ */ class Session {
712
+ _server;
713
+ _id;
714
+ _createdAt;
715
+ _lastActivityAt;
716
+ _isActiveValue;
717
+ _timeout;
718
+ _cleanupTimer = null;
719
+ _logger;
720
+ constructor(id, server, timeout, logger){
721
+ this._server = server;
722
+ this._id = id;
723
+ this._createdAt = Date.now();
724
+ this._lastActivityAt = this._createdAt;
725
+ this._isActiveValue = true;
726
+ this._timeout = timeout;
727
+ this._logger = logger;
728
+ // Start session timeout timer
729
+ this._startTimeout();
730
+ }
731
+ /**
732
+ * Check if the session is active.
733
+ */ get isActive() {
734
+ return this._isActiveValue;
735
+ }
736
+ /**
737
+ * Process a thought through this session's server instance.
738
+ */ async process(input) {
739
+ if (!this.isActive) {
740
+ throw new _errors_js__rspack_import_0/* .SessionNotActiveError */.qA(this._id);
741
+ }
742
+ // Update last activity
743
+ this._lastActivityAt = Date.now();
744
+ // Reset timeout timer
745
+ this._resetTimeout();
746
+ // Process the thought
747
+ return this._server.processThought(input);
748
+ }
749
+ /**
750
+ * Get session information.
751
+ */ getInfo() {
752
+ return {
753
+ id: this._id,
754
+ server: this._server,
755
+ createdAt: this._createdAt,
756
+ lastActivityAt: this._lastActivityAt,
757
+ isActive: this.isActive
758
+ };
759
+ }
760
+ /**
761
+ * Check if the session has timed out.
762
+ */ isTimedOut() {
763
+ return Date.now() - this._lastActivityAt > this._timeout;
764
+ }
765
+ /**
766
+ * Close the session and stop the server.
767
+ */ async close() {
768
+ this._isActiveValue = false;
769
+ // Stop timeout timer
770
+ if (this._cleanupTimer) {
771
+ clearTimeout(this._cleanupTimer);
772
+ this._cleanupTimer = null;
773
+ }
774
+ // Stop the server
775
+ this._server.stop();
776
+ }
777
+ /**
778
+ * Start the session timeout timer.
779
+ */ _startTimeout() {
780
+ if (this._cleanupTimer) {
781
+ clearTimeout(this._cleanupTimer);
782
+ }
783
+ this._cleanupTimer = setTimeout(()=>{
784
+ if (this.isTimedOut()) {
785
+ this._logger.warn(`Session ${this._id} timed out, closing`);
786
+ this.close().catch((err)=>{
787
+ this._logger.error(`Error closing timed out session ${this._id}:`, err);
788
+ });
789
+ }
790
+ }, this._timeout);
791
+ }
792
+ /**
793
+ * Reset the timeout timer after activity.
794
+ */ _resetTimeout() {
795
+ this._startTimeout();
796
+ }
797
+ }
798
+ /**
799
+ * ConnectionPool manages multiple concurrent user sessions.
800
+ *
801
+ * Each session has its own server instance with isolated state,
802
+ * allowing multiple users to interact with the system simultaneously.
803
+ */ class ConnectionPool {
804
+ _sessions = new Map();
805
+ _createSessionLock = null;
806
+ _maxSessions;
807
+ _sessionTimeout;
808
+ _autoCleanup;
809
+ _cleanupInterval;
810
+ _cleanupTimerId = null;
811
+ _terminated = false;
812
+ _logger;
813
+ _serverFactory;
814
+ constructor(options = {}){
815
+ this._maxSessions = options.maxSessions ?? 100;
816
+ this._sessionTimeout = options.sessionTimeout ?? 300000; // 5 minutes
817
+ this._autoCleanup = options.autoCleanup ?? true;
818
+ this._cleanupInterval = options.cleanupInterval ?? 60000; // 1 minute
819
+ this._serverFactory = options.serverFactory ?? null;
820
+ this._logger = options.logger ?? this._createNoopLogger();
821
+ if (this._autoCleanup) {
822
+ this._startCleanup();
823
+ }
824
+ }
825
+ /**
826
+ * Create a no-op logger when none is provided.
827
+ */ _createNoopLogger() {
828
+ return {
829
+ info: ()=>{},
830
+ warn: ()=>{},
831
+ error: ()=>{},
832
+ debug: ()=>{},
833
+ setLevel: ()=>{},
834
+ getLevel: ()=>'info'
835
+ };
836
+ }
837
+ /**
838
+ * Create a new session.
839
+ *
840
+ * @returns The session ID
841
+ * @throws Error if max sessions reached
842
+ */ async createSession() {
843
+ while(this._createSessionLock){
844
+ await this._createSessionLock;
845
+ }
846
+ if (this._terminated) {
847
+ throw new _errors_js__rspack_import_0/* .PoolTerminatedError */.m_();
848
+ }
849
+ if (this._sessions.size >= this._maxSessions) {
850
+ throw new _errors_js__rspack_import_0/* .MaxSessionsReachedError */.yM(this._maxSessions);
851
+ }
852
+ if (!this._serverFactory) {
853
+ throw new Error('ConnectionPool requires a serverFactory option to create sessions');
854
+ }
855
+ let resolveLock;
856
+ this._createSessionLock = new Promise((resolve)=>{
857
+ resolveLock = resolve;
858
+ });
859
+ try {
860
+ // Generate unique session ID
861
+ const sessionId = `session_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
862
+ // Create a new server instance for this session
863
+ const server = await this._serverFactory();
864
+ // Create session
865
+ const session = new Session(sessionId, server, this._sessionTimeout, this._logger);
866
+ this._sessions.set(sessionId, session);
867
+ this._logger.info(`Created session ${sessionId} (${this._sessions.size}/${this._maxSessions} active sessions)`);
868
+ return sessionId;
869
+ } finally{
870
+ resolveLock();
871
+ this._createSessionLock = null;
872
+ }
873
+ }
874
+ /**
875
+ * Process a thought in the specified session.
876
+ *
877
+ * @param sessionId - The session ID
878
+ * @param input - The thought data to process
879
+ * @returns Promise with the processing result
880
+ * @throws Error if session not found
881
+ */ async process(sessionId, input) {
882
+ const session = this._sessions.get(sessionId);
883
+ if (!session) {
884
+ throw new _errors_js__rspack_import_0/* .SessionNotFoundError */.Ag(sessionId);
885
+ }
886
+ return session.process(input);
887
+ }
888
+ /**
889
+ * Close a session and release resources.
890
+ *
891
+ * @param sessionId - The session ID to close
892
+ * @throws Error if session not found
893
+ */ async closeSession(sessionId) {
894
+ const session = this._sessions.get(sessionId);
895
+ if (!session) {
896
+ throw new _errors_js__rspack_import_0/* .SessionNotFoundError */.Ag(sessionId);
897
+ }
898
+ await session.close();
899
+ this._sessions.delete(sessionId);
900
+ this._logger.info(`Closed session ${sessionId} (${this._sessions.size}/${this._maxSessions} active sessions)`);
901
+ }
902
+ /**
903
+ * Get information about a session.
904
+ *
905
+ * @param sessionId - The session ID
906
+ * @returns Session info or undefined if not found
907
+ */ getSessionInfo(sessionId) {
908
+ return this._sessions.get(sessionId)?.getInfo();
909
+ }
910
+ /**
911
+ * Get all active sessions.
912
+ *
913
+ * @returns Array of session information
914
+ */ getActiveSessions() {
915
+ return Array.from(this._sessions.values()).filter((s)=>s.isActive).map((s)=>s.getInfo());
916
+ }
917
+ /**
918
+ * Get connection pool statistics.
919
+ */ getStats() {
920
+ const activeSessions = this.getActiveSessions();
921
+ return {
922
+ totalSessions: this._sessions.size,
923
+ activeSessions: activeSessions.length,
924
+ maxSessions: this._maxSessions,
925
+ cleanupEnabled: this._autoCleanup,
926
+ sessionTimeout: this._sessionTimeout
927
+ };
928
+ }
929
+ /**
930
+ * Start the automatic cleanup timer.
931
+ */ _startCleanup() {
932
+ if (this._cleanupTimerId !== null) {
933
+ clearInterval(this._cleanupTimerId);
934
+ }
935
+ this._cleanupTimerId = setInterval(()=>{
936
+ this._cleanupTimedOutSessions();
937
+ }, this._cleanupInterval);
938
+ }
939
+ /**
940
+ * Remove timed-out sessions.
941
+ */ _cleanupTimedOutSessions() {
942
+ let cleaned = 0;
943
+ for (const [sessionId, session] of this._sessions.entries()){
944
+ if (session.isTimedOut()) {
945
+ session.close().catch((err)=>{
946
+ this._logger.error(`Error closing timed out session ${sessionId}:`, err);
947
+ });
948
+ this._sessions.delete(sessionId);
949
+ cleaned++;
950
+ }
951
+ }
952
+ if (cleaned > 0) {
953
+ this._logger.info(`Cleaned ${cleaned} timed-out sessions (${this._sessions.size}/${this._maxSessions} active sessions)`);
954
+ }
955
+ }
956
+ /**
957
+ * Close all sessions and stop the cleanup timer.
958
+ */ async terminate() {
959
+ if (this._terminated) {
960
+ return;
961
+ }
962
+ this._terminated = true;
963
+ // Stop cleanup timer
964
+ if (this._cleanupTimerId !== null) {
965
+ clearInterval(this._cleanupTimerId);
966
+ this._cleanupTimerId = null;
967
+ }
968
+ // Close all sessions
969
+ const closePromises = Array.from(this._sessions.values()).map((session)=>session.close().catch((err)=>{
970
+ this._logger.error(`Error closing session ${session.getInfo().id}:`, err);
971
+ }));
972
+ await Promise.all(closePromises);
973
+ this._sessions.clear();
974
+ this._logger.info('ConnectionPool terminated');
975
+ }
976
+ /**
977
+ * Dispose of the connection pool, releasing all resources.
978
+ * Implements the IDisposable interface.
979
+ * Delegates to terminate() for backward compatibility.
980
+ */ async dispose() {
981
+ await this.terminate();
982
+ }
983
+ /**
984
+ * Check if the connection pool is active.
985
+ */ isRunning() {
986
+ return !this._terminated;
987
+ }
988
+ }
989
+ /**
990
+ * Create a connection pool with the given options.
991
+ *
992
+ * @param options - Connection pool configuration
993
+ * @returns A configured connection pool
994
+ *
995
+ * @example
996
+ * ```typescript
997
+ * const pool = createConnectionPool({
998
+ * maxSessions: 50,
999
+ * sessionTimeout: 300000
1000
+ * });
1001
+ * ```
1002
+ */ function createConnectionPool(options) {
1003
+ return new ConnectionPool(options);
1004
+ }
1005
+
1006
+
1007
+ },
1008
+ 613(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1009
+ __webpack_require__.d(__webpack_exports__, {
1010
+ Uv: () => (JsonRpcRequestSchema),
1011
+ ZK: () => (SequentialThinkingSchema),
1012
+ iV: () => (SEQUENTIAL_THINKING_TOOL)
1013
+ });
1014
+ /* import */ var valibot__rspack_import_0 = __webpack_require__(821);
1015
+ /**
1016
+ * Valibot validation schemas for the sequential thinking MCP tool.
1017
+ *
1018
+ * This module defines the validation schemas used for the sequential thinking tool,
1019
+ * including schemas for tool recommendations, skill recommendations, step recommendations,
1020
+ * and the main sequential thinking input. All schemas use Valibot for runtime validation
1021
+ * and provide detailed descriptions for MCP protocol compatibility.
1022
+ *
1023
+ * @remarks
1024
+ * **Schema Overview:**
1025
+ * - `ToolRecommendationSchema` - Validates tool recommendation objects with confidence scores
1026
+ * - `SkillRecommendationSchema` - Validates skill recommendation objects
1027
+ * - `StepRecommendationSchema` - Validates step coordination structures
1028
+ * - `SequentialThinkingSchema` - Main schema for thought input validation
1029
+ * - Reasoning enhancement fields: thought_type, quality_score, confidence, hypothesis_id, etc.
1030
+ *
1031
+ * @example
1032
+ * ```typescript
1033
+ * import { SequentialThinkingSchema } from './schema.js';
1034
+ * import { safeParse } from 'valibot';
1035
+ *
1036
+ * const result = safeParse(SequentialThinkingSchema, inputData);
1037
+ * if (result.success) {
1038
+ * const thought = result.output;
1039
+ * // Process the valid thought
1040
+ * } else {
1041
+ * console.error('Validation failed:', result.issues);
1042
+ * }
1043
+ * ```
1044
+ * @module schema
1045
+ */
1046
+ /**
1047
+ * Detailed description for the sequential thinking tool.
1048
+ *
1049
+ * This description is shown to LLMs when they consider using this tool.
1050
+ * It explains when to use the tool, its features, parameters, and best practices.
1051
+ */ const TOOL_DESCRIPTION = `A detailed tool for dynamic and reflective problem-solving through thoughts.
3
1052
  This tool helps analyze problems through a flexible thinking process that can adapt and evolve.
4
1053
  Each thought can build on, question, or revise previous insights as understanding deepens.
5
1054
 
@@ -102,13 +1151,2439 @@ You should:
102
1151
  20. Self-assess quality and confidence to track reasoning reliability
103
1152
  21. Use merge_from_thoughts to combine insights from multiple reasoning branches
104
1153
  22. Use session_id to isolate independent reasoning chains from each other
105
- 23. Use reset_state: true when starting a completely new analysis to avoid statistical contamination from previous chains`,o=i.object({tool_name:i.pipe(i.string(),i.description("Name of the tool being recommended")),confidence:i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("0-1 indicating confidence in recommendation")),rationale:i.pipe(i.string(),i.description("Why this tool is recommended")),priority:i.optional(i.pipe(i.number(),i.description("Order in the recommendation sequence (default: 999)"))),suggested_inputs:i.optional(i.pipe(i.record(i.string(),i.unknown()),i.description("Optional suggested parameters"))),alternatives:i.optional(i.pipe(i.array(i.string()),i.description("Alternative tools that could be used")))}),r=i.object({skill_name:i.pipe(i.string(),i.description("Name of the skill being recommended")),confidence:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("0-1 indicating confidence in recommendation (default: 0.5)"))),rationale:i.optional(i.pipe(i.string(),i.description("Why this skill is recommended (default: empty string)"))),priority:i.optional(i.pipe(i.number(),i.description("Order in the recommendation sequence (default: 999)"))),alternatives:i.optional(i.pipe(i.array(i.string()),i.description("Alternative skills that could be used"))),allowed_tools:i.optional(i.pipe(i.array(i.string()),i.description("Tools this skill is allowed to use (from skill frontmatter)"))),user_invocable:i.optional(i.pipe(i.boolean(),i.description("Whether this skill can be user-invoked")))}),a=i.object({step_description:i.pipe(i.string(),i.description("What needs to be done")),recommended_tools:i.pipe(i.array(o),i.description("Tools recommended for this step")),recommended_skills:i.optional(i.pipe(i.array(r),i.description("Skills recommended for this step"))),expected_outcome:i.pipe(i.string(),i.description("What to expect from this step")),next_step_conditions:i.optional(i.pipe(i.array(i.string()),i.description("Conditions to consider for the next step")))}),l=i.object({tool_name:i.pipe(i.string(),i.description("Name of the tool being recommended")),rationale:i.optional(i.pipe(i.string(),i.description("Why this tool is recommended (default: empty string)"))),confidence:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("0-1 indicating confidence in recommendation (default: 0.5)"))),priority:i.optional(i.pipe(i.number(),i.description("Order in the recommendation sequence (default: 999)"))),suggested_inputs:i.optional(i.pipe(i.record(i.string(),i.unknown()),i.description("Optional suggested parameters"))),alternatives:i.optional(i.pipe(i.array(i.string()),i.description("Alternative tools that could be used")))}),c=i.object({step_description:i.pipe(i.string(),i.description("What needs to be done")),recommended_tools:i.pipe(i.array(l),i.description("Tools recommended for this step")),recommended_skills:i.optional(i.pipe(i.array(r),i.description("Skills recommended for this step"))),expected_outcome:i.optional(i.pipe(i.string(),i.description("What to expect from this step (default: empty string)"))),next_step_conditions:i.optional(i.pipe(i.array(i.string()),i.description("Conditions to consider for the next step")))}),h=i.object({available_mcp_tools:i.optional(i.pipe(i.array(i.string()),i.description('Array of MCP tool names available for use (e.g., ["mcp-omnisearch", "mcp-turso-cloud"])'))),available_skills:i.optional(i.pipe(i.array(i.string()),i.description('Array of skill names available for use (e.g., ["commit", "review-pr", "pdf"])'))),thought:i.pipe(i.string(),i.description("Your current thinking step")),id:i.optional(i.pipe(i.string(),i.minLength(1),i.maxLength(30),i.description("Unique identifier for this thought. Auto-generated if not provided."))),next_thought_needed:i.optional(i.pipe(i.boolean(),i.description("Whether another thought step is needed (defaults to true if not provided)"))),thought_number:i.pipe(i.number(),i.minValue(1),i.description("Current thought number")),total_thoughts:i.pipe(i.number(),i.minValue(1),i.description("Estimated total thoughts needed")),is_revision:i.optional(i.pipe(i.boolean(),i.description("Whether this revises previous thinking"))),revises_thought:i.optional(i.pipe(i.number(),i.minValue(1),i.description("Which thought is being reconsidered"))),branch_from_thought:i.optional(i.pipe(i.number(),i.minValue(1),i.description("Branching point thought number"))),branch_id:i.optional(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/,"Branch ID must contain only letters, numbers, hyphens, and underscores"),i.minLength(1),i.maxLength(50),i.description("Branch identifier (alphanumeric, hyphens, underscores only, max 50 chars)"))),needs_more_thoughts:i.optional(i.pipe(i.boolean(),i.description("If more thoughts are needed"))),current_step:i.optional(i.pipe(a,i.description("Current step recommendation"))),previous_steps:i.optional(i.pipe(i.array(c),i.description("Steps already recommended (lenient schema - allows partial data with defaults)"))),remaining_steps:i.optional(i.pipe(i.array(i.string()),i.description("High-level descriptions of upcoming steps"))),thought_type:i.optional(i.pipe(i.picklist(["regular","hypothesis","verification","critique","synthesis","meta","tool_call","tool_observation","assumption","decomposition","backtrack"]),i.description("Classified purpose: regular (default), hypothesis, verification, critique, synthesis, meta, tool_call (requires toolInterleave), tool_observation (requires toolInterleave), assumption (requires newThoughtTypes), decomposition (requires newThoughtTypes), backtrack (requires newThoughtTypes)"))),quality_score:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("Self-assessed quality score (0-1)"))),confidence:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("Explicit confidence in correctness (0-1)"))),hypothesis_id:i.optional(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/,"Hypothesis ID must contain only letters, numbers, hyphens, and underscores"),i.minLength(1),i.maxLength(50),i.description("Identifier linking hypothesis to verification thoughts"))),verification_target:i.optional(i.pipe(i.number(),i.minValue(1),i.description("Thought number being verified or critiqued"))),synthesis_sources:i.optional(i.pipe(i.array(i.pipe(i.number(),i.minValue(1))),i.description("Thought numbers being synthesized"))),merge_from_thoughts:i.optional(i.pipe(i.array(i.pipe(i.number(),i.minValue(1))),i.description("Thought numbers from other branches being merged (DAG)"))),merge_branch_ids:i.optional(i.pipe(i.array(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/),i.maxLength(50))),i.description("Branch IDs being merged into current context"))),meta_observation:i.optional(i.pipe(i.string(),i.description("Metacognitive observation about reasoning process"))),reasoning_depth:i.optional(i.pipe(i.picklist(["shallow","moderate","deep"]),i.description("Effort signal: how deep reasoning should go"))),session_id:i.optional(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/,"Session ID must contain only letters, numbers, hyphens, and underscores"),i.minLength(1),i.maxLength(100),i.description("Optional session identifier for state isolation. When provided, thought history, branches, and statistics are scoped to this session. Omitting preserves global behavior."))),reset_state:i.optional(i.pipe(i.boolean(),i.description("When true, clears all state for the target session before processing this thought. The thought is then processed as the first in a fresh session."))),tool_name:i.optional(i.pipe(i.string(),i.minLength(1),i.description("Name of the tool being invoked (for tool_call thoughts)"))),tool_arguments:i.optional(i.pipe(i.record(i.string(),i.unknown()),i.description("Arguments passed to the tool (for tool_call thoughts)"))),tool_result:i.optional(i.pipe(i.unknown(),i.description("Result returned by the tool (for tool_observation thoughts)"))),continuation_token:i.optional(i.pipe(i.string(),i.minLength(1),i.description("Token for resuming long-running tool invocations"))),decomposition_children:i.optional(i.pipe(i.array(i.string()),i.description("Child thought IDs produced by decomposition"))),backtrack_target:i.optional(i.pipe(i.number(),i.integer(),i.minValue(1),i.description("Thought number to backtrack to. When the parent thought has thought_type=backtrack, this thought is logically retracted: it remains in history but is excluded from quality signals and reasoning stats."))),register_branch_id:i.optional(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/,"register_branch_id must contain only letters, numbers, hyphens, and underscores"),i.minLength(1),i.maxLength(50),i.description("Pre-declares a branch ID for this session before any thoughts reference it. Useful so that subsequent thoughts using merge_branch_ids can target a branch that has not yet received any thoughts.")))}),p={name:"sequentialthinking_tools",description:n,inputSchema:{}},d=i.object({jsonrpc:i.pipe(i.string(),i.literal("2.0"),i.description('JSON-RPC protocol version (must be "2.0")')),method:i.pipe(i.string(),i.minLength(1),i.description("Method name to invoke")),params:i.optional(i.pipe(i.union([i.object({}),i.array(i.unknown())]),i.description("Method parameters (object or array)"))),id:i.optional(i.pipe(i.union([i.string(),i.number(),i.null()]),i.description("Request ID (omit for notifications)")))}),u=i.union([i.literal("sequence"),i.literal("branch"),i.literal("merge"),i.literal("verifies"),i.literal("critiques"),i.literal("derives_from"),i.literal("tool_invocation"),i.literal("revises")]);i.object({id:i.pipe(i.string(),i.minLength(1),i.maxLength(30)),from:i.pipe(i.string(),i.minLength(1),i.maxLength(30)),to:i.pipe(i.string(),i.minLength(1),i.maxLength(30)),kind:u,sessionId:i.pipe(i.string(),i.minLength(1)),createdAt:i.number(),metadata:i.optional(i.record(i.string(),i.unknown()))})},681(e,t,s){s.d(t,{j:()=>r}),s(561);let i=/^[a-zA-Z0-9_-]+$/;class n{_level="info";info(e,t){}warn(e,t){}error(e,t){}debug(e,t){}setLevel(e){this._level=e}getLevel(){return this._level}}let o=new Set(["session","sessionId","client","clientId"]);class r{_port;_host;_corsOrigin;_enableCors;_rateLimitEnabled;_maxRequestsPerMinute;_allowedHosts;_rateLimitMap=new Map;_rateLimitCleanupIntervalId=null;_wasHostExplicitlySet;_isShuttingDown=!1;_logger;_healthChecker;constructor(e={}){this._port=e.port??9108,this._host=e.host??"127.0.0.1",this._wasHostExplicitlySet=void 0!==e.host,this._corsOrigin=e.corsOrigin??"*",this._enableCors=e.enableCors??!0,this._rateLimitEnabled=e.enableRateLimit??!0,this._maxRequestsPerMinute=e.maxRequestsPerMinute??100,this._allowedHosts=this._buildAllowedHosts(e.allowedHosts),this._isShuttingDown=!1,this._logger=e.logger??new n,this._healthChecker=e.healthChecker??null,this._rateLimitEnabled&&this._startRateLimitCleanup()}get serverUrl(){let e=this._wasHostExplicitlySet||"127.0.0.1"!==this._host?this._host:"localhost";return`http://${e}:${this._port}`}validateSessionId(e){return!(e.length>100)&&i.test(e)}sanitizeQueryParams(e){let t={};for(let[s,i]of e.searchParams.entries())o.has(s)&&(t[s]=i);return t}checkRateLimit(e){if(!this._rateLimitEnabled)return!1;let t=Date.now();this._cleanupExpiredRateLimitEntries(t);let s=this._rateLimitMap.get(e);return!s||t>s.resetTime?(this._rateLimitMap.set(e,{count:1,resetTime:t+6e4}),!1):s.count>=this._maxRequestsPerMinute||(s.count++,!1)}_cleanupExpiredRateLimitEntries(e=Date.now()){for(let[t,s]of this._rateLimitMap.entries())s.resetTime<=e&&this._rateLimitMap.delete(t)}_startRateLimitCleanup(){null!==this._rateLimitCleanupIntervalId&&clearInterval(this._rateLimitCleanupIntervalId),this._rateLimitCleanupIntervalId=setInterval(()=>{this._cleanupExpiredRateLimitEntries()},6e4)}_stopRateLimitCleanup(){null!==this._rateLimitCleanupIntervalId&&(clearInterval(this._rateLimitCleanupIntervalId),this._rateLimitCleanupIntervalId=null)}getClientIp(e){let t=e.headers["x-forwarded-for"];return t&&"string"==typeof t?t.split(",")[0].trim():e.socket.remoteAddress||"unknown"}validateCorsOrigin(e){if("*"===this._corsOrigin)return!0;let t=e.headers.origin;if(!t||this._corsOrigin===t)return!0;if(this._corsOrigin.includes("*")){let e=this._corsOrigin.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[a-zA-Z0-9.-]*");return RegExp(`^${e}$`).test(t)}return!1}setCorsHeaders(e){this._enableCors&&(e.setHeader("Access-Control-Allow-Origin",this._corsOrigin),e.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type"))}validateHostHeader(e){let t=e.headers.host;if(!t)return!0;let s=t.split(":")[0].trim().toLowerCase();return!!s&&(0===this._allowedHosts.size||this._allowedHosts.has(s))}_buildAllowedHosts(e){if(e&&e.length>0)return new Set(e.map(e=>e.toLowerCase().trim()).filter(Boolean));let t=this._host.toLowerCase(),s=["localhost","127.0.0.1","::1"];return new Set(s.includes(t)||"0.0.0.0"===t||"::"===t?s:[t])}log(e,t,s){"info"===e?this._logger.info(t,s):"warn"===e?this._logger.warn(t,s):this._logger.error(t,s)}isShuttingDown(){return this._isShuttingDown}handleHealthEndpoint(e,t){let s={status:"healthy",...t};this._healthChecker&&(s.liveness=this._healthChecker.checkLiveness()),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(s))}async handleReadinessEndpoint(e){if(this._healthChecker){let t=await this._healthChecker.checkReadiness(),s="ok"===t.status?200:503;e.writeHead(s,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}else e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok",timestamp:new Date().toISOString(),components:{}}))}handleMetricsEndpoint(e,t){if(!t){e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Not Found");return}e.writeHead(200,{"Content-Type":"text/plain; version=0.0.4; charset=utf-8"}),e.end(t())}}},504(e,t,s){s.d(t,{SseTransport:()=>l});var i=s(316),n=s(61),o=s(821),r=s(555),a=s(681);class l extends a.j{_server;_path;_clients=new Set;_clientSessionMap=new Map;_messageQueue=new Map;_metrics;_connectionPool;constructor(e={}){super(e),this._path=e.path??"/sse",this._metrics=e.metrics,this._connectionPool=e.connectionPool,this._updateActiveConnectionsMetric(),this._server=(0,i.createServer)((e,t)=>this._handleRequest(e,t))}async connect(e){return this._mcpServer=e,new Promise(e=>{this._server.listen(this._port,this._host,()=>{this.log("info",`SSE transport listening on http://${this._host}:${this._port}`),e()})})}_mcpServer=null;async _handleRequest(e,t){var s,i,o,r,a;let l=Date.now(),c=e.url||"/",h=e.method||"GET";if(null==(s=this._metrics)||s.counter("http_requests_total",1,{transport:"sse",method:h,path:c},"Total HTTP requests"),t.once("finish",()=>{var e;let t=(Date.now()-l)/1e3;null==(e=this._metrics)||e.histogram("http_request_duration_seconds",t,{transport:"sse",path:c})}),!this.validateHostHeader(e)){null==(i=this._metrics)||i.counter("http_request_errors_total",1,{transport:"sse",error_type:"forbidden"},"Total HTTP request errors"),t.writeHead(403,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Forbidden - invalid host header"}));return}let p=new n.URL(e.url||"",`http://${e.headers.host}`),d=this.getClientIp(e);if(this.checkRateLimit(d)){null==(o=this._metrics)||o.counter("http_request_errors_total",1,{transport:"sse",error_type:"rate_limit"},"Total HTTP request errors"),t.writeHead(429,{"Content-Type":"application/json","Retry-After":"60"}),t.end(JSON.stringify({error:"Too many requests"}));return}if(!this.validateCorsOrigin(e)){null==(r=this._metrics)||r.counter("http_request_errors_total",1,{transport:"sse",error_type:"forbidden"},"Total HTTP request errors"),t.writeHead(403,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Forbidden - invalid origin"}));return}this.setCorsHeaders(t);let u=this.sanitizeQueryParams(p);if(u.session||u.sessionId){let e=u.session??u.sessionId;if(!this.validateSessionId(e)){null==(a=this._metrics)||a.counter("http_request_errors_total",1,{transport:"sse",error_type:"validation"},"Total HTTP request errors"),t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Invalid session ID format"}));return}}if(this._enableCors&&"OPTIONS"===e.method){t.writeHead(204),t.end();return}p.pathname===this._path&&"GET"===e.method?await this._handleSseConnection(e,t,u):p.pathname===`${this._path}/message`&&"POST"===e.method?await this._handleMessage(e,t,u):"/health"===p.pathname?this._handleHealthCheck(t):"/ready"===p.pathname?await this._handleReadinessCheck(t):(t.writeHead(404,{"Content-Type":"text/plain"}),t.end("Not Found"))}_handleHealthCheck(e){let t={status:"healthy",clients:this._clients.size};this._connectionPool&&(t.pool=this._connectionPool.getStats()),this._healthChecker&&(t.liveness=this._healthChecker.checkLiveness()),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}async _handleReadinessCheck(e){if(this._healthChecker){let t=await this._healthChecker.checkReadiness(),s="ok"===t.status?200:503;e.writeHead(s,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}else e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok",timestamp:new Date().toISOString(),components:{}}))}async _handleSseConnection(e,t,s){let i;if(t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),this._connectionPool){let e=s.session??s.sessionId;if(e&&this._connectionPool.getSessionInfo(e))i=e;else try{i=await this._connectionPool.createSession()}catch(e){t.write(`event: error
106
- `),t.write(`data: ${JSON.stringify({error:e instanceof Error?e.message:"Failed to create session"})}
1154
+ 23. Use reset_state: true when starting a completely new analysis to avoid statistical contamination from previous chains`;
1155
+ /**
1156
+ * Valibot schema for validating tool recommendation objects.
1157
+ *
1158
+ * Validates that a tool recommendation has:
1159
+ * - A tool name (string)
1160
+ * - A confidence score between 0 and 1
1161
+ * - A rationale explaining the recommendation
1162
+ * - A priority number for ordering
1163
+ * - Optional suggested input parameters
1164
+ * - Optional alternative tools
1165
+ *
1166
+ * @example
1167
+ * ```typescript
1168
+ * import { safeParse } from 'valibot';
1169
+ * import { ToolRecommendationSchema } from './schema.js';
1170
+ *
1171
+ * const result = safeParse(ToolRecommendationSchema, {
1172
+ * tool_name: 'mcp__tavily-mcp__tavily-search',
1173
+ * confidence: 0.9,
1174
+ * rationale: 'Best for web search',
1175
+ * priority: 1
1176
+ * });
1177
+ * ```
1178
+ */ const ToolRecommendationSchema = valibot__rspack_import_0.object({
1179
+ tool_name: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Name of the tool being recommended')),
1180
+ confidence: valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(0), valibot__rspack_import_0.maxValue(1), valibot__rspack_import_0.description('0-1 indicating confidence in recommendation')),
1181
+ rationale: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Why this tool is recommended')),
1182
+ priority: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.description('Order in the recommendation sequence (default: 999)'))),
1183
+ suggested_inputs: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.record(valibot__rspack_import_0.string(), valibot__rspack_import_0.unknown()), valibot__rspack_import_0.description('Optional suggested parameters'))),
1184
+ alternatives: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Alternative tools that could be used')))
1185
+ });
1186
+ /**
1187
+ * Valibot schema for validating skill recommendation objects.
1188
+ *
1189
+ * Validates that a skill recommendation has:
1190
+ * - A skill name (string)
1191
+ * - A confidence score between 0 and 1
1192
+ * - A rationale explaining the recommendation
1193
+ * - A priority number for ordering
1194
+ * - Optional alternative skills
1195
+ * - Optional allowed tools list
1196
+ * - Optional user invocable flag
1197
+ *
1198
+ * @example
1199
+ * ```typescript
1200
+ * import { safeParse } from 'valibot';
1201
+ * import { SkillRecommendationSchema } from './schema.js';
1202
+ *
1203
+ * const result = safeParse(SkillRecommendationSchema, {
1204
+ * skill_name: 'commit',
1205
+ * confidence: 0.95,
1206
+ * rationale: 'Handles git commit workflow',
1207
+ * priority: 1,
1208
+ * user_invocable: true
1209
+ * });
1210
+ * ```
1211
+ */ const SkillRecommendationSchema = valibot__rspack_import_0.object({
1212
+ skill_name: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Name of the skill being recommended')),
1213
+ confidence: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(0), valibot__rspack_import_0.maxValue(1), valibot__rspack_import_0.description('0-1 indicating confidence in recommendation (default: 0.5)'))),
1214
+ rationale: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Why this skill is recommended (default: empty string)'))),
1215
+ priority: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.description('Order in the recommendation sequence (default: 999)'))),
1216
+ alternatives: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Alternative skills that could be used'))),
1217
+ allowed_tools: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Tools this skill is allowed to use (from skill frontmatter)'))),
1218
+ user_invocable: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.boolean(), valibot__rspack_import_0.description('Whether this skill can be user-invoked')))
1219
+ });
1220
+ /**
1221
+ * Valibot schema for validating step recommendation objects.
1222
+ *
1223
+ * Validates that a step recommendation has:
1224
+ * - A step description
1225
+ * - An array of recommended tools
1226
+ * - An optional array of recommended skills
1227
+ * - An expected outcome
1228
+ * - Optional conditions for the next step
1229
+ *
1230
+ * @example
1231
+ * ```typescript
1232
+ * import { safeParse } from 'valibot';
1233
+ * import { StepRecommendationSchema } from './schema.js';
1234
+ *
1235
+ * const result = safeParse(StepRecommendationSchema, {
1236
+ * step_description: 'Search for TypeScript files',
1237
+ * recommended_tools: [{ ... }],
1238
+ * expected_outcome: 'List of all TypeScript files'
1239
+ * });
1240
+ * ```
1241
+ */ const StepRecommendationSchema = valibot__rspack_import_0.object({
1242
+ step_description: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('What needs to be done')),
1243
+ recommended_tools: valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(ToolRecommendationSchema), valibot__rspack_import_0.description('Tools recommended for this step')),
1244
+ recommended_skills: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(SkillRecommendationSchema), valibot__rspack_import_0.description('Skills recommended for this step'))),
1245
+ expected_outcome: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('What to expect from this step')),
1246
+ next_step_conditions: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Conditions to consider for the next step')))
1247
+ });
1248
+ /**
1249
+ * Valibot schema for validating partial tool recommendation objects.
1250
+ *
1251
+ * This is a lenient version of ToolRecommendationSchema used for previous_steps,
1252
+ * where LLMs naturally provide partial/skeletal data. Only tool_name and rationale
1253
+ * are required, while confidence and priority are optional with default values.
1254
+ *
1255
+ * Validates that a partial tool recommendation has:
1256
+ * - A tool name (required)
1257
+ * - A rationale explaining the recommendation (required)
1258
+ * - An optional confidence score (defaults to 0.5)
1259
+ * - An optional priority number (defaults to 999)
1260
+ * - Optional suggested input parameters
1261
+ * - Optional alternative tools
1262
+ *
1263
+ * @remarks
1264
+ * **Design Rationale:**
1265
+ * LLMs tend to provide complete data for current_step but only partial data
1266
+ * for previous_steps (historical context). This schema accommodates that natural
1267
+ * LLM behavior while maintaining data integrity through sensible defaults.
1268
+ *
1269
+ * @example
1270
+ * ```typescript
1271
+ * import { safeParse } from 'valibot';
1272
+ * import { PartialToolRecommendationSchema } from './schema.js';
1273
+ *
1274
+ * // Minimal valid input (LLM often generates this for previous_steps)
1275
+ * const result = safeParse(PartialToolRecommendationSchema, {
1276
+ * tool_name: 'Read',
1277
+ * rationale: 'Read the file'
1278
+ * });
1279
+ * // confidence and priority will be filled in by the normalizer
1280
+ * ```
1281
+ */ const PartialToolRecommendationSchema = valibot__rspack_import_0.object({
1282
+ tool_name: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Name of the tool being recommended')),
1283
+ rationale: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Why this tool is recommended (default: empty string)'))),
1284
+ confidence: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(0), valibot__rspack_import_0.maxValue(1), valibot__rspack_import_0.description('0-1 indicating confidence in recommendation (default: 0.5)'))),
1285
+ priority: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.description('Order in the recommendation sequence (default: 999)'))),
1286
+ suggested_inputs: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.record(valibot__rspack_import_0.string(), valibot__rspack_import_0.unknown()), valibot__rspack_import_0.description('Optional suggested parameters'))),
1287
+ alternatives: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Alternative tools that could be used')))
1288
+ });
1289
+ /**
1290
+ * Valibot schema for validating partial step recommendation objects.
1291
+ *
1292
+ * This is a lenient version of StepRecommendationSchema used for previous_steps,
1293
+ * where LLMs naturally provide partial/skeletal data. Only step_description is
1294
+ * strictly required, while expected_outcome and tool recommendation fields are
1295
+ * optional with default values.
1296
+ *
1297
+ * Validates that a partial step recommendation has:
1298
+ * - A step description (required)
1299
+ * - An array of recommended tools (with optional confidence/priority)
1300
+ * - An optional array of recommended skills
1301
+ * - An optional expected outcome (defaults to empty string)
1302
+ * - Optional conditions for the next step
1303
+ *
1304
+ * @remarks
1305
+ * **Design Rationale:**
1306
+ * LLMs provide complete, detailed data for current_step but only brief summaries
1307
+ * for previous_steps. This schema allows the natural LLM behavior while the
1308
+ * InputNormalizer fills in sensible defaults for missing fields.
1309
+ *
1310
+ * @example
1311
+ * ```typescript
1312
+ * import { safeParse } from 'valibot';
1313
+ * import { PartialStepRecommendationSchema } from './schema.js';
1314
+ *
1315
+ * // Minimal valid input (LLM often generates this for previous_steps)
1316
+ * const result = safeParse(PartialStepRecommendationSchema, {
1317
+ * step_description: 'Read the file',
1318
+ * recommended_tools: [{
1319
+ * tool_name: 'Read',
1320
+ * rationale: 'Read the file'
1321
+ * }]
1322
+ * });
1323
+ * // confidence, priority, and expected_outcome will be filled in by normalizer
1324
+ * ```
1325
+ */ const PartialStepRecommendationSchema = valibot__rspack_import_0.object({
1326
+ step_description: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('What needs to be done')),
1327
+ recommended_tools: valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(PartialToolRecommendationSchema), valibot__rspack_import_0.description('Tools recommended for this step')),
1328
+ recommended_skills: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(SkillRecommendationSchema), valibot__rspack_import_0.description('Skills recommended for this step'))),
1329
+ expected_outcome: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('What to expect from this step (default: empty string)'))),
1330
+ next_step_conditions: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Conditions to consider for the next step')))
1331
+ });
1332
+ /**
1333
+ * Main Valibot schema for validating sequential thinking tool input.
1334
+ *
1335
+ * This is the primary schema used for the sequential thinking MCP tool.
1336
+ * It validates all thought data including:
1337
+ * - Optional available tools and skills arrays
1338
+ * - The thought content (required)
1339
+ * - Thought numbering (thought_number, total_thoughts)
1340
+ * - Revision and branching metadata
1341
+ * - Current, previous, and remaining step recommendations
1342
+ *
1343
+ * @remarks
1344
+ * **Validation Rules:**
1345
+ * - `thought_number` must be >= 1
1346
+ * - `total_thoughts` must be >= 1
1347
+ * - `branch_id` must be 1-50 characters, alphanumeric/hyphens/underscores only
1348
+ * - `confidence` values must be between 0 and 1
1349
+ * - `thought_type` must be one of: regular, hypothesis, verification, critique, synthesis, meta
1350
+ * - `quality_score` and `confidence` must be between 0 and 1
1351
+ * - `hypothesis_id` must be 1-50 characters, alphanumeric/hyphens/underscores only
1352
+ *
1353
+ * @example
1354
+ * ```typescript
1355
+ * import { safeParse } from 'valibot';
1356
+ * import { SequentialThinkingSchema } from './schema.js';
1357
+ *
1358
+ * const result = safeParse(SequentialThinkingSchema, {
1359
+ * thought: 'I need to analyze the problem',
1360
+ * thought_number: 1,
1361
+ * total_thoughts: 5,
1362
+ * next_thought_needed: true,
1363
+ * available_mcp_tools: ['Read', 'Write', 'Grep']
1364
+ * });
1365
+ *
1366
+ * if (result.success) {
1367
+ * console.log('Valid thought:', result.output);
1368
+ * } else {
1369
+ * console.error('Validation errors:', result.issues);
1370
+ * }
1371
+ * ```
1372
+ */ const SequentialThinkingSchema = valibot__rspack_import_0.object({
1373
+ available_mcp_tools: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Array of MCP tool names available for use (e.g., ["mcp-omnisearch", "mcp-turso-cloud"])'))),
1374
+ available_skills: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Array of skill names available for use (e.g., ["commit", "review-pr", "pdf"])'))),
1375
+ thought: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Your current thinking step')),
1376
+ id: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.maxLength(30), valibot__rspack_import_0.description('Unique identifier for this thought. Auto-generated if not provided.'))),
1377
+ next_thought_needed: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.boolean(), valibot__rspack_import_0.description('Whether another thought step is needed (defaults to true if not provided)'))),
1378
+ thought_number: valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(1), valibot__rspack_import_0.description('Current thought number')),
1379
+ total_thoughts: valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(1), valibot__rspack_import_0.description('Estimated total thoughts needed')),
1380
+ is_revision: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.boolean(), valibot__rspack_import_0.description('Whether this revises previous thinking'))),
1381
+ revises_thought: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(1), valibot__rspack_import_0.description('Which thought is being reconsidered'))),
1382
+ branch_from_thought: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(1), valibot__rspack_import_0.description('Branching point thought number'))),
1383
+ branch_id: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.regex(/^[a-zA-Z0-9_-]+$/, 'Branch ID must contain only letters, numbers, hyphens, and underscores'), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.maxLength(50), valibot__rspack_import_0.description('Branch identifier (alphanumeric, hyphens, underscores only, max 50 chars)'))),
1384
+ needs_more_thoughts: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.boolean(), valibot__rspack_import_0.description('If more thoughts are needed'))),
1385
+ current_step: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(StepRecommendationSchema, valibot__rspack_import_0.description('Current step recommendation'))),
1386
+ previous_steps: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(PartialStepRecommendationSchema), valibot__rspack_import_0.description('Steps already recommended (lenient schema - allows partial data with defaults)'))),
1387
+ remaining_steps: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('High-level descriptions of upcoming steps'))),
1388
+ thought_type: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.picklist([
1389
+ 'regular',
1390
+ 'hypothesis',
1391
+ 'verification',
1392
+ 'critique',
1393
+ 'synthesis',
1394
+ 'meta',
1395
+ 'tool_call',
1396
+ 'tool_observation',
1397
+ 'assumption',
1398
+ 'decomposition',
1399
+ 'backtrack'
1400
+ ]), valibot__rspack_import_0.description('Classified purpose: regular (default), hypothesis, verification, critique, synthesis, meta, tool_call (requires toolInterleave), tool_observation (requires toolInterleave), assumption (requires newThoughtTypes), decomposition (requires newThoughtTypes), backtrack (requires newThoughtTypes)'))),
1401
+ quality_score: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(0), valibot__rspack_import_0.maxValue(1), valibot__rspack_import_0.description('Self-assessed quality score (0-1)'))),
1402
+ confidence: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(0), valibot__rspack_import_0.maxValue(1), valibot__rspack_import_0.description('Explicit confidence in correctness (0-1)'))),
1403
+ hypothesis_id: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.regex(/^[a-zA-Z0-9_-]+$/, 'Hypothesis ID must contain only letters, numbers, hyphens, and underscores'), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.maxLength(50), valibot__rspack_import_0.description('Identifier linking hypothesis to verification thoughts'))),
1404
+ verification_target: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(1), valibot__rspack_import_0.description('Thought number being verified or critiqued'))),
1405
+ synthesis_sources: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(1))), valibot__rspack_import_0.description('Thought numbers being synthesized'))),
1406
+ merge_from_thoughts: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(1))), valibot__rspack_import_0.description('Thought numbers from other branches being merged (DAG)'))),
1407
+ merge_branch_ids: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.regex(/^[a-zA-Z0-9_-]+$/), valibot__rspack_import_0.maxLength(50))), valibot__rspack_import_0.description('Branch IDs being merged into current context'))),
1408
+ meta_observation: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Metacognitive observation about reasoning process'))),
1409
+ reasoning_depth: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.picklist([
1410
+ 'shallow',
1411
+ 'moderate',
1412
+ 'deep'
1413
+ ]), valibot__rspack_import_0.description('Effort signal: how deep reasoning should go'))),
1414
+ session_id: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.regex(/^[a-zA-Z0-9_-]+$/, 'Session ID must contain only letters, numbers, hyphens, and underscores'), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.maxLength(100), valibot__rspack_import_0.description('Optional session identifier for state isolation. When provided, thought history, branches, and statistics are scoped to this session. Omitting preserves global behavior.'))),
1415
+ reset_state: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.boolean(), valibot__rspack_import_0.description('When true, clears all state for the target session before processing this thought. The thought is then processed as the first in a fresh session.'))),
1416
+ tool_name: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.description('Name of the tool being invoked (for tool_call thoughts)'))),
1417
+ tool_arguments: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.record(valibot__rspack_import_0.string(), valibot__rspack_import_0.unknown()), valibot__rspack_import_0.description('Arguments passed to the tool (for tool_call thoughts)'))),
1418
+ tool_result: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.unknown(), valibot__rspack_import_0.description('Result returned by the tool (for tool_observation thoughts)'))),
1419
+ continuation_token: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.description('Token for resuming long-running tool invocations'))),
1420
+ decomposition_children: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Child thought IDs produced by decomposition'))),
1421
+ backtrack_target: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.integer(), valibot__rspack_import_0.minValue(1), valibot__rspack_import_0.description('Thought number to backtrack to. When the parent thought has thought_type=backtrack, this thought is logically retracted: it remains in history but is excluded from quality signals and reasoning stats.'))),
1422
+ register_branch_id: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.regex(/^[a-zA-Z0-9_-]+$/, 'register_branch_id must contain only letters, numbers, hyphens, and underscores'), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.maxLength(50), valibot__rspack_import_0.description('Pre-declares a branch ID for this session before any thoughts reference it. Useful so that subsequent thoughts using merge_branch_ids can target a branch that has not yet received any thoughts.')))
1423
+ });
1424
+ /**
1425
+ * The sequential thinking tool definition for MCP registration.
1426
+ *
1427
+ * This object defines the tool that is registered with the MCP server.
1428
+ * The inputSchema is left empty as the schema is handled by tmcp
1429
+ * when registering the tool using the Valibot adapter.
1430
+ *
1431
+ * @example
1432
+ * ```typescript
1433
+ * import { SEQUENTIAL_THINKING_TOOL } from './schema.js';
1434
+ * import { McpServer } from 'tmcp';
1435
+ *
1436
+ * const server = new McpServer({ name: 'my-server', version: '1.0.0' });
1437
+ * server.tool({
1438
+ * name: SEQUENTIAL_THINKING_TOOL.name,
1439
+ * description: SEQUENTIAL_THINKING_TOOL.description,
1440
+ * schema: SequentialThinkingSchema
1441
+ * }, handler);
1442
+ * ```
1443
+ */ const SEQUENTIAL_THINKING_TOOL = {
1444
+ name: 'sequentialthinking_tools',
1445
+ description: TOOL_DESCRIPTION,
1446
+ inputSchema: {}
1447
+ };
1448
+ /**
1449
+ * Valibot schema for validating JSON-RPC 2.0 request messages.
1450
+ *
1451
+ * Validates that a JSON-RPC request has:
1452
+ * - A jsonrpc version (must be "2.0")
1453
+ * - A method name (string)
1454
+ * - Optional params (object or array)
1455
+ * - Optional id (string, number, or null for notifications)
1456
+ *
1457
+ * @example
1458
+ * ```typescript
1459
+ * import { safeParse } from 'valibot';
1460
+ * import { JsonRpcRequestSchema } from './schema.js';
1461
+ *
1462
+ * const result = safeParse(JsonRpcRequestSchema, {
1463
+ * jsonrpc: '2.0',
1464
+ * method: 'tools/list',
1465
+ * id: 1
1466
+ * });
1467
+ * ```
1468
+ */ const JsonRpcRequestSchema = valibot__rspack_import_0.object({
1469
+ jsonrpc: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.literal('2.0'), valibot__rspack_import_0.description('JSON-RPC protocol version (must be "2.0")')),
1470
+ method: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.description('Method name to invoke')),
1471
+ params: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.union([
1472
+ valibot__rspack_import_0.object({}),
1473
+ valibot__rspack_import_0.array(valibot__rspack_import_0.unknown())
1474
+ ]), valibot__rspack_import_0.description('Method parameters (object or array)'))),
1475
+ id: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.union([
1476
+ valibot__rspack_import_0.string(),
1477
+ valibot__rspack_import_0.number(),
1478
+ valibot__rspack_import_0["null"]()
1479
+ ]), valibot__rspack_import_0.description('Request ID (omit for notifications)')))
1480
+ });
1481
+ /**
1482
+ * Schema for {@link EdgeKind} — the semantic relationship between two thoughts.
1483
+ */ const EdgeKindSchema = valibot__rspack_import_0.union([
1484
+ valibot__rspack_import_0.literal('sequence'),
1485
+ valibot__rspack_import_0.literal('branch'),
1486
+ valibot__rspack_import_0.literal('merge'),
1487
+ valibot__rspack_import_0.literal('verifies'),
1488
+ valibot__rspack_import_0.literal('critiques'),
1489
+ valibot__rspack_import_0.literal('derives_from'),
1490
+ valibot__rspack_import_0.literal('tool_invocation'),
1491
+ valibot__rspack_import_0.literal('revises')
1492
+ ]);
1493
+ /**
1494
+ * Schema for {@link Edge} — a directed edge in the thought DAG.
1495
+ */ const EdgeSchema = valibot__rspack_import_0.object({
1496
+ id: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.maxLength(30)),
1497
+ from: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.maxLength(30)),
1498
+ to: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.maxLength(30)),
1499
+ kind: EdgeKindSchema,
1500
+ sessionId: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.minLength(1)),
1501
+ createdAt: valibot__rspack_import_0.number(),
1502
+ metadata: valibot__rspack_import_0.optional(valibot__rspack_import_0.record(valibot__rspack_import_0.string(), valibot__rspack_import_0.unknown()))
1503
+ });
1504
+
1505
+
1506
+ },
1507
+ 419(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1508
+
1509
+ // EXPORTS
1510
+ __webpack_require__.d(__webpack_exports__, {
1511
+ j: () => (/* binding */ BaseTransport)
1512
+ });
1513
+
1514
+ // EXTERNAL MODULE: external "node:crypto"
1515
+ var external_node_crypto_ = __webpack_require__(561);
1516
+ ;// CONCATENATED MODULE: ./src/core/ids.ts
1517
+ /**
1518
+ * Unique identifier generation utilities for thoughts and edges.
1519
+ *
1520
+ * @module core/ids
1521
+ */
1522
+ /**
1523
+ * Generate a unique lexicographically-sortable identifier.
1524
+ *
1525
+ * Format: 8-char base36 timestamp + 20-char hex random (10 random bytes).
1526
+ * Result is up to 28 characters, sortable by creation time.
1527
+ *
1528
+ * @returns A unique string identifier.
1529
+ *
1530
+ * @example
1531
+ * ```typescript
1532
+ * const id = generateUlid(); // '01h2k3m400a1b2c3d4e5f6...'
1533
+ * ```
1534
+ */ function generateUlid() {
1535
+ const timestamp = Date.now().toString(36).padStart(8, '0');
1536
+ const random = crypto.randomBytes(10).toString('hex');
1537
+ return `${timestamp}${random}`;
1538
+ }
1539
+ /**
1540
+ * Valid session ID pattern: alphanumeric, hyphens, underscores.
1541
+ *
1542
+ * Length is enforced separately via {@link MAX_SESSION_ID_LENGTH}.
1543
+ * Same character set as branch IDs.
1544
+ */ const SESSION_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
1545
+ /**
1546
+ * Maximum session ID length (in characters).
1547
+ *
1548
+ * Allows compound identifiers (e.g. `user-123_task-abc`).
1549
+ */ const MAX_SESSION_ID_LENGTH = 100;
1550
+
1551
+ ;// CONCATENATED MODULE: ./src/transport/BaseTransport.ts
1552
+ /**
1553
+ * Base transport implementation.
1554
+ *
1555
+ * This class provides shared functionality for all transport implementations,
1556
+ * including session validation, rate limiting, CORS handling, and IP extraction.
1557
+ *
1558
+ * @remarks
1559
+ * **Security Features:**
1560
+ * - Session ID validation (alphanumeric, max 64 chars)
1561
+ * - Query parameter sanitization (whitelist allowed keys)
1562
+ * - Rate limiting per IP (configurable, default 100 req/min)
1563
+ * - CORS origin validation
1564
+ *
1565
+ * **Rate Limiting:**
1566
+ * - Tracks requests per IP address within a time window
1567
+ * - Returns 429 Too Many Requests when limit exceeded
1568
+ * - Can be disabled via `enableRateLimit: false`
1569
+ */
1570
+ /**
1571
+ * No-op logger that does nothing. Used when no logger is provided.
1572
+ */ class NoopLogger {
1573
+ _level = 'info';
1574
+ info(_message, _meta) {}
1575
+ warn(_message, _meta) {}
1576
+ error(_message, _meta) {}
1577
+ debug(_message, _meta) {}
1578
+ setLevel(level) {
1579
+ this._level = level;
1580
+ }
1581
+ getLevel() {
1582
+ return this._level;
1583
+ }
1584
+ }
1585
+ /**
1586
+ * Allowed query parameter names (whitelist for security).
1587
+ */ const ALLOWED_QUERY_PARAMS = new Set([
1588
+ 'session',
1589
+ 'sessionId',
1590
+ 'client',
1591
+ 'clientId'
1592
+ ]);
1593
+ /**
1594
+ * Rate limit settings (requests per minute per IP).
1595
+ */ const RATE_LIMIT_REQUESTS = 100;
1596
+ const RATE_LIMIT_WINDOW_MS = 60 * 1000; // 1 minute
1597
+ class BaseTransport {
1598
+ _port;
1599
+ _host;
1600
+ _corsOrigin;
1601
+ _enableCors;
1602
+ _rateLimitEnabled;
1603
+ _maxRequestsPerMinute;
1604
+ _allowedHosts;
1605
+ _rateLimitMap = new Map();
1606
+ _rateLimitCleanupIntervalId = null;
1607
+ _wasHostExplicitlySet;
1608
+ /** Shutdown state for graceful shutdown. */ _isShuttingDown = false;
1609
+ _logger;
1610
+ _healthChecker;
1611
+ constructor(options = {}){
1612
+ this._port = options.port ?? 9108;
1613
+ this._host = options.host ?? '127.0.0.1';
1614
+ this._wasHostExplicitlySet = options.host !== undefined;
1615
+ this._corsOrigin = options.corsOrigin ?? '*';
1616
+ this._enableCors = options.enableCors ?? true;
1617
+ this._rateLimitEnabled = options.enableRateLimit ?? true;
1618
+ this._maxRequestsPerMinute = options.maxRequestsPerMinute ?? RATE_LIMIT_REQUESTS;
1619
+ this._allowedHosts = this._buildAllowedHosts(options.allowedHosts);
1620
+ this._isShuttingDown = false;
1621
+ this._logger = options.logger ?? new NoopLogger();
1622
+ this._healthChecker = options.healthChecker ?? null;
1623
+ if (this._rateLimitEnabled) {
1624
+ this._startRateLimitCleanup();
1625
+ }
1626
+ }
1627
+ /**
1628
+ * Get the server URL with localhost substitution for default host.
1629
+ */ get serverUrl() {
1630
+ const host = !this._wasHostExplicitlySet && this._host === '127.0.0.1' ? 'localhost' : this._host;
1631
+ return `http://${host}:${this._port}`;
1632
+ }
1633
+ /**
1634
+ * Validate session ID format.
1635
+ *
1636
+ * @param sessionId - The session ID to validate
1637
+ * @returns true if valid, false otherwise
1638
+ */ validateSessionId(sessionId) {
1639
+ if (sessionId.length > MAX_SESSION_ID_LENGTH) {
1640
+ return false;
1641
+ }
1642
+ return SESSION_ID_PATTERN.test(sessionId);
1643
+ }
1644
+ /**
1645
+ * Sanitize query parameters by removing any not in whitelist.
1646
+ *
1647
+ * @param url - The URL object containing query parameters
1648
+ * @returns A sanitized record of allowed query parameters
1649
+ */ sanitizeQueryParams(url) {
1650
+ const sanitized = {};
1651
+ for (const [key, value] of url.searchParams.entries()){
1652
+ if (ALLOWED_QUERY_PARAMS.has(key)) {
1653
+ sanitized[key] = value;
1654
+ }
1655
+ }
1656
+ return sanitized;
1657
+ }
1658
+ /**
1659
+ * Check rate limit for a given IP address.
1660
+ *
1661
+ * @param ip - The IP address to check
1662
+ * @returns true if rate limit exceeded, false otherwise
1663
+ */ checkRateLimit(ip) {
1664
+ if (!this._rateLimitEnabled) {
1665
+ return false;
1666
+ }
1667
+ const now = Date.now();
1668
+ this._cleanupExpiredRateLimitEntries(now);
1669
+ const record = this._rateLimitMap.get(ip);
1670
+ if (!record || now > record.resetTime) {
1671
+ this._rateLimitMap.set(ip, {
1672
+ count: 1,
1673
+ resetTime: now + RATE_LIMIT_WINDOW_MS
1674
+ });
1675
+ return false;
1676
+ }
1677
+ if (record.count >= this._maxRequestsPerMinute) {
1678
+ return true; // Rate limit exceeded
1679
+ }
1680
+ record.count++;
1681
+ return false;
1682
+ }
1683
+ _cleanupExpiredRateLimitEntries(now = Date.now()) {
1684
+ for (const [ip, record] of this._rateLimitMap.entries()){
1685
+ if (record.resetTime <= now) {
1686
+ this._rateLimitMap.delete(ip);
1687
+ }
1688
+ }
1689
+ }
1690
+ _startRateLimitCleanup() {
1691
+ if (this._rateLimitCleanupIntervalId !== null) {
1692
+ clearInterval(this._rateLimitCleanupIntervalId);
1693
+ }
1694
+ this._rateLimitCleanupIntervalId = setInterval(()=>{
1695
+ this._cleanupExpiredRateLimitEntries();
1696
+ }, RATE_LIMIT_WINDOW_MS);
1697
+ }
1698
+ _stopRateLimitCleanup() {
1699
+ if (this._rateLimitCleanupIntervalId !== null) {
1700
+ clearInterval(this._rateLimitCleanupIntervalId);
1701
+ this._rateLimitCleanupIntervalId = null;
1702
+ }
1703
+ }
1704
+ /**
1705
+ * Get client IP address from request.
1706
+ *
1707
+ * @param req - The incoming request
1708
+ * @returns The client IP address
1709
+ */ getClientIp(req) {
1710
+ const forwardedFor = req.headers['x-forwarded-for'];
1711
+ if (forwardedFor && typeof forwardedFor === 'string') {
1712
+ return forwardedFor.split(',')[0].trim();
1713
+ }
1714
+ const remoteAddress = req.socket.remoteAddress;
1715
+ return remoteAddress || 'unknown';
1716
+ }
1717
+ /**
1718
+ * Validate CORS origin from request headers.
1719
+ *
1720
+ * @param req - The incoming request
1721
+ * @returns true if origin is valid, false otherwise
1722
+ */ validateCorsOrigin(req) {
1723
+ if (this._corsOrigin === '*') {
1724
+ return true;
1725
+ }
1726
+ const origin = req.headers.origin;
1727
+ if (!origin) {
1728
+ return true; // No origin header is acceptable
1729
+ }
1730
+ // Exact match
1731
+ if (this._corsOrigin === origin) {
1732
+ return true;
1733
+ }
1734
+ // Check if configured origin is a wildcard pattern
1735
+ if (this._corsOrigin.includes('*')) {
1736
+ // Escape all regex metacharacters EXCEPT *,
1737
+ // then replace * with a hostname-safe pattern (alphanumeric, hyphens, dots)
1738
+ const escaped = this._corsOrigin.replace(/[.+?^${}()|[\]\\]/g, '\\$&') // escape metacharacters (not *)
1739
+ .replace(/\*/g, '[a-zA-Z0-9.-]*'); // * matches valid hostname chars only
1740
+ const regex = new RegExp(`^${escaped}$`);
1741
+ return regex.test(origin);
1742
+ }
1743
+ return false;
1744
+ }
1745
+ /**
1746
+ * Set CORS headers on response.
1747
+ *
1748
+ * @param res - The server response
1749
+ */ setCorsHeaders(res) {
1750
+ if (this._enableCors) {
1751
+ res.setHeader('Access-Control-Allow-Origin', this._corsOrigin);
1752
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
1753
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
1754
+ }
1755
+ }
1756
+ validateHostHeader(req) {
1757
+ const rawHost = req.headers.host;
1758
+ if (!rawHost) {
1759
+ return true;
1760
+ }
1761
+ const hostWithoutPort = rawHost.split(':')[0].trim().toLowerCase();
1762
+ if (!hostWithoutPort) {
1763
+ return false;
1764
+ }
1765
+ if (this._allowedHosts.size === 0) {
1766
+ return true;
1767
+ }
1768
+ return this._allowedHosts.has(hostWithoutPort);
1769
+ }
1770
+ _buildAllowedHosts(configuredHosts) {
1771
+ if (configuredHosts && configuredHosts.length > 0) {
1772
+ return new Set(configuredHosts.map((host)=>host.toLowerCase().trim()).filter(Boolean));
1773
+ }
1774
+ const boundHost = this._host.toLowerCase();
1775
+ const localHosts = [
1776
+ 'localhost',
1777
+ '127.0.0.1',
1778
+ '::1'
1779
+ ];
1780
+ if (localHosts.includes(boundHost)) {
1781
+ return new Set(localHosts);
1782
+ }
1783
+ if (boundHost === '0.0.0.0' || boundHost === '::') {
1784
+ return new Set(localHosts);
1785
+ }
1786
+ return new Set([
1787
+ boundHost
1788
+ ]);
1789
+ }
1790
+ /**
1791
+ * Log a message using the configured logger.
1792
+ *
1793
+ * @param level - Log level
1794
+ * @param message - Message to log
1795
+ * @param meta - Optional metadata
1796
+ */ log(level, message, meta) {
1797
+ if (level === 'info') {
1798
+ this._logger.info(message, meta);
1799
+ } else if (level === 'warn') {
1800
+ this._logger.warn(message, meta);
1801
+ } else {
1802
+ this._logger.error(message, meta);
1803
+ }
1804
+ }
1805
+ /**
1806
+ * Check if transport is shutting down.
1807
+ * @returns true if in shutdown phase
1808
+ */ get isShuttingDown() {
1809
+ return this._isShuttingDown;
1810
+ }
1811
+ /**
1812
+ * Handle GET /health endpoint — liveness check.
1813
+ *
1814
+ * Builds a standard health response with optional liveness data from the health checker.
1815
+ * Transports can pass extra data (e.g. client counts, session info).
1816
+ *
1817
+ * @param res - The server response
1818
+ * @param extraData - Optional additional health metadata
1819
+ */ handleHealthEndpoint(res, extraData) {
1820
+ const healthData = {
1821
+ status: 'healthy',
1822
+ ...extraData
1823
+ };
1824
+ if (this._healthChecker) {
1825
+ const liveness = this._healthChecker.checkLiveness();
1826
+ healthData.liveness = liveness;
1827
+ }
1828
+ res.writeHead(200, {
1829
+ 'Content-Type': 'application/json'
1830
+ });
1831
+ res.end(JSON.stringify(healthData));
1832
+ }
1833
+ /**
1834
+ * Handle GET /ready endpoint — readiness check.
1835
+ *
1836
+ * Delegates to the health checker if available, otherwise returns a default OK response.
1837
+ *
1838
+ * @param res - The server response
1839
+ */ async handleReadinessEndpoint(res) {
1840
+ if (this._healthChecker) {
1841
+ const readiness = await this._healthChecker.checkReadiness();
1842
+ const statusCode = readiness.status === 'ok' ? 200 : 503;
1843
+ res.writeHead(statusCode, {
1844
+ 'Content-Type': 'application/json'
1845
+ });
1846
+ res.end(JSON.stringify(readiness));
1847
+ } else {
1848
+ res.writeHead(200, {
1849
+ 'Content-Type': 'application/json'
1850
+ });
1851
+ res.end(JSON.stringify({
1852
+ status: 'ok',
1853
+ timestamp: new Date().toISOString(),
1854
+ components: {}
1855
+ }));
1856
+ }
1857
+ }
1858
+ /**
1859
+ * Handle GET /metrics endpoint — Prometheus metrics.
1860
+ *
1861
+ * Returns 404 if no metrics provider is configured.
1862
+ *
1863
+ * @param res - The server response
1864
+ * @param metricsProvider - Function that returns Prometheus-format metrics text
1865
+ */ handleMetricsEndpoint(res, metricsProvider) {
1866
+ if (!metricsProvider) {
1867
+ res.writeHead(404, {
1868
+ 'Content-Type': 'text/plain'
1869
+ });
1870
+ res.end('Not Found');
1871
+ return;
1872
+ }
1873
+ res.writeHead(200, {
1874
+ 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8'
1875
+ });
1876
+ res.end(metricsProvider());
1877
+ }
1878
+ }
1879
+
1880
+
1881
+ },
1882
+ 390(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1883
+ __webpack_require__.d(__webpack_exports__, {
1884
+ SseTransport: () => (SseTransport)
1885
+ });
1886
+ /* import */ var node_http__rspack_import_0 = __webpack_require__(316);
1887
+ /* import */ var node_url__rspack_import_1 = __webpack_require__(61);
1888
+ /* import */ var valibot__rspack_import_2 = __webpack_require__(821);
1889
+ /* import */ var _schema_js__rspack_import_3 = __webpack_require__(613);
1890
+ /* import */ var _BaseTransport_js__rspack_import_4 = __webpack_require__(419);
1891
+ /**
1892
+ * SSE (Server-Sent Events) Transport implementation.
1893
+ *
1894
+ * This transport allows multiple concurrent connections over HTTP using Server-Sent Events,
1895
+ * enabling multi-user scenarios and horizontal scaling.
1896
+ *
1897
+ * When a ConnectionPool is provided, each SSE client gets an isolated session with its own
1898
+ * thought history. Without a pool, all clients share a single server instance (backward compatible).
1899
+ *
1900
+ * @example
1901
+ * ```typescript
1902
+ * const transport = new SseTransport({
1903
+ * port: 3000,
1904
+ * host: 'localhost'
1905
+ * });
1906
+ * await transport.connect(server);
1907
+ * ```
1908
+ */
1909
+
1910
+
1911
+
1912
+
1913
+ /**
1914
+ * SSE Transport for MCP server over HTTP.
1915
+ *
1916
+ * This transport uses Server-Sent Events (SSE) to communicate with clients,
1917
+ * allowing multiple concurrent connections and web-based clients.
1918
+ *
1919
+ * @remarks
1920
+ * **Security Features:**
1921
+ * - Session ID validation (alphanumeric, max 64 chars)
1922
+ * - Query parameter sanitization (whitelist allowed keys)
1923
+ * - Rate limiting per IP (configurable, default 100 req/min)
1924
+ * - CORS origin validation
1925
+ *
1926
+ * **Rate Limiting:**
1927
+ * - Tracks requests per IP address within a time window
1928
+ * - Returns 429 Too Many Requests when limit exceeded
1929
+ * - Can be disabled via `enableRateLimit: false`
1930
+ */ class SseTransport extends _BaseTransport_js__rspack_import_4/* .BaseTransport */.j {
1931
+ get kind() {
1932
+ return 'sse';
1933
+ }
1934
+ _server;
1935
+ _path;
1936
+ _clients = new Set();
1937
+ _clientSessionMap = new Map();
1938
+ _messageQueue = new Map();
1939
+ _metrics;
1940
+ _connectionPool;
1941
+ constructor(options = {}){
1942
+ super(options);
1943
+ this._path = options.path ?? '/sse';
1944
+ this._metrics = options.metrics;
1945
+ this._connectionPool = options.connectionPool;
1946
+ this._updateActiveConnectionsMetric();
1947
+ this._server = (0,node_http__rspack_import_0.createServer)((req, res)=>this._handleRequest(req, res));
1948
+ }
1949
+ /**
1950
+ * Connect MCP server to this transport.
1951
+ *
1952
+ * @param mcpServer - The MCP server instance
1953
+ */ async connect(mcpServer) {
1954
+ this._mcpServer = mcpServer;
1955
+ return new Promise((resolve)=>{
1956
+ this._server.listen(this._port, this._host, ()=>{
1957
+ this.log('info', `SSE transport listening on http://${this._host}:${this._port}`);
1958
+ resolve();
1959
+ });
1960
+ });
1961
+ }
1962
+ _mcpServer = null;
1963
+ /**
1964
+ * Handle incoming HTTP requests
1965
+ */ async _handleRequest(req, res) {
1966
+ const startTime = Date.now();
1967
+ const requestPath = req.url || '/';
1968
+ const requestMethod = req.method || 'GET';
1969
+ this._metrics?.counter('http_requests_total', 1, {
1970
+ transport: 'sse',
1971
+ method: requestMethod,
1972
+ path: requestPath
1973
+ }, 'Total HTTP requests');
1974
+ res.once('finish', ()=>{
1975
+ const durationSeconds = (Date.now() - startTime) / 1000;
1976
+ this._metrics?.histogram('http_request_duration_seconds', durationSeconds, {
1977
+ transport: 'sse',
1978
+ path: requestPath
1979
+ });
1980
+ });
1981
+ if (!this.validateHostHeader(req)) {
1982
+ this._metrics?.counter('http_request_errors_total', 1, {
1983
+ transport: 'sse',
1984
+ error_type: 'forbidden'
1985
+ }, 'Total HTTP request errors');
1986
+ res.writeHead(403, {
1987
+ 'Content-Type': 'application/json'
1988
+ });
1989
+ res.end(JSON.stringify({
1990
+ error: 'Forbidden - invalid host header'
1991
+ }));
1992
+ return;
1993
+ }
1994
+ const url = new node_url__rspack_import_1.URL(req.url || '', `http://${req.headers.host}`);
1995
+ // Check rate limit first
1996
+ const clientIp = this.getClientIp(req);
1997
+ if (this.checkRateLimit(clientIp)) {
1998
+ this._metrics?.counter('http_request_errors_total', 1, {
1999
+ transport: 'sse',
2000
+ error_type: 'rate_limit'
2001
+ }, 'Total HTTP request errors');
2002
+ res.writeHead(429, {
2003
+ 'Content-Type': 'application/json',
2004
+ 'Retry-After': '60'
2005
+ });
2006
+ res.end(JSON.stringify({
2007
+ error: 'Too many requests'
2008
+ }));
2009
+ return;
2010
+ }
2011
+ // Validate CORS origin
2012
+ if (!this.validateCorsOrigin(req)) {
2013
+ this._metrics?.counter('http_request_errors_total', 1, {
2014
+ transport: 'sse',
2015
+ error_type: 'forbidden'
2016
+ }, 'Total HTTP request errors');
2017
+ res.writeHead(403, {
2018
+ 'Content-Type': 'application/json'
2019
+ });
2020
+ res.end(JSON.stringify({
2021
+ error: 'Forbidden - invalid origin'
2022
+ }));
2023
+ return;
2024
+ }
2025
+ // Set CORS headers
2026
+ this.setCorsHeaders(res);
2027
+ // Sanitize query parameters
2028
+ const sanitizedParams = this.sanitizeQueryParams(url);
2029
+ // Validate session ID if present
2030
+ if (sanitizedParams.session || sanitizedParams.sessionId) {
2031
+ const sessionId = sanitizedParams.session ?? sanitizedParams.sessionId;
2032
+ if (!this.validateSessionId(sessionId)) {
2033
+ this._metrics?.counter('http_request_errors_total', 1, {
2034
+ transport: 'sse',
2035
+ error_type: 'validation'
2036
+ }, 'Total HTTP request errors');
2037
+ res.writeHead(400, {
2038
+ 'Content-Type': 'application/json'
2039
+ });
2040
+ res.end(JSON.stringify({
2041
+ error: 'Invalid session ID format'
2042
+ }));
2043
+ return;
2044
+ }
2045
+ }
2046
+ // Handle CORS preflight
2047
+ if (this._enableCors && req.method === 'OPTIONS') {
2048
+ res.writeHead(204);
2049
+ res.end();
2050
+ return;
2051
+ }
2052
+ // Handle SSE endpoint
2053
+ if (url.pathname === this._path && req.method === 'GET') {
2054
+ await this._handleSseConnection(req, res, sanitizedParams);
2055
+ return;
2056
+ }
2057
+ // Handle message endpoint (for receiving messages from clients)
2058
+ if (url.pathname === `${this._path}/message` && req.method === 'POST') {
2059
+ await this._handleMessage(req, res, sanitizedParams);
2060
+ return;
2061
+ }
2062
+ // Handle health check (liveness)
2063
+ if (url.pathname === '/health') {
2064
+ this._handleHealthCheck(res);
2065
+ return;
2066
+ }
2067
+ // Handle readiness check
2068
+ if (url.pathname === '/ready') {
2069
+ await this._handleReadinessCheck(res);
2070
+ return;
2071
+ }
2072
+ // 404 for unknown paths
2073
+ res.writeHead(404, {
2074
+ 'Content-Type': 'text/plain'
2075
+ });
2076
+ res.end('Not Found');
2077
+ }
2078
+ /**
2079
+ * Handle health check (liveness) endpoint
2080
+ */ _handleHealthCheck(res) {
2081
+ const healthData = {
2082
+ status: 'healthy',
2083
+ clients: this._clients.size
2084
+ };
2085
+ if (this._connectionPool) {
2086
+ const poolStats = this._connectionPool.getStats();
2087
+ healthData.pool = poolStats;
2088
+ }
2089
+ if (this._healthChecker) {
2090
+ const liveness = this._healthChecker.checkLiveness();
2091
+ healthData.liveness = liveness;
2092
+ }
2093
+ res.writeHead(200, {
2094
+ 'Content-Type': 'application/json'
2095
+ });
2096
+ res.end(JSON.stringify(healthData));
2097
+ }
2098
+ /**
2099
+ * Handle readiness check endpoint
2100
+ */ async _handleReadinessCheck(res) {
2101
+ if (this._healthChecker) {
2102
+ const readiness = await this._healthChecker.checkReadiness();
2103
+ const statusCode = readiness.status === 'ok' ? 200 : 503;
2104
+ res.writeHead(statusCode, {
2105
+ 'Content-Type': 'application/json'
2106
+ });
2107
+ res.end(JSON.stringify(readiness));
2108
+ } else {
2109
+ res.writeHead(200, {
2110
+ 'Content-Type': 'application/json'
2111
+ });
2112
+ res.end(JSON.stringify({
2113
+ status: 'ok',
2114
+ timestamp: new Date().toISOString(),
2115
+ components: {}
2116
+ }));
2117
+ }
2118
+ }
2119
+ /**
2120
+ * Handle new SSE connection
2121
+ */ async _handleSseConnection(req, res, params) {
2122
+ // Set SSE headers
2123
+ res.writeHead(200, {
2124
+ 'Content-Type': 'text/event-stream',
2125
+ 'Cache-Control': 'no-cache',
2126
+ Connection: 'keep-alive'
2127
+ });
2128
+ // Resolve session ID when pool is active
2129
+ let sessionId;
2130
+ if (this._connectionPool) {
2131
+ const requestedSession = params.session ?? params.sessionId;
2132
+ if (requestedSession && this._connectionPool.getSessionInfo(requestedSession)) {
2133
+ sessionId = requestedSession;
2134
+ } else {
2135
+ try {
2136
+ sessionId = await this._connectionPool.createSession();
2137
+ } catch (error) {
2138
+ res.write(`event: error\n`);
2139
+ res.write(`data: ${JSON.stringify({
2140
+ error: error instanceof Error ? error.message : 'Failed to create session'
2141
+ })}\n\n`);
2142
+ res.end();
2143
+ return;
2144
+ }
2145
+ }
2146
+ this._clientSessionMap.set(res, sessionId);
2147
+ this._updatePoolMetrics();
2148
+ }
2149
+ // Send initial connection event
2150
+ const connectedPayload = {
2151
+ timestamp: Date.now()
2152
+ };
2153
+ if (sessionId) {
2154
+ connectedPayload.sessionId = sessionId;
2155
+ }
2156
+ this._sendSseEvent(res, 'connected', connectedPayload);
2157
+ // Add to clients
2158
+ this._clients.add(res);
2159
+ this._updateActiveConnectionsMetric();
2160
+ // Handle client disconnect
2161
+ req.on('close', ()=>{
2162
+ this._clients.delete(res);
2163
+ this._clientSessionMap.delete(res);
2164
+ this._updateActiveConnectionsMetric();
2165
+ });
2166
+ // Send any queued messages
2167
+ const clientId = this._generateClientId();
2168
+ const queued = this._messageQueue.get(clientId);
2169
+ if (queued) {
2170
+ for (const message of queued){
2171
+ this._sendSseEvent(res, 'message', message);
2172
+ }
2173
+ this._messageQueue.delete(clientId);
2174
+ }
2175
+ }
2176
+ /**
2177
+ * Handle incoming message from client
2178
+ */ async _handleMessage(req, res, _params) {
2179
+ let body = '';
2180
+ for await (const chunk of req){
2181
+ body += chunk.toString();
2182
+ }
2183
+ try {
2184
+ const jsonRpcRequest = JSON.parse(body);
2185
+ const parseResult = (0,valibot__rspack_import_2.safeParse)(_schema_js__rspack_import_3/* .JsonRpcRequestSchema */.Uv, jsonRpcRequest);
2186
+ if (!parseResult.success) {
2187
+ this._metrics?.counter('http_request_errors_total', 1, {
2188
+ transport: 'sse',
2189
+ error_type: 'validation'
2190
+ }, 'Total HTTP request errors');
2191
+ res.writeHead(200, {
2192
+ 'Content-Type': 'application/json'
2193
+ });
2194
+ res.end(JSON.stringify({
2195
+ jsonrpc: '2.0',
2196
+ id: jsonRpcRequest?.id ?? null,
2197
+ error: {
2198
+ code: -32600,
2199
+ message: 'Invalid Request',
2200
+ data: parseResult.issues
2201
+ }
2202
+ }));
2203
+ return;
2204
+ }
2205
+ // Process message through MCP server
2206
+ if (this._mcpServer) {
2207
+ const response = await this._mcpServer.receive(jsonRpcRequest, {
2208
+ sessionInfo: {}
2209
+ });
2210
+ res.writeHead(200, {
2211
+ 'Content-Type': 'application/json'
2212
+ });
2213
+ if (response) {
2214
+ res.end(JSON.stringify(response));
2215
+ } else {
2216
+ res.end(JSON.stringify({
2217
+ jsonrpc: '2.0',
2218
+ id: jsonRpcRequest?.id ?? null,
2219
+ result: null
2220
+ }));
2221
+ }
2222
+ } else {
2223
+ this._metrics?.counter('http_request_errors_total', 1, {
2224
+ transport: 'sse',
2225
+ error_type: 'server_not_ready'
2226
+ }, 'Total HTTP request errors');
2227
+ res.writeHead(503, {
2228
+ 'Content-Type': 'application/json'
2229
+ });
2230
+ res.end(JSON.stringify({
2231
+ error: 'Server not ready'
2232
+ }));
2233
+ }
2234
+ } catch {
2235
+ this._metrics?.counter('http_request_errors_total', 1, {
2236
+ transport: 'sse',
2237
+ error_type: 'parse_error'
2238
+ }, 'Total HTTP request errors');
2239
+ res.writeHead(400, {
2240
+ 'Content-Type': 'application/json'
2241
+ });
2242
+ res.end(JSON.stringify({
2243
+ error: 'Invalid JSON'
2244
+ }));
2245
+ }
2246
+ }
2247
+ /**
2248
+ * Send an SSE event to a specific client
2249
+ */ _sendSseEvent(res, event, data) {
2250
+ try {
2251
+ res.write(`event: ${event}\n`);
2252
+ res.write(`data: ${JSON.stringify(data)}\n\n`);
2253
+ } catch {
2254
+ // Client disconnected
2255
+ this._clients.delete(res);
2256
+ this._updateActiveConnectionsMetric();
2257
+ }
2258
+ }
2259
+ _updateActiveConnectionsMetric() {
2260
+ this._metrics?.gauge('sse_active_connections', this._clients.size, {}, 'Current active SSE connections');
2261
+ }
2262
+ _updatePoolMetrics() {
2263
+ if (!this._connectionPool || !this._metrics) {
2264
+ return;
2265
+ }
2266
+ const stats = this._connectionPool.getStats();
2267
+ this._metrics.gauge('sse_pool_active_sessions', stats.activeSessions, {}, 'Active sessions in connection pool');
2268
+ this._metrics.gauge('sse_pool_total_sessions', stats.totalSessions, {}, 'Total sessions in connection pool');
2269
+ this._metrics.gauge('sse_pool_max_sessions', stats.maxSessions, {}, 'Maximum sessions in connection pool');
2270
+ }
2271
+ /**
2272
+ * Broadcast a message to all connected clients
2273
+ */ broadcast(event, data) {
2274
+ for (const client of this._clients){
2275
+ this._sendSseEvent(client, event, data);
2276
+ }
2277
+ }
2278
+ /**
2279
+ * Generate a unique client ID
2280
+ */ _generateClientId() {
2281
+ return `client_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
2282
+ }
2283
+ /**
2284
+ * Get number of connected clients
2285
+ */ get clientCount() {
2286
+ return this._clients.size;
2287
+ }
2288
+ /**
2289
+ * Get the connection pool, if one was configured.
2290
+ */ get connectionPool() {
2291
+ return this._connectionPool;
2292
+ }
2293
+ /**
2294
+ * Stop the transport server with graceful shutdown.
2295
+ *
2296
+ * @param timeout - Maximum time to wait for requests to drain (not used for SSE)
2297
+ * @returns Promise that resolves when shutdown is complete
2298
+ */ async stop(_timeout) {
2299
+ this._isShuttingDown = true;
2300
+ this._stopRateLimitCleanup();
2301
+ // Terminate connection pool if present
2302
+ if (this._connectionPool) {
2303
+ await this._connectionPool.terminate();
2304
+ }
2305
+ return new Promise((resolve)=>{
2306
+ // Close all client connections
2307
+ for (const client of this._clients){
2308
+ try {
2309
+ client.end();
2310
+ } catch {
2311
+ // Ignore errors
2312
+ }
2313
+ }
2314
+ this._clients.clear();
2315
+ this._clientSessionMap.clear();
2316
+ this._updateActiveConnectionsMetric();
2317
+ // Close server
2318
+ this._server.close(()=>{
2319
+ this.log('info', 'SSE transport stopped');
2320
+ resolve();
2321
+ });
2322
+ });
2323
+ }
2324
+ }
2325
+ /**
2326
+ * Create an SSE transport with given options.
2327
+ *
2328
+ * @param options - Transport configuration
2329
+ * @returns A configured SSE transport
2330
+ *
2331
+ * @example
2332
+ * ```typescript
2333
+ * const transport = createSseTransport({ port: 3000 });
2334
+ * await transport.connect(mcpServer);
2335
+ * ```
2336
+ */ function createSseTransport(options = {}) {
2337
+ return new SseTransport(options);
2338
+ }
2339
+
2340
+
2341
+ },
2342
+ 34(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
2343
+
2344
+ // EXPORTS
2345
+ __webpack_require__.d(__webpack_exports__, {
2346
+ StreamableHttpTransport: () => (/* binding */ StreamableHttpTransport)
2347
+ });
2348
+
2349
+ // UNUSED EXPORTS: createStreamableHttpTransport
2350
+
2351
+ // EXTERNAL MODULE: external "node:crypto"
2352
+ var external_node_crypto_ = __webpack_require__(561);
2353
+ // EXTERNAL MODULE: external "node:http"
2354
+ var external_node_http_ = __webpack_require__(316);
2355
+ // EXTERNAL MODULE: external "valibot"
2356
+ var external_valibot_ = __webpack_require__(821);
2357
+ // EXTERNAL MODULE: ./src/errors.ts
2358
+ var errors = __webpack_require__(937);
2359
+ // EXTERNAL MODULE: ./src/schema.ts
2360
+ var schema = __webpack_require__(613);
2361
+ // EXTERNAL MODULE: ./src/transport/BaseTransport.ts + 1 modules
2362
+ var BaseTransport = __webpack_require__(419);
2363
+ ;// CONCATENATED MODULE: ./src/transport/HttpHelpers.ts
2364
+ /**
2365
+ * Shared HTTP helper utilities for MCP transport implementations.
2366
+ *
2367
+ * Centralizes JSON-RPC response formatting, request body reading,
2368
+ * and common HTTP response patterns to eliminate duplication across
2369
+ * HttpTransport, StreamableHttpTransport, and SseTransport.
2370
+ *
2371
+ * @module transport/HttpHelpers
2372
+ */ /**
2373
+ * Send a JSON-RPC 2.0 error response.
2374
+ *
2375
+ * Standardizes error response formatting across all transport implementations.
2376
+ * All JSON-RPC errors use the standard `{ jsonrpc, id, error }` shape.
2377
+ *
2378
+ * @param res - The server response to write to
2379
+ * @param statusCode - HTTP status code (e.g. 400, 403, 429, 500)
2380
+ * @param code - JSON-RPC error code (e.g. -32700, -32600, -32603)
2381
+ * @param message - Human-readable error message
2382
+ * @param id - Optional JSON-RPC request ID (defaults to null)
2383
+ * @param data - Optional additional error data
2384
+ */ function sendJsonRpcError(res, statusCode, code, message, id = null, data) {
2385
+ const body = {
2386
+ jsonrpc: '2.0',
2387
+ id,
2388
+ error: {
2389
+ code,
2390
+ message
2391
+ }
2392
+ };
2393
+ if (data !== undefined) {
2394
+ body.error.data = data;
2395
+ }
2396
+ res.writeHead(statusCode, {
2397
+ 'Content-Type': 'application/json'
2398
+ });
2399
+ res.end(JSON.stringify(body));
2400
+ }
2401
+ /**
2402
+ * Send a JSON-RPC 2.0 success response.
2403
+ *
2404
+ * @param res - The server response to write to
2405
+ * @param response - The JSON-RPC response object to send
2406
+ * @param statusCode - HTTP status code (default: 200)
2407
+ * @param headers - Optional additional response headers
2408
+ */ function sendJsonRpcResponse(res, response, statusCode = 200, headers = {}) {
2409
+ const defaultHeaders = {
2410
+ 'Content-Type': 'application/json'
2411
+ };
2412
+ res.writeHead(statusCode, {
2413
+ ...defaultHeaders,
2414
+ ...headers
2415
+ });
2416
+ res.end(JSON.stringify(response));
2417
+ }
2418
+ /**
2419
+ * Send a CORS preflight (OPTIONS) response.
2420
+ *
2421
+ * @param res - The server response to write to
2422
+ * @param extraAllowHeaders - Optional extra Access-Control-Allow-Headers values
2423
+ */ function sendCorsPreflight(res, extraAllowHeaders) {
2424
+ if (extraAllowHeaders && extraAllowHeaders.length > 0) {
2425
+ res.setHeader('Access-Control-Allow-Headers', `Content-Type, ${extraAllowHeaders.join(', ')}`);
2426
+ }
2427
+ res.writeHead(204);
2428
+ res.end();
2429
+ }
2430
+ /**
2431
+ * Read the full request body with optional size limit enforcement.
2432
+ *
2433
+ * Streams the request body chunks, tracking total size.
2434
+ * If the body exceeds `maxBodySize`, reading stops and `null` is returned
2435
+ * to indicate the payload is too large.
2436
+ *
2437
+ * @param req - The incoming HTTP request
2438
+ * @param maxBodySize - Maximum allowed body size in bytes (0 = unlimited)
2439
+ * @returns The body string, or `null` if the body exceeded the size limit
2440
+ */ async function readRequestBody(req, maxBodySize) {
2441
+ let body = '';
2442
+ let bodySize = 0;
2443
+ for await (const chunk of req){
2444
+ const chunkStr = typeof chunk === 'string' ? chunk : chunk.toString();
2445
+ bodySize += chunkStr.length;
2446
+ if (maxBodySize > 0 && bodySize > maxBodySize) {
2447
+ return null;
2448
+ }
2449
+ body += chunkStr;
2450
+ }
2451
+ return body;
2452
+ }
2453
+
2454
+ ;// CONCATENATED MODULE: ./src/transport/StreamableHttpTransport.ts
2455
+ /**
2456
+ * Streamable HTTP Transport implementation (MCP spec recommended transport).
2457
+ *
2458
+ * This transport implements the MCP Streamable HTTP specification, which replaces
2459
+ * the deprecated SSE transport as the recommended HTTP-based transport since March 2025.
2460
+ *
2461
+ * Key features:
2462
+ * - POST /mcp for JSON-RPC requests (main MCP endpoint)
2463
+ * - GET /mcp for optional SSE server-to-client notifications
2464
+ * - Session management via Mcp-Session-Id header
2465
+ * - Supports both stateful (session-based) and stateless (per-request) modes
2466
+ * - Health endpoints (/health, /ready)
2467
+ *
2468
+ * @example
2469
+ * ```typescript
2470
+ * const transport = new StreamableHttpTransport({
2471
+ * port: 3000,
2472
+ * host: 'localhost',
2473
+ * stateful: true,
2474
+ * });
2475
+ * await transport.connect(server);
2476
+ * ```
2477
+ */
2478
+
2479
+
2480
+
2481
+
2482
+
2483
+
2484
+ /**
2485
+ * Streamable HTTP Transport for MCP server.
2486
+ *
2487
+ * This transport implements the MCP Streamable HTTP specification,
2488
+ * providing JSON-RPC over HTTP with optional session management
2489
+ * and server-to-client SSE notification streams.
2490
+ *
2491
+ * @remarks
2492
+ * **Security Features (inherited from BaseTransport):**
2493
+ * - Session ID validation (alphanumeric, max 64 chars)
2494
+ * - Query parameter sanitization (whitelist allowed keys)
2495
+ * - Rate limiting per IP (configurable, default 100 req/min)
2496
+ * - CORS origin validation
2497
+ * - Host header validation
2498
+ *
2499
+ * **MCP Streamable HTTP Spec Compliance:**
2500
+ * - POST /mcp — JSON-RPC method calls
2501
+ * - GET /mcp — SSE notification stream (server-to-client)
2502
+ * - Mcp-Session-Id header for session management
2503
+ * - Content-Type: application/json for JSON-RPC responses
2504
+ * - Content-Type: text/event-stream for SSE notification streams
2505
+ *
2506
+ * **HTTP Status Code Mapping:**
2507
+ * - 200: Success (JSON-RPC response or SSE stream)
2508
+ * - 202: Accepted (JSON-RPC notification, no response body)
2509
+ * - 204: CORS Preflight (empty body)
2510
+ * - 400: Bad Request (invalid JSON, invalid session ID)
2511
+ * - 403: Forbidden (invalid CORS, invalid host)
2512
+ * - 404: Not Found
2513
+ * - 405: Method Not Allowed
2514
+ * - 413: Payload Too Large
2515
+ * - 429: Too Many Requests
2516
+ * - 500: Internal Server Error
2517
+ * - 503: Server Not Ready / Shutting Down
2518
+ */ class StreamableHttpTransport extends BaseTransport/* .BaseTransport */.j {
2519
+ get kind() {
2520
+ return 'streamable-http';
2521
+ }
2522
+ _server = null;
2523
+ _mcpServer = null;
2524
+ _path;
2525
+ _stateful;
2526
+ _sessionIdGenerator;
2527
+ _sessions = new Map();
2528
+ _requestCount = 0;
2529
+ _activeRequests = 0;
2530
+ _bodySizeLimitEnabled;
2531
+ _maxBodySize;
2532
+ _requestTimeout;
2533
+ _metrics;
2534
+ _metricsProvider;
2535
+ constructor(options = {}){
2536
+ super(options);
2537
+ this._path = options.path ?? '/mcp';
2538
+ this._stateful = options.stateful ?? true;
2539
+ this._sessionIdGenerator = options.sessionIdGenerator ?? (()=>(0,external_node_crypto_.randomUUID)());
2540
+ this._bodySizeLimitEnabled = options.enableBodySizeLimit ?? true;
2541
+ this._maxBodySize = options.maxBodySize ?? 10 * 1024 * 1024;
2542
+ this._requestTimeout = options.requestTimeout ?? 30000;
2543
+ this._metrics = options.metrics;
2544
+ this._metricsProvider = options.metricsProvider ?? null;
2545
+ }
2546
+ /**
2547
+ * Get number of active sessions (stateful) or active requests (stateless).
2548
+ */ get clientCount() {
2549
+ return this._stateful ? this._sessions.size : this._activeRequests;
2550
+ }
2551
+ /**
2552
+ * Get the total number of requests handled.
2553
+ */ get requestCount() {
2554
+ return this._requestCount;
2555
+ }
2556
+ /**
2557
+ * Connects MCP server to this transport and starts listening.
2558
+ */ async connect(mcpServer) {
2559
+ this._mcpServer = mcpServer;
2560
+ this._server = (0,external_node_http_.createServer)((req, res)=>this._handleRequest(req, res));
2561
+ return new Promise((resolve)=>{
2562
+ this._server.listen(this._port, this._host, ()=>{
2563
+ this.log('info', `Streamable HTTP transport listening on http://${this._host}:${this._port}`);
2564
+ resolve();
2565
+ });
2566
+ });
2567
+ }
2568
+ /**
2569
+ * Route and handle incoming HTTP requests.
2570
+ */ async _handleRequest(req, res) {
2571
+ const startTime = Date.now();
2572
+ this._metrics?.counter('streamable_http_requests_total', 1, {}, 'Total Streamable HTTP transport requests');
2573
+ res.once('finish', ()=>{
2574
+ const durationSeconds = (Date.now() - startTime) / 1000;
2575
+ this._metrics?.histogram('streamable_http_request_duration_seconds', durationSeconds, {});
2576
+ });
2577
+ // Host validation
2578
+ if (!this.validateHostHeader(req)) {
2579
+ this._sendJsonRpcError(res, 403, -32000, 'Forbidden - invalid host header');
2580
+ return;
2581
+ }
2582
+ // Shutdown check
2583
+ if (this.isShuttingDown) {
2584
+ this._sendJsonRpcError(res, 503, -32603, 'Server is shutting down');
2585
+ return;
2586
+ }
2587
+ // Rate limiting
2588
+ const clientIp = this.getClientIp(req);
2589
+ if (this.checkRateLimit(clientIp)) {
2590
+ res.setHeader('Retry-After', '60');
2591
+ this._sendJsonRpcError(res, 429, -32000, 'Too many requests');
2592
+ return;
2593
+ }
2594
+ // CORS validation
2595
+ if (!this.validateCorsOrigin(req)) {
2596
+ this._sendJsonRpcError(res, 403, -32000, 'Forbidden - invalid origin');
2597
+ return;
2598
+ }
2599
+ this.setCorsHeaders(res);
2600
+ // CORS preflight
2601
+ if (req.method === 'OPTIONS') {
2602
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Mcp-Session-Id');
2603
+ res.writeHead(204);
2604
+ res.end();
2605
+ return;
2606
+ }
2607
+ // Parse URL path
2608
+ const urlPath = req.url?.split('?')[0] ?? '/';
2609
+ // Metrics endpoint
2610
+ if (req.method === 'GET' && urlPath === '/metrics') {
2611
+ this._handleMetrics(res);
2612
+ return;
2613
+ }
2614
+ // Health check (liveness)
2615
+ if (req.method === 'GET' && urlPath === '/health') {
2616
+ this._handleHealthCheck(res);
2617
+ return;
2618
+ }
2619
+ // Readiness check
2620
+ if (req.method === 'GET' && urlPath === '/ready') {
2621
+ await this._handleReadinessCheck(res);
2622
+ return;
2623
+ }
2624
+ // MCP endpoint routing
2625
+ if (urlPath === this._path) {
2626
+ if (req.method === 'POST') {
2627
+ await this._handleMcpPost(req, res);
2628
+ return;
2629
+ }
2630
+ if (req.method === 'GET') {
2631
+ this._handleMcpGet(req, res);
2632
+ return;
2633
+ }
2634
+ res.writeHead(405, {
2635
+ 'Content-Type': 'application/json',
2636
+ Allow: 'GET, POST'
2637
+ });
2638
+ res.end(JSON.stringify({
2639
+ jsonrpc: '2.0',
2640
+ id: null,
2641
+ error: {
2642
+ code: -32601,
2643
+ message: 'Method not allowed'
2644
+ }
2645
+ }));
2646
+ return;
2647
+ }
2648
+ // 404 for unknown paths
2649
+ this._sendJsonRpcError(res, 404, -32601, 'Not Found');
2650
+ }
2651
+ /**
2652
+ * Send a JSON-RPC error response.
2653
+ */ _sendJsonRpcError(res, statusCode, code, message, id = null, extra) {
2654
+ const error = {
2655
+ code,
2656
+ message
2657
+ };
2658
+ if (extra) {
2659
+ Object.assign(error, extra);
2660
+ }
2661
+ res.writeHead(statusCode, {
2662
+ 'Content-Type': 'application/json'
2663
+ });
2664
+ res.end(JSON.stringify({
2665
+ jsonrpc: '2.0',
2666
+ id,
2667
+ error
2668
+ }));
2669
+ }
2670
+ /**
2671
+ * Handle POST /mcp — JSON-RPC method calls.
2672
+ *
2673
+ * Per the MCP Streamable HTTP spec:
2674
+ * - Accepts JSON-RPC request bodies
2675
+ * - Returns Mcp-Session-Id header for new sessions (stateful mode)
2676
+ * - Validates Mcp-Session-Id for existing sessions (stateful mode)
2677
+ * - Content-Type: application/json for responses
2678
+ */ async _handleMcpPost(req, res) {
2679
+ this._requestCount++;
2680
+ this._activeRequests++;
2681
+ const timeout = setTimeout(()=>{
2682
+ this._activeRequests--;
2683
+ this._sendJsonRpcError(res, 500, -32603, 'Request timeout');
2684
+ }, this._requestTimeout);
2685
+ try {
2686
+ // Read request body with size limit
2687
+ const body = await readRequestBody(req, this._bodySizeLimitEnabled ? this._maxBodySize : 0);
2688
+ if (body === null) {
2689
+ clearTimeout(timeout);
2690
+ this._activeRequests--;
2691
+ this._sendJsonRpcError(res, 413, -32000, 'Request body too large');
2692
+ return;
2693
+ }
2694
+ // Parse JSON
2695
+ let jsonRpcRequest;
2696
+ try {
2697
+ jsonRpcRequest = JSON.parse(body);
2698
+ } catch {
2699
+ clearTimeout(timeout);
2700
+ this._activeRequests--;
2701
+ this._sendJsonRpcError(res, 200, -32700, 'Parse error');
2702
+ return;
2703
+ }
2704
+ // Validate JSON-RPC schema
2705
+ const parseResult = (0,external_valibot_.safeParse)(schema/* .JsonRpcRequestSchema */.Uv, jsonRpcRequest);
2706
+ if (!parseResult.success) {
2707
+ clearTimeout(timeout);
2708
+ this._activeRequests--;
2709
+ this._sendJsonRpcError(res, 200, -32600, 'Invalid Request', jsonRpcRequest?.id ?? null, {
2710
+ data: parseResult.issues
2711
+ });
2712
+ return;
2713
+ }
2714
+ // Session management (stateful mode)
2715
+ let sessionId;
2716
+ if (this._stateful) {
2717
+ const sessionResult = this._resolveSession(req, res);
2718
+ if (sessionResult === false) {
2719
+ clearTimeout(timeout);
2720
+ this._activeRequests--;
2721
+ return;
2722
+ }
2723
+ sessionId = sessionResult;
2724
+ }
2725
+ // Check if MCP server is ready
2726
+ if (!this._mcpServer) {
2727
+ clearTimeout(timeout);
2728
+ this._activeRequests--;
2729
+ this._sendJsonRpcError(res, 503, -32603, 'Server not ready', jsonRpcRequest?.id ?? null);
2730
+ return;
2731
+ }
2732
+ // Process JSON-RPC request through MCP server
2733
+ const response = await this._mcpServer.receive(jsonRpcRequest, {
2734
+ sessionInfo: {}
2735
+ });
2736
+ clearTimeout(timeout);
2737
+ this._activeRequests--;
2738
+ // Send response with session header if applicable
2739
+ const responseHeaders = {
2740
+ 'Content-Type': 'application/json'
2741
+ };
2742
+ if (sessionId) responseHeaders['Mcp-Session-Id'] = sessionId;
2743
+ if (response) {
2744
+ res.writeHead(200, responseHeaders);
2745
+ res.end(JSON.stringify(response));
2746
+ } else {
2747
+ if (sessionId) res.setHeader('Mcp-Session-Id', sessionId);
2748
+ res.writeHead(202);
2749
+ res.end();
2750
+ }
2751
+ } catch (error) {
2752
+ clearTimeout(timeout);
2753
+ this._activeRequests--;
2754
+ this._sendJsonRpcError(res, 200, -32603, 'Internal error', null, {
2755
+ data: (0,errors/* .getErrorMessage */.u1)(error)
2756
+ });
2757
+ }
2758
+ }
2759
+ /**
2760
+ * Handle GET /mcp — Optional SSE notification stream.
2761
+ *
2762
+ * Per the MCP Streamable HTTP spec, clients may open a GET request
2763
+ * to receive server-initiated notifications as SSE events.
2764
+ * Requires a valid Mcp-Session-Id in stateful mode.
2765
+ */ _handleMcpGet(req, res) {
2766
+ if (!this._stateful) {
2767
+ // SSE notification streams require stateful mode
2768
+ res.writeHead(405, {
2769
+ 'Content-Type': 'application/json',
2770
+ Allow: 'POST'
2771
+ });
2772
+ res.end(JSON.stringify({
2773
+ jsonrpc: '2.0',
2774
+ id: null,
2775
+ error: {
2776
+ code: -32601,
2777
+ message: 'GET not supported in stateless mode'
2778
+ }
2779
+ }));
2780
+ return;
2781
+ }
2782
+ // Require Mcp-Session-Id for GET requests
2783
+ const sessionId = this._getSessionIdFromHeader(req);
2784
+ if (!sessionId) {
2785
+ res.writeHead(400, {
2786
+ 'Content-Type': 'application/json'
2787
+ });
2788
+ res.end(JSON.stringify({
2789
+ jsonrpc: '2.0',
2790
+ id: null,
2791
+ error: {
2792
+ code: -32600,
2793
+ message: 'Missing Mcp-Session-Id header'
2794
+ }
2795
+ }));
2796
+ return;
2797
+ }
2798
+ const session = this._sessions.get(sessionId);
2799
+ if (!session) {
2800
+ res.writeHead(404, {
2801
+ 'Content-Type': 'application/json'
2802
+ });
2803
+ res.end(JSON.stringify({
2804
+ jsonrpc: '2.0',
2805
+ id: null,
2806
+ error: {
2807
+ code: -32001,
2808
+ message: 'Session not found'
2809
+ }
2810
+ }));
2811
+ return;
2812
+ }
2813
+ // Set SSE headers
2814
+ res.writeHead(200, {
2815
+ 'Content-Type': 'text/event-stream',
2816
+ 'Cache-Control': 'no-cache',
2817
+ Connection: 'keep-alive',
2818
+ 'Mcp-Session-Id': sessionId
2819
+ });
2820
+ // Send initial connected event
2821
+ this._sendSseEvent(res, 'connected', {
2822
+ sessionId,
2823
+ timestamp: Date.now()
2824
+ });
2825
+ // Track this notification stream
2826
+ session.notificationStreams.add(res);
2827
+ session.lastActivityAt = Date.now();
2828
+ this._updateSessionMetrics();
2829
+ // Handle client disconnect
2830
+ req.on('close', ()=>{
2831
+ session.notificationStreams.delete(res);
2832
+ this._updateSessionMetrics();
2833
+ });
2834
+ }
2835
+ /**
2836
+ * Resolve or create a session for a stateful request.
2837
+ *
2838
+ * @returns Session ID string on success, or `false` if the response was already sent (error).
2839
+ */ _resolveSession(req, res) {
2840
+ const headerSessionId = this._getSessionIdFromHeader(req);
2841
+ if (headerSessionId) {
2842
+ // Validate format
2843
+ if (!this.validateSessionId(headerSessionId)) {
2844
+ res.writeHead(400, {
2845
+ 'Content-Type': 'application/json'
2846
+ });
2847
+ res.end(JSON.stringify({
2848
+ jsonrpc: '2.0',
2849
+ id: null,
2850
+ error: {
2851
+ code: -32600,
2852
+ message: 'Invalid Mcp-Session-Id format'
2853
+ }
2854
+ }));
2855
+ return false;
2856
+ }
2857
+ // Check if session exists
2858
+ const session = this._sessions.get(headerSessionId);
2859
+ if (session) {
2860
+ session.lastActivityAt = Date.now();
2861
+ return headerSessionId;
2862
+ }
2863
+ // Unknown session ID — per spec, return 404
2864
+ res.writeHead(404, {
2865
+ 'Content-Type': 'application/json'
2866
+ });
2867
+ res.end(JSON.stringify({
2868
+ jsonrpc: '2.0',
2869
+ id: null,
2870
+ error: {
2871
+ code: -32001,
2872
+ message: 'Session not found'
2873
+ }
2874
+ }));
2875
+ return false;
2876
+ }
2877
+ // No session header — create new session
2878
+ const newSessionId = this._sessionIdGenerator();
2879
+ const sessionState = {
2880
+ id: newSessionId,
2881
+ createdAt: Date.now(),
2882
+ lastActivityAt: Date.now(),
2883
+ notificationStreams: new Set()
2884
+ };
2885
+ this._sessions.set(newSessionId, sessionState);
2886
+ this.log('info', `New session created: ${newSessionId}`);
2887
+ this._updateSessionMetrics();
2888
+ return newSessionId;
2889
+ }
2890
+ /**
2891
+ * Extract Mcp-Session-Id from request headers.
2892
+ */ _getSessionIdFromHeader(req) {
2893
+ const value = req.headers['mcp-session-id'];
2894
+ if (typeof value === 'string' && value.length > 0) {
2895
+ return value;
2896
+ }
2897
+ return undefined;
2898
+ }
2899
+ /**
2900
+ * Send an SSE event to a specific client response stream.
2901
+ */ _sendSseEvent(res, event, data) {
2902
+ try {
2903
+ res.write(`event: ${event}\n`);
2904
+ res.write(`data: ${JSON.stringify(data)}\n\n`);
2905
+ } catch {
2906
+ // Client disconnected — ignore
2907
+ }
2908
+ }
2909
+ /**
2910
+ * Broadcast a notification to all SSE streams in a given session.
2911
+ *
2912
+ * @param sessionId - Target session ID
2913
+ * @param event - SSE event name
2914
+ * @param data - Event payload
2915
+ */ broadcastToSession(sessionId, event, data) {
2916
+ const session = this._sessions.get(sessionId);
2917
+ if (!session) {
2918
+ return;
2919
+ }
2920
+ for (const stream of session.notificationStreams){
2921
+ this._sendSseEvent(stream, event, data);
2922
+ }
2923
+ }
2924
+ /**
2925
+ * Handle GET /metrics endpoint.
2926
+ */ _handleMetrics(res) {
2927
+ if (!this._metricsProvider) {
2928
+ res.writeHead(404, {
2929
+ 'Content-Type': 'text/plain'
2930
+ });
2931
+ res.end('Not Found');
2932
+ return;
2933
+ }
2934
+ res.writeHead(200, {
2935
+ 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8'
2936
+ });
2937
+ res.end(this._metricsProvider());
2938
+ }
2939
+ /**
2940
+ * Handle GET /health — Liveness check.
2941
+ */ _handleHealthCheck(res) {
2942
+ const healthData = {
2943
+ status: 'healthy',
2944
+ requests: this._requestCount,
2945
+ sessions: this._sessions.size,
2946
+ transport: 'streamable-http'
2947
+ };
2948
+ if (this._healthChecker) {
2949
+ const liveness = this._healthChecker.checkLiveness();
2950
+ healthData.liveness = liveness;
2951
+ }
2952
+ res.writeHead(200, {
2953
+ 'Content-Type': 'application/json'
2954
+ });
2955
+ res.end(JSON.stringify(healthData));
2956
+ }
2957
+ /**
2958
+ * Handle GET /ready — Readiness check.
2959
+ */ async _handleReadinessCheck(res) {
2960
+ if (this._healthChecker) {
2961
+ const readiness = await this._healthChecker.checkReadiness();
2962
+ const statusCode = readiness.status === 'ok' ? 200 : 503;
2963
+ res.writeHead(statusCode, {
2964
+ 'Content-Type': 'application/json'
2965
+ });
2966
+ res.end(JSON.stringify(readiness));
2967
+ } else {
2968
+ res.writeHead(200, {
2969
+ 'Content-Type': 'application/json'
2970
+ });
2971
+ res.end(JSON.stringify({
2972
+ status: 'ok',
2973
+ timestamp: new Date().toISOString(),
2974
+ components: {}
2975
+ }));
2976
+ }
2977
+ }
2978
+ /**
2979
+ * Update session-related metrics.
2980
+ */ _updateSessionMetrics() {
2981
+ this._metrics?.gauge('streamable_http_active_sessions', this._sessions.size, {}, 'Active Streamable HTTP sessions');
2982
+ let totalStreams = 0;
2983
+ for (const session of this._sessions.values()){
2984
+ totalStreams += session.notificationStreams.size;
2985
+ }
2986
+ this._metrics?.gauge('streamable_http_notification_streams', totalStreams, {}, 'Active SSE notification streams');
2987
+ }
2988
+ /**
2989
+ * Stop transport server with graceful shutdown.
2990
+ *
2991
+ * @param timeout - Maximum time to wait for in-flight requests (default: 30s)
2992
+ */ async stop(timeout) {
2993
+ this._isShuttingDown = true;
2994
+ this._stopRateLimitCleanup();
2995
+ const shutdownTimeout = timeout ?? 30000;
2996
+ // Close all SSE notification streams
2997
+ for (const session of this._sessions.values()){
2998
+ for (const stream of session.notificationStreams){
2999
+ try {
3000
+ stream.end();
3001
+ } catch {
3002
+ // Ignore errors
3003
+ }
3004
+ }
3005
+ session.notificationStreams.clear();
3006
+ }
3007
+ this._sessions.clear();
3008
+ return new Promise((resolve)=>{
3009
+ if (!this._server) {
3010
+ this.log('info', 'Streamable HTTP transport stopped (no server)');
3011
+ resolve();
3012
+ return;
3013
+ }
3014
+ // Force close after timeout
3015
+ const forceClose = setTimeout(()=>{
3016
+ this.log('warn', 'Streamable HTTP transport force-closing after timeout');
3017
+ resolve();
3018
+ }, shutdownTimeout);
3019
+ this._server.close(()=>{
3020
+ clearTimeout(forceClose);
3021
+ this.log('info', 'Streamable HTTP transport stopped');
3022
+ resolve();
3023
+ });
3024
+ });
3025
+ }
3026
+ }
3027
+ /**
3028
+ * Create a Streamable HTTP transport with given options.
3029
+ *
3030
+ * @param options - Transport configuration
3031
+ * @returns A configured Streamable HTTP transport
3032
+ *
3033
+ * @example
3034
+ * ```typescript
3035
+ * const transport = createStreamableHttpTransport({ port: 3000, stateful: true });
3036
+ * await transport.connect(server);
3037
+ * ```
3038
+ */ function createStreamableHttpTransport(options = {}) {
3039
+ return new StreamableHttpTransport(options);
3040
+ }
3041
+
3042
+
3043
+ },
3044
+ 65(module) {
3045
+
3046
+ module.exports = __rspack_external__lib_js_262c9725;
3047
+
3048
+
3049
+ },
3050
+ 561(module) {
3051
+
3052
+ module.exports = __rspack_external_node_crypto_9ba42079;
3053
+
3054
+
3055
+ },
3056
+ 316(module) {
3057
+
3058
+ module.exports = __rspack_external_node_http_2dc67212;
3059
+
3060
+
3061
+ },
3062
+ 61(module) {
3063
+
3064
+ module.exports = __rspack_external_node_url_e96de089;
3065
+
3066
+
3067
+ },
3068
+ 821(module) {
3069
+
3070
+ module.exports = __rspack_external_valibot;
3071
+
3072
+
3073
+ },
3074
+
3075
+ });
3076
+ // The module cache
3077
+ var __webpack_module_cache__ = {};
3078
+
3079
+ // The require function
3080
+ function __webpack_require__(moduleId) {
3081
+
3082
+ // Check if module is in cache
3083
+ var cachedModule = __webpack_module_cache__[moduleId];
3084
+ if (cachedModule !== undefined) {
3085
+ return cachedModule.exports;
3086
+ }
3087
+ // Create a new module (and put it into the cache)
3088
+ var module = (__webpack_module_cache__[moduleId] = {
3089
+ exports: {}
3090
+ });
3091
+ // Execute the module function
3092
+ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
3093
+
3094
+ // Return the exports of the module
3095
+ return module.exports;
3096
+
3097
+ }
3098
+
3099
+ // webpack/runtime/define_property_getters
3100
+ (() => {
3101
+ __webpack_require__.d = (exports, definition) => {
3102
+ for(var key in definition) {
3103
+ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
3104
+ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
3105
+ }
3106
+ }
3107
+ };
3108
+ })();
3109
+ // webpack/runtime/has_own_property
3110
+ (() => {
3111
+ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
3112
+ })();
3113
+ var __webpack_exports__ = {};
3114
+ // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
3115
+ (() => {
3116
+
3117
+ ;// CONCATENATED MODULE: external "@tmcp/adapter-valibot"
3118
+
3119
+ ;// CONCATENATED MODULE: external "@tmcp/transport-stdio"
3120
+
3121
+ ;// CONCATENATED MODULE: external "node:fs"
3122
+
3123
+ ;// CONCATENATED MODULE: external "node:path"
3124
+
3125
+ // EXTERNAL MODULE: external "node:url"
3126
+ var external_node_url_ = __webpack_require__(61);
3127
+ ;// CONCATENATED MODULE: external "tmcp"
3128
+
3129
+ // EXTERNAL MODULE: external "./lib.js"
3130
+ var external_lib_js_ = __webpack_require__(65);
3131
+ ;// CONCATENATED MODULE: external "node:async_hooks"
3132
+
3133
+ ;// CONCATENATED MODULE: ./src/context/RequestContext.ts
3134
+ /**
3135
+ * Request context management using AsyncLocalStorage for correlation IDs.
3136
+ *
3137
+ * Provides zero-cost request ID propagation across async boundaries
3138
+ * via Node.js AsyncLocalStorage.
3139
+ *
3140
+ * @module context
3141
+ */
3142
+ /**
3143
+ * AsyncLocalStorage instance for request context.
3144
+ * Stores requestId that propagates across async boundaries.
3145
+ */ const store = new AsyncLocalStorage();
3146
+ /**
3147
+ * Get the current request ID from context.
3148
+ *
3149
+ * Returns undefined if called outside of a runWithContext() call.
3150
+ *
3151
+ * @returns The current request ID or undefined
3152
+ */ function getRequestId() {
3153
+ return store.getStore()?.requestId;
3154
+ }
3155
+
3156
+ ;// CONCATENATED MODULE: ./src/logger/StructuredLogger.ts
3157
+ /**
3158
+ * Lightweight structured logging without external dependencies.
3159
+ *
3160
+ * This module provides a structured logging implementation that writes to stderr
3161
+ * for MCP server compatibility. It supports multiple log levels, pretty printing,
3162
+ * and hierarchical child loggers with inherited context.
3163
+ *
3164
+ * @module logger
3165
+ */
3166
+ /**
3167
+ * Structured logger with level filtering and context support.
3168
+ *
3169
+ * This logger provides structured logging capabilities with configurable
3170
+ * output formats, log levels, and hierarchical context. All output is
3171
+ * written to stderr for compatibility with MCP servers.
3172
+ *
3173
+ * @remarks
3174
+ * **Log Level Priority** (lowest to highest):
3175
+ * - `debug` (0) - Detailed debugging information
3176
+ * - `info` (1) - General informational messages
3177
+ * - `warn` (2) - Warning messages for potential issues
3178
+ * - `error` (3) - Error messages for failures
3179
+ *
3180
+ * Only messages at or above the configured level will be output.
3181
+ *
3182
+ * **Output Formats:**
3183
+ * - Pretty (default): `[timestamp] [LEVEL] [context] message {meta}`
3184
+ * - JSON: `{"level":"info","message":"...","timestamp":"...","context":"...","meta":{...}}`
3185
+ *
3186
+ * @example
3187
+ * ```typescript
3188
+ * // Create a logger
3189
+ * const logger = new StructuredLogger({
3190
+ * level: 'info',
3191
+ * context: 'SequentialThinking',
3192
+ * pretty: true
3193
+ * });
3194
+ *
3195
+ * // Log messages
3196
+ * logger.debug('Detailed debug info', { userId: '123' });
3197
+ * logger.info('Server started', { port: 3000 });
3198
+ * logger.warn('High memory usage', { usage: '85%' });
3199
+ * logger.error('Connection failed', { error: 'ECONNREFUSED' });
3200
+ *
3201
+ * // Create a child logger with extended context
3202
+ * const childLogger = logger.createChild('Database');
3203
+ * childLogger.info('Query executed', { rows: 42 });
3204
+ * // Output: [timestamp] [INFO] [SequentialThinking:Database] Query executed {"rows":42}
3205
+ * ```
3206
+ */ class StructuredLogger {
3207
+ /** Current minimum log level. */ _level;
3208
+ /** Default context for log messages. */ _context;
3209
+ /** Whether pretty printing is enabled. */ _pretty;
3210
+ /**
3211
+ * Log level priority ordering for filtering.
3212
+ * Higher numbers = higher severity.
3213
+ * @private
3214
+ */ static LEVEL_PRIORITY = {
3215
+ debug: 0,
3216
+ info: 1,
3217
+ warn: 2,
3218
+ error: 3
3219
+ };
3220
+ /**
3221
+ * Creates a new StructuredLogger instance.
3222
+ *
3223
+ * @param options - Configuration options for the logger
3224
+ *
3225
+ * @example
3226
+ * ```typescript
3227
+ * // Default configuration
3228
+ * const logger1 = new StructuredLogger();
3229
+ *
3230
+ * // Custom configuration
3231
+ * const logger2 = new StructuredLogger({
3232
+ * level: 'debug',
3233
+ * context: 'MyApp',
3234
+ * pretty: false // JSON output
3235
+ * });
3236
+ * ```
3237
+ */ constructor(options = {}){
3238
+ this._level = options.level ?? 'info';
3239
+ this._context = options.context ?? 'SequentialThinking';
3240
+ this._pretty = options.pretty ?? true;
3241
+ }
3242
+ /**
3243
+ * Determines whether a message at the given level should be logged.
3244
+ * @param level - The log level to check
3245
+ * @returns true if the level meets the threshold, false otherwise
3246
+ * @private
3247
+ */ shouldLog(level) {
3248
+ return StructuredLogger.LEVEL_PRIORITY[level] >= StructuredLogger.LEVEL_PRIORITY[this._level];
3249
+ }
3250
+ /**
3251
+ * Formats a log entry for output.
3252
+ * @param entry - The log entry to format
3253
+ * @returns Formatted string representation
3254
+ * @private
3255
+ */ format(entry) {
3256
+ if (this._pretty) {
3257
+ const metaStr = entry.meta ? ` ${JSON.stringify(entry.meta)}` : '';
3258
+ const requestIdStr = entry.requestId ? ` [${entry.requestId}]` : '';
3259
+ return `[${entry.timestamp}] [${entry.level.toUpperCase()}]${entry.context ? ` [${entry.context}]` : ''}${requestIdStr} ${entry.message}${metaStr}`;
3260
+ }
3261
+ return JSON.stringify(entry);
3262
+ }
3263
+ /**
3264
+ * Internal logging method that handles level filtering and output.
3265
+ * @param level - The log level for this message
3266
+ * @param message - The message to log
3267
+ * @param meta - Optional structured metadata
3268
+ * @private
3269
+ */ log(level, message, meta) {
3270
+ if (!this.shouldLog(level)) return;
3271
+ const requestId = getRequestId();
3272
+ const entry = {
3273
+ level,
3274
+ message,
3275
+ timestamp: new Date().toISOString(),
3276
+ context: this._context,
3277
+ meta,
3278
+ ...requestId ? {
3279
+ requestId
3280
+ } : {}
3281
+ };
3282
+ const formatted = this.format(entry);
3283
+ // Write to stderr for MCP server compatibility
3284
+ console.error(formatted);
3285
+ }
3286
+ /**
3287
+ * Log a debug message.
3288
+ *
3289
+ * Debug messages contain detailed information typically used for
3290
+ * troubleshooting and development. Only output when log level is 'debug'.
3291
+ *
3292
+ * @param message - The message to log
3293
+ * @param meta - Optional structured metadata
3294
+ *
3295
+ * @example
3296
+ * ```typescript
3297
+ * logger.debug('Processing request', { path: '/api/users', method: 'GET' });
3298
+ * ```
3299
+ */ debug(message, meta) {
3300
+ this.log('debug', message, meta);
3301
+ }
3302
+ /**
3303
+ * Log an info message.
3304
+ *
3305
+ * Info messages contain general informational messages about normal operation.
3306
+ * Output when log level is 'info' or lower.
3307
+ *
3308
+ * @param message - The message to log
3309
+ * @param meta - Optional structured metadata
3310
+ *
3311
+ * @example
3312
+ * ```typescript
3313
+ * logger.info('Server started', { port: 3000, env: 'production' });
3314
+ * ```
3315
+ */ info(message, meta) {
3316
+ this.log('info', message, meta);
3317
+ }
3318
+ /**
3319
+ * Log a warning message.
3320
+ *
3321
+ * Warning messages indicate potential issues that don't prevent operation
3322
+ * but may require attention. Output when log level is 'warn' or lower.
3323
+ *
3324
+ * @param message - The message to log
3325
+ * @param meta - Optional structured metadata
3326
+ *
3327
+ * @example
3328
+ * ```typescript
3329
+ * logger.warn('High memory usage detected', { usage: '85%', threshold: '80%' });
3330
+ * ```
3331
+ */ warn(message, meta) {
3332
+ this.log('warn', message, meta);
3333
+ }
3334
+ /**
3335
+ * Log an error message.
3336
+ *
3337
+ * Error messages indicate failures or error conditions. Always output
3338
+ * regardless of log level setting.
3339
+ *
3340
+ * @param message - The message to log
3341
+ * @param meta - Optional structured metadata
3342
+ *
3343
+ * @example
3344
+ * ```typescript
3345
+ * logger.error('Database connection failed', { error: err.message, code: err.code });
3346
+ * ```
3347
+ */ error(message, meta) {
3348
+ this.log('error', message, meta);
3349
+ }
3350
+ /**
3351
+ * Creates a child logger with inherited settings and extended context.
3352
+ *
3353
+ * Child loggers inherit the parent's log level and pretty print setting,
3354
+ * but have their context appended to the parent's context for hierarchical logging.
3355
+ *
3356
+ * @param context - Additional context to append to the parent's context
3357
+ * @returns A new logger instance with extended context
3358
+ *
3359
+ * @example
3360
+ * ```typescript
3361
+ * const parentLogger = new StructuredLogger({ context: 'App' });
3362
+ * const dbLogger = parentLogger.createChild('Database');
3363
+ * const queryLogger = dbLogger.createChild('Query');
3364
+ *
3365
+ * parentLogger.info('Starting up');
3366
+ * // Output: [timestamp] [INFO] [App] Starting up
3367
+ *
3368
+ * dbLogger.info('Connected');
3369
+ * // Output: [timestamp] [INFO] [App:Database] Connected
3370
+ *
3371
+ * queryLogger.info('Executed in 5ms');
3372
+ * // Output: [timestamp] [INFO] [App:Database:Query] Executed in 5ms
3373
+ * ```
3374
+ */ createChild(context) {
3375
+ return new StructuredLogger({
3376
+ level: this._level,
3377
+ context: `${this._context}:${context}`,
3378
+ pretty: this._pretty
3379
+ });
3380
+ }
3381
+ /**
3382
+ * Sets the minimum log level.
3383
+ *
3384
+ * Only messages at or above this level will be output.
3385
+ *
3386
+ * @param level - The new minimum log level
3387
+ *
3388
+ * @example
3389
+ * ```typescript
3390
+ * logger.setLevel('debug'); // Enable all logging
3391
+ * logger.setLevel('error'); // Only show errors
3392
+ * ```
3393
+ */ setLevel(level) {
3394
+ this._level = level;
3395
+ }
3396
+ /**
3397
+ * Gets the current minimum log level.
3398
+ *
3399
+ * @returns The current log level
3400
+ *
3401
+ * @example
3402
+ * ```typescript
3403
+ * const currentLevel = logger.getLevel();
3404
+ * console.log(`Current level: ${currentLevel}`);
3405
+ * ```
3406
+ */ getLevel() {
3407
+ return this._level;
3408
+ }
3409
+ }
3410
+
3411
+ // EXTERNAL MODULE: ./src/errors.ts
3412
+ var errors = __webpack_require__(937);
3413
+ // EXTERNAL MODULE: ./src/schema.ts
3414
+ var schema = __webpack_require__(613);
3415
+ ;// CONCATENATED MODULE: ./src/cli.ts
3416
+ //#!/usr/bin/env bun
3417
+ // CLI entry point for tracelattice MCP server.
3418
+ // This file handles CLI argument parsing, transport selection, and signal handlers.
3419
+ // For library usage, import from './lib.js' or './index.js' instead.
3420
+
3421
+
3422
+
3423
+
3424
+
3425
+
3426
+
3427
+
3428
+
107
3429
 
108
- `),t.end();return}this._clientSessionMap.set(t,i),this._updatePoolMetrics()}let n={timestamp:Date.now()};i&&(n.sessionId=i),this._sendSseEvent(t,"connected",n),this._clients.add(t),this._updateActiveConnectionsMetric(),e.on("close",()=>{this._clients.delete(t),this._clientSessionMap.delete(t),this._updateActiveConnectionsMetric()});let o=this._generateClientId(),r=this._messageQueue.get(o);if(r){for(let e of r)this._sendSseEvent(t,"message",e);this._messageQueue.delete(o)}}async _handleMessage(e,t,s){var i,n,a;let l="";for await(let t of e)l+=t.toString();try{let e=JSON.parse(l),s=(0,o.safeParse)(r.Uv,e);if(!s.success){null==(i=this._metrics)||i.counter("http_request_errors_total",1,{transport:"sse",error_type:"validation"},"Total HTTP request errors"),t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify({jsonrpc:"2.0",id:(null==e?void 0:e.id)??null,error:{code:-32600,message:"Invalid Request",data:s.issues}}));return}if(this._mcpServer){let s=await this._mcpServer.receive(e,{sessionInfo:{}});t.writeHead(200,{"Content-Type":"application/json"}),s?t.end(JSON.stringify(s)):t.end(JSON.stringify({jsonrpc:"2.0",id:(null==e?void 0:e.id)??null,result:null}))}else null==(n=this._metrics)||n.counter("http_request_errors_total",1,{transport:"sse",error_type:"server_not_ready"},"Total HTTP request errors"),t.writeHead(503,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Server not ready"}))}catch{null==(a=this._metrics)||a.counter("http_request_errors_total",1,{transport:"sse",error_type:"parse_error"},"Total HTTP request errors"),t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Invalid JSON"}))}}_sendSseEvent(e,t,s){try{e.write(`event: ${t}
109
- `),e.write(`data: ${JSON.stringify(s)}
3430
+ // Get version from package.json
3431
+ const cli_filename = (0,external_node_url_.fileURLToPath)(import.meta.url);
3432
+ const cli_dirname = dirname(cli_filename);
3433
+ const package_json = JSON.parse(readFileSync(join(cli_dirname, '../package.json'), 'utf-8'));
3434
+ const { name: cli_name, version } = package_json;
3435
+ // Handle CLI arguments
3436
+ const args = process.argv.slice(2);
3437
+ const shouldShowVersion = args.includes('--version') || args.includes('-v');
3438
+ if (shouldShowVersion) {
3439
+ console.log(`${cli_name} v${version}`);
3440
+ process.exit(0);
3441
+ }
3442
+ async function main() {
3443
+ const adapter = new ValibotJsonSchemaAdapter();
3444
+ const server = new McpServer({
3445
+ name: cli_name,
3446
+ version,
3447
+ description: 'Semantic Sequential Thinking MCP Server'
3448
+ }, {
3449
+ adapter,
3450
+ capabilities: {
3451
+ tools: {
3452
+ listChanged: true
3453
+ }
3454
+ }
3455
+ });
3456
+ const thinkingServer = await (0,external_lib_js_.initializeServer)();
3457
+ server.tool({
3458
+ name: 'sequentialthinking_tools',
3459
+ description: schema/* .SEQUENTIAL_THINKING_TOOL.description */.iV.description,
3460
+ schema: schema/* .SequentialThinkingSchema */.ZK
3461
+ }, async (input)=>{
3462
+ return thinkingServer.processThought(input);
3463
+ });
3464
+ const transportType = process.env.TRANSPORT_TYPE || 'stdio';
3465
+ if (transportType === 'sse') {
3466
+ await startSseTransport(server, thinkingServer);
3467
+ } else if (transportType === 'streamable-http') {
3468
+ await startStreamableHttpTransport(server, thinkingServer);
3469
+ } else {
3470
+ await startStdioTransport(server, thinkingServer);
3471
+ }
3472
+ }
3473
+ /**
3474
+ * Start SSE transport for multi-user support
3475
+ */ async function startSseTransport(server, thinkingServer) {
3476
+ const { SseTransport } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 390));
3477
+ const { createConnectionPool } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 789));
3478
+ const port = parseInt(process.env.SSE_PORT || '3000', 10);
3479
+ const host = process.env.SSE_HOST || 'localhost';
3480
+ const transportMetrics = thinkingServer.getContainer().resolve('Metrics');
3481
+ const enablePool = process.env.SSE_ENABLE_POOL !== 'false';
3482
+ const maxSessions = parseInt(process.env.SSE_MAX_SESSIONS || '100', 10);
3483
+ const sessionTimeout = parseInt(process.env.SSE_SESSION_TIMEOUT || '300000', 10);
3484
+ const connectionPool = enablePool ? createConnectionPool({
3485
+ maxSessions,
3486
+ sessionTimeout,
3487
+ logger: thinkingServer['_logger'],
3488
+ serverFactory: async ()=>{
3489
+ const { createServer: createThinkingServer } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 65));
3490
+ const sessionServer = await createThinkingServer({
3491
+ autoDiscover: true
3492
+ });
3493
+ return sessionServer;
3494
+ }
3495
+ }) : undefined;
3496
+ const sseTransport = new SseTransport({
3497
+ port,
3498
+ host,
3499
+ corsOrigin: process.env.CORS_ORIGIN || '*',
3500
+ enableCors: process.env.ENABLE_CORS !== 'false',
3501
+ allowedHosts: process.env.ALLOWED_HOSTS?.split(',').map((hostValue)=>hostValue.trim()),
3502
+ metrics: transportMetrics,
3503
+ connectionPool
3504
+ });
3505
+ // Connect the SSE transport
3506
+ await sseTransport.connect(server);
3507
+ const shutdown = async ()=>{
3508
+ await sseTransport.stop();
3509
+ await thinkingServer.stop();
3510
+ };
3511
+ registerShutdownHandlers(shutdown);
3512
+ thinkingServer['_logger'].info(`Sequential Thinking MCP Server running on SSE transport at http://${host}:${port}`);
3513
+ }
3514
+ /**
3515
+ * Start Streamable HTTP transport (MCP spec recommended)
3516
+ */ async function startStreamableHttpTransport(server, thinkingServer) {
3517
+ const { StreamableHttpTransport } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 34));
3518
+ const port = parseInt(process.env.STREAMABLE_HTTP_PORT || process.env.SSE_PORT || '3000', 10);
3519
+ const host = process.env.STREAMABLE_HTTP_HOST || process.env.SSE_HOST || 'localhost';
3520
+ const transportMetrics = thinkingServer.getContainer().resolve('Metrics');
3521
+ const stateful = process.env.STREAMABLE_HTTP_STATEFUL !== 'false';
3522
+ const streamableTransport = new StreamableHttpTransport({
3523
+ port,
3524
+ host,
3525
+ corsOrigin: process.env.CORS_ORIGIN || '*',
3526
+ enableCors: process.env.ENABLE_CORS !== 'false',
3527
+ allowedHosts: process.env.ALLOWED_HOSTS?.split(',').map((hostValue)=>hostValue.trim()),
3528
+ metrics: transportMetrics,
3529
+ stateful
3530
+ });
3531
+ // Connect the Streamable HTTP transport
3532
+ await streamableTransport.connect(server);
3533
+ const shutdown = async ()=>{
3534
+ await streamableTransport.stop();
3535
+ await thinkingServer.stop();
3536
+ };
3537
+ registerShutdownHandlers(shutdown);
3538
+ thinkingServer['_logger'].info(`Sequential Thinking MCP Server running on Streamable HTTP transport at http://${host}:${port}`);
3539
+ }
3540
+ /**
3541
+ * Start stdio transport (default, single-user)
3542
+ */ async function startStdioTransport(server, thinkingServer) {
3543
+ const transport = new StdioTransport(server);
3544
+ transport.listen();
3545
+ const shutdown = async ()=>{
3546
+ const forceExit = setTimeout(()=>{
3547
+ thinkingServer['_logger'].error('Graceful shutdown timed out after 30s - forcing exit');
3548
+ process.exit(1);
3549
+ }, 30000).unref(); // 30s timeout, don't keep process alive
3550
+ try {
3551
+ await thinkingServer.stop();
3552
+ clearTimeout(forceExit);
3553
+ process.exit(0);
3554
+ } catch (error) {
3555
+ thinkingServer['_logger'].error('Error during shutdown', {
3556
+ error: (0,errors/* .getErrorMessage */.u1)(error)
3557
+ });
3558
+ process.exit(1);
3559
+ }
3560
+ };
3561
+ // Register signal handlers ONCE (fixes double-registration bug)
3562
+ process.once('SIGINT', ()=>void shutdown());
3563
+ process.once('SIGTERM', ()=>void shutdown());
3564
+ thinkingServer['_logger'].info('Sequential Thinking MCP Server running on stdio');
3565
+ }
3566
+ /**
3567
+ * Register shutdown signal handlers for a common pattern
3568
+ */ function registerShutdownHandlers(shutdown) {
3569
+ process.once('SIGINT', ()=>{
3570
+ shutdown().then(()=>process.exit(0)).catch(()=>process.exit(1));
3571
+ });
3572
+ process.once('SIGTERM', ()=>{
3573
+ shutdown().then(()=>process.exit(0)).catch(()=>process.exit(1));
3574
+ });
3575
+ }
3576
+ main().catch((error)=>{
3577
+ const logger = new StructuredLogger({
3578
+ level: 'error',
3579
+ context: 'SequentialThinking',
3580
+ pretty: true
3581
+ });
3582
+ logger.error('Fatal error running server', {
3583
+ error: (0,errors/* .getErrorMessage */.u1)(error)
3584
+ });
3585
+ process.exit(1);
3586
+ });
110
3587
 
111
- `)}catch{this._clients.delete(e),this._updateActiveConnectionsMetric()}}_updateActiveConnectionsMetric(){var e;null==(e=this._metrics)||e.gauge("sse_active_connections",this._clients.size,{},"Current active SSE connections")}_updatePoolMetrics(){if(!this._connectionPool||!this._metrics)return;let e=this._connectionPool.getStats();this._metrics.gauge("sse_pool_active_sessions",e.activeSessions,{},"Active sessions in connection pool"),this._metrics.gauge("sse_pool_total_sessions",e.totalSessions,{},"Total sessions in connection pool"),this._metrics.gauge("sse_pool_max_sessions",e.maxSessions,{},"Maximum sessions in connection pool")}broadcast(e,t){for(let s of this._clients)this._sendSseEvent(s,e,t)}_generateClientId(){return`client_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}get clientCount(){return this._clients.size}get connectionPool(){return this._connectionPool}async stop(e){return this._isShuttingDown=!0,this._stopRateLimitCleanup(),this._connectionPool&&await this._connectionPool.terminate(),new Promise(e=>{for(let e of this._clients)try{e.end()}catch{}this._clients.clear(),this._clientSessionMap.clear(),this._updateActiveConnectionsMetric(),this._server.close(()=>{this.log("info","SSE transport stopped"),e()})})}}},756(e,t,s){s.d(t,{StreamableHttpTransport:()=>h});var i=s(561),n=s(316),o=s(821),r=s(787),a=s(555),l=s(681);async function c(e,t){let s="",i=0;for await(let n of e){let e="string"==typeof n?n:n.toString();if(i+=e.length,t>0&&i>t)return null;s+=e}return s}class h extends l.j{_server=null;_mcpServer=null;_path;_stateful;_sessionIdGenerator;_sessions=new Map;_requestCount=0;_activeRequests=0;_bodySizeLimitEnabled;_maxBodySize;_requestTimeout;_metrics;_metricsProvider;constructor(e={}){super(e),this._path=e.path??"/mcp",this._stateful=e.stateful??!0,this._sessionIdGenerator=e.sessionIdGenerator??(()=>(0,i.randomUUID)()),this._bodySizeLimitEnabled=e.enableBodySizeLimit??!0,this._maxBodySize=e.maxBodySize??0xa00000,this._requestTimeout=e.requestTimeout??3e4,this._metrics=e.metrics,this._metricsProvider=e.metricsProvider??null}get clientCount(){return this._stateful?this._sessions.size:this._activeRequests}get requestCount(){return this._requestCount}async connect(e){return this._mcpServer=e,this._server=(0,n.createServer)((e,t)=>this._handleRequest(e,t)),new Promise(e=>{this._server.listen(this._port,this._host,()=>{this.log("info",`Streamable HTTP transport listening on http://${this._host}:${this._port}`),e()})})}async _handleRequest(e,t){var s,i;let n=Date.now();if(null==(s=this._metrics)||s.counter("streamable_http_requests_total",1,{},"Total Streamable HTTP transport requests"),t.once("finish",()=>{var e;let t=(Date.now()-n)/1e3;null==(e=this._metrics)||e.histogram("streamable_http_request_duration_seconds",t,{})}),!this.validateHostHeader(e))return void this._sendJsonRpcError(t,403,-32e3,"Forbidden - invalid host header");if(this.isShuttingDown())return void this._sendJsonRpcError(t,503,-32603,"Server is shutting down");let o=this.getClientIp(e);if(this.checkRateLimit(o)){t.setHeader("Retry-After","60"),this._sendJsonRpcError(t,429,-32e3,"Too many requests");return}if(!this.validateCorsOrigin(e))return void this._sendJsonRpcError(t,403,-32e3,"Forbidden - invalid origin");if(this.setCorsHeaders(t),"OPTIONS"===e.method){t.setHeader("Access-Control-Allow-Headers","Content-Type, Mcp-Session-Id"),t.writeHead(204),t.end();return}let r=(null==(i=e.url)?void 0:i.split("?")[0])??"/";"GET"===e.method&&"/metrics"===r?this._handleMetrics(t):"GET"===e.method&&"/health"===r?this._handleHealthCheck(t):"GET"===e.method&&"/ready"===r?await this._handleReadinessCheck(t):r===this._path?"POST"===e.method?await this._handleMcpPost(e,t):"GET"===e.method?this._handleMcpGet(e,t):(t.writeHead(405,{"Content-Type":"application/json",Allow:"GET, POST"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32601,message:"Method not allowed"}}))):this._sendJsonRpcError(t,404,-32601,"Not Found")}_sendJsonRpcError(e,t,s,i,n=null,o){let r={code:s,message:i};o&&Object.assign(r,o),e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify({jsonrpc:"2.0",id:n,error:r}))}async _handleMcpPost(e,t){this._requestCount++,this._activeRequests++;let s=setTimeout(()=>{this._activeRequests--,this._sendJsonRpcError(t,500,-32603,"Request timeout")},this._requestTimeout);try{let i,n,r=await c(e,this._bodySizeLimitEnabled?this._maxBodySize:0);if(null===r){clearTimeout(s),this._activeRequests--,this._sendJsonRpcError(t,413,-32e3,"Request body too large");return}try{i=JSON.parse(r)}catch{clearTimeout(s),this._activeRequests--,this._sendJsonRpcError(t,200,-32700,"Parse error");return}let l=(0,o.safeParse)(a.Uv,i);if(!l.success){clearTimeout(s),this._activeRequests--,this._sendJsonRpcError(t,200,-32600,"Invalid Request",(null==i?void 0:i.id)??null,{data:l.issues});return}if(this._stateful){let i=this._resolveSession(e,t);if(!1===i){clearTimeout(s),this._activeRequests--;return}n=i}if(!this._mcpServer){clearTimeout(s),this._activeRequests--,this._sendJsonRpcError(t,503,-32603,"Server not ready",(null==i?void 0:i.id)??null);return}let h=await this._mcpServer.receive(i,{sessionInfo:{}});clearTimeout(s),this._activeRequests--;let p={"Content-Type":"application/json"};n&&(p["Mcp-Session-Id"]=n),h?(t.writeHead(200,p),t.end(JSON.stringify(h))):(n&&t.setHeader("Mcp-Session-Id",n),t.writeHead(202),t.end())}catch(e){clearTimeout(s),this._activeRequests--,this._sendJsonRpcError(t,200,-32603,"Internal error",null,{data:(0,r.u1)(e)})}}_handleMcpGet(e,t){if(!this._stateful){t.writeHead(405,{"Content-Type":"application/json",Allow:"POST"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32601,message:"GET not supported in stateless mode"}}));return}let s=this._getSessionIdFromHeader(e);if(!s){t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32600,message:"Missing Mcp-Session-Id header"}}));return}let i=this._sessions.get(s);if(!i){t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32001,message:"Session not found"}}));return}t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Mcp-Session-Id":s}),this._sendSseEvent(t,"connected",{sessionId:s,timestamp:Date.now()}),i.notificationStreams.add(t),i.lastActivityAt=Date.now(),this._updateSessionMetrics(),e.on("close",()=>{i.notificationStreams.delete(t),this._updateSessionMetrics()})}_resolveSession(e,t){let s=this._getSessionIdFromHeader(e);if(s){if(!this.validateSessionId(s))return t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32600,message:"Invalid Mcp-Session-Id format"}})),!1;let e=this._sessions.get(s);return e?(e.lastActivityAt=Date.now(),s):(t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32001,message:"Session not found"}})),!1)}let i=this._sessionIdGenerator(),n={id:i,createdAt:Date.now(),lastActivityAt:Date.now(),notificationStreams:new Set};return this._sessions.set(i,n),this.log("info",`New session created: ${i}`),this._updateSessionMetrics(),i}_getSessionIdFromHeader(e){let t=e.headers["mcp-session-id"];if("string"==typeof t&&t.length>0)return t}_sendSseEvent(e,t,s){try{e.write(`event: ${t}
112
- `),e.write(`data: ${JSON.stringify(s)}
3588
+ })();
113
3589
 
114
- `)}catch{}}broadcastToSession(e,t,s){let i=this._sessions.get(e);if(i)for(let e of i.notificationStreams)this._sendSseEvent(e,t,s)}_handleMetrics(e){if(!this._metricsProvider){e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Not Found");return}e.writeHead(200,{"Content-Type":"text/plain; version=0.0.4; charset=utf-8"}),e.end(this._metricsProvider())}_handleHealthCheck(e){let t={status:"healthy",requests:this._requestCount,sessions:this._sessions.size,transport:"streamable-http"};this._healthChecker&&(t.liveness=this._healthChecker.checkLiveness()),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}async _handleReadinessCheck(e){if(this._healthChecker){let t=await this._healthChecker.checkReadiness(),s="ok"===t.status?200:503;e.writeHead(s,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}else e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok",timestamp:new Date().toISOString(),components:{}}))}_updateSessionMetrics(){var e,t;null==(e=this._metrics)||e.gauge("streamable_http_active_sessions",this._sessions.size,{},"Active Streamable HTTP sessions");let s=0;for(let e of this._sessions.values())s+=e.notificationStreams.size;null==(t=this._metrics)||t.gauge("streamable_http_notification_streams",s,{},"Active SSE notification streams")}async stop(e){this._isShuttingDown=!0,this._stopRateLimitCleanup();let t=e??3e4;for(let e of this._sessions.values()){for(let t of e.notificationStreams)try{t.end()}catch{}e.notificationStreams.clear()}return this._sessions.clear(),new Promise(e=>{if(!this._server){this.log("info","Streamable HTTP transport stopped (no server)"),e();return}let s=setTimeout(()=>{this.log("warn","Streamable HTTP transport force-closing after timeout"),e()},t);this._server.close(()=>{clearTimeout(s),this.log("info","Streamable HTTP transport stopped"),e()})})}}},65(t){t.exports=e},561(e){e.exports=t},316(e){e.exports=s},61(e){e.exports=i},821(e){e.exports=n}},u={};function _(e){var t=u[e];if(void 0!==t)return t.exports;var s=u[e]={exports:{}};return d[e](s,s.exports,_),s.exports}_.d=(e,t)=>{for(var s in t)_.o(t,s)&&!_.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},_.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e=_(61),t=_(65);let s=new p;class i{_level;_context;_pretty;static LEVEL_PRIORITY={debug:0,info:1,warn:2,error:3};constructor(e={}){this._level=e.level??"info",this._context=e.context??"SequentialThinking",this._pretty=e.pretty??!0}shouldLog(e){return i.LEVEL_PRIORITY[e]>=i.LEVEL_PRIORITY[this._level]}format(e){if(this._pretty){let t=e.meta?` ${JSON.stringify(e.meta)}`:"",s=e.requestId?` [${e.requestId}]`:"";return`[${e.timestamp}] [${e.level.toUpperCase()}]${e.context?` [${e.context}]`:""}${s} ${e.message}${t}`}return JSON.stringify(e)}log(e,t,i){var n;if(!this.shouldLog(e))return;let o=null==(n=s.getStore())?void 0:n.requestId,r={level:e,message:t,timestamp:new Date().toISOString(),context:this._context,meta:i,...o?{requestId:o}:{}};console.error(this.format(r))}debug(e,t){this.log("debug",e,t)}info(e,t){this.log("info",e,t)}warn(e,t){this.log("warn",e,t)}error(e,t){this.log("error",e,t)}createChild(e){return new i({level:this._level,context:`${this._context}:${e}`,pretty:this._pretty})}setLevel(e){this._level=e}getLevel(){return this._level}}var n=_(787),d=_(555);let{name:u,version:m}=JSON.parse(a(c(l((0,e.fileURLToPath)(import.meta.url)),"../package.json"),"utf-8")),g=process.argv.slice(2);async function f(e,t){var s;let{SseTransport:i}=await Promise.resolve().then(_.bind(_,504)),{createConnectionPool:n}=await Promise.resolve().then(_.bind(_,527)),o=parseInt(process.env.SSE_PORT||"3000",10),r=process.env.SSE_HOST||"localhost",a=t.getContainer().resolve("Metrics"),l="false"!==process.env.SSE_ENABLE_POOL,c=parseInt(process.env.SSE_MAX_SESSIONS||"100",10),h=parseInt(process.env.SSE_SESSION_TIMEOUT||"300000",10),p=l?n({maxSessions:c,sessionTimeout:h,logger:t._logger,serverFactory:async()=>{let{createServer:e}=await Promise.resolve().then(_.bind(_,65));return await e({autoDiscover:!0})}}):void 0,d=new i({port:o,host:r,corsOrigin:process.env.CORS_ORIGIN||"*",enableCors:"false"!==process.env.ENABLE_CORS,allowedHosts:null==(s=process.env.ALLOWED_HOSTS)?void 0:s.split(",").map(e=>e.trim()),metrics:a,connectionPool:p});await d.connect(e),S(async()=>{await d.stop(),await t.stop()}),t._logger.info(`Sequential Thinking MCP Server running on SSE transport at http://${r}:${o}`)}async function v(e,t){var s;let{StreamableHttpTransport:i}=await Promise.resolve().then(_.bind(_,756)),n=parseInt(process.env.STREAMABLE_HTTP_PORT||process.env.SSE_PORT||"3000",10),o=process.env.STREAMABLE_HTTP_HOST||process.env.SSE_HOST||"localhost",r=t.getContainer().resolve("Metrics"),a="false"!==process.env.STREAMABLE_HTTP_STATEFUL,l=new i({port:n,host:o,corsOrigin:process.env.CORS_ORIGIN||"*",enableCors:"false"!==process.env.ENABLE_CORS,allowedHosts:null==(s=process.env.ALLOWED_HOSTS)?void 0:s.split(",").map(e=>e.trim()),metrics:r,stateful:a});await l.connect(e),S(async()=>{await l.stop(),await t.stop()}),t._logger.info(`Sequential Thinking MCP Server running on Streamable HTTP transport at http://${o}:${n}`)}async function y(e,t){new r(e).listen();let s=async()=>{let e=setTimeout(()=>{t._logger.error("Graceful shutdown timed out after 30s - forcing exit"),process.exit(1)},3e4).unref();try{await t.stop(),clearTimeout(e),process.exit(0)}catch(e){t._logger.error("Error during shutdown",{error:(0,n.u1)(e)}),process.exit(1)}};process.once("SIGINT",()=>void s()),process.once("SIGTERM",()=>void s()),t._logger.info("Sequential Thinking MCP Server running on stdio")}function S(e){process.once("SIGINT",()=>{e().then(()=>process.exit(0)).catch(()=>process.exit(1))}),process.once("SIGTERM",()=>{e().then(()=>process.exit(0)).catch(()=>process.exit(1))})}(g.includes("--version")||g.includes("-v"))&&(console.log(`${u} v${m}`),process.exit(0)),(async function(){let e=new h({name:u,version:m,description:"Semantic Sequential Thinking MCP Server"},{adapter:new o,capabilities:{tools:{listChanged:!0}}}),s=await (0,t.initializeServer)();e.tool({name:"sequentialthinking_tools",description:d.iV.description,schema:d.ZK},async e=>s.processThought(e));let i=process.env.TRANSPORT_TYPE||"stdio";"sse"===i?await f(e,s):"streamable-http"===i?await v(e,s):await y(e,s)})().catch(e=>{new i({level:"error",context:"SequentialThinking",pretty:!0}).error("Fatal error running server",{error:(0,n.u1)(e)}),process.exit(1)})})();