@mxf-dev/core 1.0.1 → 2.0.1

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 (303) hide show
  1. package/README.md +18 -0
  2. package/dist/adapters/FrameworkAdapter.js +1 -1
  3. package/dist/adapters/FrameworkAdapter.js.map +1 -1
  4. package/dist/config/ConfigManager.d.ts +9 -8
  5. package/dist/config/ConfigManager.d.ts.map +1 -1
  6. package/dist/config/ConfigManager.js +47 -17
  7. package/dist/config/ConfigManager.js.map +1 -1
  8. package/dist/config/memory-strata.config.d.ts +25 -0
  9. package/dist/config/memory-strata.config.d.ts.map +1 -0
  10. package/dist/config/memory-strata.config.js +107 -0
  11. package/dist/config/memory-strata.config.js.map +1 -0
  12. package/dist/constants/ToolNames.d.ts +1 -29
  13. package/dist/constants/ToolNames.d.ts.map +1 -1
  14. package/dist/constants/ToolNames.js +4 -17
  15. package/dist/constants/ToolNames.js.map +1 -1
  16. package/dist/database/DatabaseAdapterFactory.d.ts +14 -2
  17. package/dist/database/DatabaseAdapterFactory.d.ts.map +1 -1
  18. package/dist/database/DatabaseAdapterFactory.js +21 -6
  19. package/dist/database/DatabaseAdapterFactory.js.map +1 -1
  20. package/dist/database/adapters/mongodb/MongoBaseRepository.d.ts +7 -1
  21. package/dist/database/adapters/mongodb/MongoBaseRepository.d.ts.map +1 -1
  22. package/dist/database/adapters/mongodb/MongoBaseRepository.js +12 -2
  23. package/dist/database/adapters/mongodb/MongoBaseRepository.js.map +1 -1
  24. package/dist/events/ClientEventBus.d.ts +16 -77
  25. package/dist/events/ClientEventBus.d.ts.map +1 -1
  26. package/dist/events/ClientEventBus.js +38 -311
  27. package/dist/events/ClientEventBus.js.map +1 -1
  28. package/dist/events/EventBus.d.ts +1 -1
  29. package/dist/events/EventBus.d.ts.map +1 -1
  30. package/dist/events/EventBus.js +5 -4
  31. package/dist/events/EventBus.js.map +1 -1
  32. package/dist/events/EventBusBase.d.ts +139 -34
  33. package/dist/events/EventBusBase.d.ts.map +1 -1
  34. package/dist/events/EventBusBase.js +366 -88
  35. package/dist/events/EventBusBase.js.map +1 -1
  36. package/dist/events/EventNames.d.ts +10 -1
  37. package/dist/events/EventNames.d.ts.map +1 -1
  38. package/dist/events/EventNames.js +3 -0
  39. package/dist/events/EventNames.js.map +1 -1
  40. package/dist/events/PublicEvents.d.ts +6 -2
  41. package/dist/events/PublicEvents.d.ts.map +1 -1
  42. package/dist/events/PublicEvents.js +7 -4
  43. package/dist/events/PublicEvents.js.map +1 -1
  44. package/dist/events/ServerEventBus.d.ts +23 -112
  45. package/dist/events/ServerEventBus.d.ts.map +1 -1
  46. package/dist/events/ServerEventBus.js +58 -323
  47. package/dist/events/ServerEventBus.js.map +1 -1
  48. package/dist/events/event-definitions/LlmBudgetEvents.d.ts +68 -0
  49. package/dist/events/event-definitions/LlmBudgetEvents.d.ts.map +1 -0
  50. package/dist/events/event-definitions/LlmBudgetEvents.js +35 -0
  51. package/dist/events/event-definitions/LlmBudgetEvents.js.map +1 -0
  52. package/dist/interfaces/IMemoryPersistence.d.ts +41 -0
  53. package/dist/interfaces/IMemoryPersistence.d.ts.map +1 -0
  54. package/dist/interfaces/IMemoryPersistence.js +15 -0
  55. package/dist/interfaces/IMemoryPersistence.js.map +1 -0
  56. package/dist/middleware/MxpMiddleware.d.ts +8 -1
  57. package/dist/middleware/MxpMiddleware.d.ts.map +1 -1
  58. package/dist/middleware/MxpMiddleware.js +42 -20
  59. package/dist/middleware/MxpMiddleware.js.map +1 -1
  60. package/dist/models/channelKey.d.ts +1 -0
  61. package/dist/models/channelKey.d.ts.map +1 -1
  62. package/dist/models/channelKey.js +5 -0
  63. package/dist/models/channelKey.js.map +1 -1
  64. package/dist/models/memoryUtility.d.ts +39 -0
  65. package/dist/models/memoryUtility.d.ts.map +1 -0
  66. package/dist/models/memoryUtility.js +39 -0
  67. package/dist/models/memoryUtility.js.map +1 -0
  68. package/dist/models/user.d.ts.map +1 -1
  69. package/dist/models/user.js +23 -1
  70. package/dist/models/user.js.map +1 -1
  71. package/dist/mxp/BinaryProtocolLayer.d.ts +24 -8
  72. package/dist/mxp/BinaryProtocolLayer.d.ts.map +1 -1
  73. package/dist/mxp/BinaryProtocolLayer.js +90 -103
  74. package/dist/mxp/BinaryProtocolLayer.js.map +1 -1
  75. package/dist/mxp/ContextCompressionEngine.d.ts +57 -10
  76. package/dist/mxp/ContextCompressionEngine.d.ts.map +1 -1
  77. package/dist/mxp/ContextCompressionEngine.js +170 -128
  78. package/dist/mxp/ContextCompressionEngine.js.map +1 -1
  79. package/dist/mxp/MxpTokenOptimizer.d.ts +7 -3
  80. package/dist/mxp/MxpTokenOptimizer.d.ts.map +1 -1
  81. package/dist/mxp/MxpTokenOptimizer.js +8 -5
  82. package/dist/mxp/MxpTokenOptimizer.js.map +1 -1
  83. package/dist/prompts/MxfAgentSystemPrompt.d.ts +1 -1
  84. package/dist/prompts/MxfAgentSystemPrompt.d.ts.map +1 -1
  85. package/dist/prompts/MxfAgentSystemPrompt.js +47 -57
  86. package/dist/prompts/MxfAgentSystemPrompt.js.map +1 -1
  87. package/dist/protocols/mcp/ToolError.d.ts +123 -0
  88. package/dist/protocols/mcp/ToolError.d.ts.map +1 -0
  89. package/dist/protocols/mcp/ToolError.js +108 -0
  90. package/dist/protocols/mcp/ToolError.js.map +1 -0
  91. package/dist/protocols/mcp/defineTool.d.ts +133 -0
  92. package/dist/protocols/mcp/defineTool.d.ts.map +1 -0
  93. package/dist/protocols/mcp/defineTool.js +236 -0
  94. package/dist/protocols/mcp/defineTool.js.map +1 -0
  95. package/dist/protocols/mcp/security/HttpTargetGuard.d.ts +38 -0
  96. package/dist/protocols/mcp/security/HttpTargetGuard.d.ts.map +1 -0
  97. package/dist/protocols/mcp/security/HttpTargetGuard.js +227 -0
  98. package/dist/protocols/mcp/security/HttpTargetGuard.js.map +1 -0
  99. package/dist/protocols/mcp/security/McpSecurityGuard.d.ts +9 -1
  100. package/dist/protocols/mcp/security/McpSecurityGuard.d.ts.map +1 -1
  101. package/dist/protocols/mcp/security/McpSecurityGuard.js +10 -2
  102. package/dist/protocols/mcp/security/McpSecurityGuard.js.map +1 -1
  103. package/dist/protocols/mcp/security/McpToolPolicy.d.ts +81 -0
  104. package/dist/protocols/mcp/security/McpToolPolicy.d.ts.map +1 -0
  105. package/dist/protocols/mcp/security/McpToolPolicy.js +202 -0
  106. package/dist/protocols/mcp/security/McpToolPolicy.js.map +1 -0
  107. package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts +51 -18
  108. package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts.map +1 -1
  109. package/dist/protocols/mcp/services/ExternalMcpServerManager.js +256 -283
  110. package/dist/protocols/mcp/services/ExternalMcpServerManager.js.map +1 -1
  111. package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts +39 -6
  112. package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts.map +1 -1
  113. package/dist/protocols/mcp/services/ExternalServerConfigs.js +76 -18
  114. package/dist/protocols/mcp/services/ExternalServerConfigs.js.map +1 -1
  115. package/dist/protocols/mcp/tools/AnalyticsTools.js +1 -1
  116. package/dist/protocols/mcp/tools/AnalyticsTools.js.map +1 -1
  117. package/dist/protocols/mcp/tools/CodeAnalysisTools.d.ts.map +1 -1
  118. package/dist/protocols/mcp/tools/CodeAnalysisTools.js +15 -0
  119. package/dist/protocols/mcp/tools/CodeAnalysisTools.js.map +1 -1
  120. package/dist/protocols/mcp/tools/EffectivenessTools.js +3 -3
  121. package/dist/protocols/mcp/tools/EffectivenessTools.js.map +1 -1
  122. package/dist/protocols/mcp/tools/GitTools.d.ts +9 -369
  123. package/dist/protocols/mcp/tools/GitTools.d.ts.map +1 -1
  124. package/dist/protocols/mcp/tools/GitTools.js +222 -517
  125. package/dist/protocols/mcp/tools/GitTools.js.map +1 -1
  126. package/dist/protocols/mcp/tools/InfrastructureTools.d.ts +56 -24
  127. package/dist/protocols/mcp/tools/InfrastructureTools.d.ts.map +1 -1
  128. package/dist/protocols/mcp/tools/InfrastructureTools.js +117 -26
  129. package/dist/protocols/mcp/tools/InfrastructureTools.js.map +1 -1
  130. package/dist/protocols/mcp/tools/MemorySearchTools.d.ts +0 -3
  131. package/dist/protocols/mcp/tools/MemorySearchTools.d.ts.map +1 -1
  132. package/dist/protocols/mcp/tools/MemorySearchTools.js +58 -1
  133. package/dist/protocols/mcp/tools/MemorySearchTools.js.map +1 -1
  134. package/dist/protocols/mcp/tools/OrparTools.d.ts +8 -0
  135. package/dist/protocols/mcp/tools/OrparTools.d.ts.map +1 -1
  136. package/dist/protocols/mcp/tools/OrparTools.js +66 -0
  137. package/dist/protocols/mcp/tools/OrparTools.js.map +1 -1
  138. package/dist/protocols/mcp/tools/SafetyTools.d.ts +7 -525
  139. package/dist/protocols/mcp/tools/SafetyTools.d.ts.map +1 -1
  140. package/dist/protocols/mcp/tools/SafetyTools.js +349 -514
  141. package/dist/protocols/mcp/tools/SafetyTools.js.map +1 -1
  142. package/dist/protocols/mcp/tools/TaskPlanningTools.d.ts.map +1 -1
  143. package/dist/protocols/mcp/tools/TaskPlanningTools.js +56 -26
  144. package/dist/protocols/mcp/tools/TaskPlanningTools.js.map +1 -1
  145. package/dist/protocols/mcp/tools/TestTools.d.ts +15 -376
  146. package/dist/protocols/mcp/tools/TestTools.d.ts.map +1 -1
  147. package/dist/protocols/mcp/tools/TestTools.js +241 -363
  148. package/dist/protocols/mcp/tools/TestTools.js.map +1 -1
  149. package/dist/protocols/mcp/tools/TypeScriptTools.d.ts +6 -276
  150. package/dist/protocols/mcp/tools/TypeScriptTools.d.ts.map +1 -1
  151. package/dist/protocols/mcp/tools/TypeScriptTools.js +223 -337
  152. package/dist/protocols/mcp/tools/TypeScriptTools.js.map +1 -1
  153. package/dist/protocols/mcp/tools/WebTools.d.ts +15 -728
  154. package/dist/protocols/mcp/tools/WebTools.d.ts.map +1 -1
  155. package/dist/protocols/mcp/tools/WebTools.js +151 -257
  156. package/dist/protocols/mcp/tools/WebTools.js.map +1 -1
  157. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.d.ts +5 -3
  158. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.d.ts.map +1 -1
  159. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js +31 -6
  160. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js.map +1 -1
  161. package/dist/schemas/EventPayloadSchema.d.ts +21 -0
  162. package/dist/schemas/EventPayloadSchema.d.ts.map +1 -1
  163. package/dist/schemas/EventPayloadSchema.js +14 -0
  164. package/dist/schemas/EventPayloadSchema.js.map +1 -1
  165. package/dist/services/BackgroundTaskManager.d.ts.map +1 -1
  166. package/dist/services/BackgroundTaskManager.js +12 -4
  167. package/dist/services/BackgroundTaskManager.js.map +1 -1
  168. package/dist/services/BrowserManager.d.ts +1 -1
  169. package/dist/services/BrowserManager.d.ts.map +1 -1
  170. package/dist/services/BrowserManager.js +26 -3
  171. package/dist/services/BrowserManager.js.map +1 -1
  172. package/dist/services/MemoryCompressor.d.ts +11 -2
  173. package/dist/services/MemoryCompressor.d.ts.map +1 -1
  174. package/dist/services/MemoryCompressor.js +8 -26
  175. package/dist/services/MemoryCompressor.js.map +1 -1
  176. package/dist/services/MemoryService.d.ts +16 -3
  177. package/dist/services/MemoryService.d.ts.map +1 -1
  178. package/dist/services/MemoryService.js +79 -55
  179. package/dist/services/MemoryService.js.map +1 -1
  180. package/dist/services/MxfMLService.d.ts +5 -0
  181. package/dist/services/MxfMLService.d.ts.map +1 -1
  182. package/dist/services/MxfMLService.js +32 -6
  183. package/dist/services/MxfMLService.js.map +1 -1
  184. package/dist/services/PredictiveAnalyticsService.d.ts +45 -9
  185. package/dist/services/PredictiveAnalyticsService.d.ts.map +1 -1
  186. package/dist/services/PredictiveAnalyticsService.js +82 -44
  187. package/dist/services/PredictiveAnalyticsService.js.map +1 -1
  188. package/dist/services/QValueManager.d.ts +7 -0
  189. package/dist/services/QValueManager.d.ts.map +1 -1
  190. package/dist/services/QValueManager.js +9 -0
  191. package/dist/services/QValueManager.js.map +1 -1
  192. package/dist/services/RewardSignalProcessor.d.ts +38 -1
  193. package/dist/services/RewardSignalProcessor.d.ts.map +1 -1
  194. package/dist/services/RewardSignalProcessor.js +109 -7
  195. package/dist/services/RewardSignalProcessor.js.map +1 -1
  196. package/dist/services/SharedStateService.d.ts +16 -2
  197. package/dist/services/SharedStateService.d.ts.map +1 -1
  198. package/dist/services/SharedStateService.js +44 -3
  199. package/dist/services/SharedStateService.js.map +1 -1
  200. package/dist/services/TaskEffectivenessService.d.ts +34 -18
  201. package/dist/services/TaskEffectivenessService.d.ts.map +1 -1
  202. package/dist/services/TaskEffectivenessService.js +91 -155
  203. package/dist/services/TaskEffectivenessService.js.map +1 -1
  204. package/dist/services/WebSearchService.d.ts.map +1 -1
  205. package/dist/services/WebSearchService.js.map +1 -1
  206. package/dist/services/dag/TaskDagService.d.ts.map +1 -1
  207. package/dist/services/dag/TaskDagService.js +2 -0
  208. package/dist/services/dag/TaskDagService.js.map +1 -1
  209. package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts +7 -0
  210. package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts.map +1 -1
  211. package/dist/services/orpar-memory/OrparMemoryCoordinator.js +71 -10
  212. package/dist/services/orpar-memory/OrparMemoryCoordinator.js.map +1 -1
  213. package/dist/types/MemoryUtilityTypes.d.ts +2 -0
  214. package/dist/types/MemoryUtilityTypes.d.ts.map +1 -1
  215. package/dist/types/MemoryUtilityTypes.js.map +1 -1
  216. package/dist/utils/Logger.d.ts +43 -3
  217. package/dist/utils/Logger.d.ts.map +1 -1
  218. package/dist/utils/Logger.js +78 -36
  219. package/dist/utils/Logger.js.map +1 -1
  220. package/dist/utils/MxpEncryption.d.ts +19 -6
  221. package/dist/utils/MxpEncryption.d.ts.map +1 -1
  222. package/dist/utils/MxpEncryption.js +48 -16
  223. package/dist/utils/MxpEncryption.js.map +1 -1
  224. package/package.json +19 -4
  225. package/src/adapters/FrameworkAdapter.ts +1 -1
  226. package/src/config/ConfigManager.ts +52 -19
  227. package/src/config/memory-strata.config.ts +136 -0
  228. package/src/constants/ToolNames.ts +4 -18
  229. package/src/database/DatabaseAdapterFactory.ts +23 -6
  230. package/src/database/adapters/mongodb/MongoBaseRepository.ts +16 -2
  231. package/src/events/ClientEventBus.ts +68 -403
  232. package/src/events/EventBus.ts +7 -8
  233. package/src/events/EventBusBase.ts +479 -116
  234. package/src/events/EventNames.ts +6 -0
  235. package/src/events/PublicEvents.ts +7 -4
  236. package/src/events/ServerEventBus.ts +78 -473
  237. package/src/events/event-definitions/LlmBudgetEvents.ts +74 -0
  238. package/src/interfaces/IMemoryPersistence.ts +51 -0
  239. package/src/middleware/MxpMiddleware.ts +51 -24
  240. package/src/models/channelKey.ts +18 -4
  241. package/src/models/memoryUtility.ts +64 -0
  242. package/src/models/user.ts +36 -4
  243. package/src/mxp/BinaryProtocolLayer.ts +108 -124
  244. package/src/mxp/ContextCompressionEngine.ts +219 -161
  245. package/src/mxp/MxpTokenOptimizer.ts +10 -10
  246. package/src/prompts/MxfAgentSystemPrompt.ts +45 -55
  247. package/src/protocols/mcp/ToolError.ts +201 -0
  248. package/src/protocols/mcp/defineTool.ts +379 -0
  249. package/src/protocols/mcp/security/HttpTargetGuard.ts +267 -0
  250. package/src/protocols/mcp/security/McpSecurityGuard.ts +10 -3
  251. package/src/protocols/mcp/security/McpToolPolicy.ts +221 -0
  252. package/src/protocols/mcp/services/ExternalMcpServerManager.ts +340 -322
  253. package/src/protocols/mcp/services/ExternalServerConfigs.ts +82 -19
  254. package/src/protocols/mcp/tools/AnalyticsTools.ts +1 -1
  255. package/src/protocols/mcp/tools/CodeAnalysisTools.ts +15 -0
  256. package/src/protocols/mcp/tools/EffectivenessTools.ts +3 -3
  257. package/src/protocols/mcp/tools/GitTools.ts +290 -569
  258. package/src/protocols/mcp/tools/InfrastructureTools.ts +189 -43
  259. package/src/protocols/mcp/tools/MemorySearchTools.ts +77 -1
  260. package/src/protocols/mcp/tools/OrparTools.ts +87 -0
  261. package/src/protocols/mcp/tools/SafetyTools.ts +501 -579
  262. package/src/protocols/mcp/tools/TaskPlanningTools.ts +81 -39
  263. package/src/protocols/mcp/tools/TestTools.ts +339 -419
  264. package/src/protocols/mcp/tools/TypeScriptTools.ts +316 -376
  265. package/src/protocols/mcp/tools/WebTools.ts +209 -307
  266. package/src/protocols/mcp/tools/shell/ShellExecuteHandler.ts +53 -14
  267. package/src/schemas/EventPayloadSchema.ts +37 -0
  268. package/src/services/BackgroundTaskManager.ts +12 -4
  269. package/src/services/BrowserManager.ts +41 -1
  270. package/src/services/MemoryCompressor.ts +20 -32
  271. package/src/services/MemoryService.ts +96 -58
  272. package/src/services/MxfMLService.ts +41 -7
  273. package/src/services/PredictiveAnalyticsService.ts +101 -51
  274. package/src/services/QValueManager.ts +10 -0
  275. package/src/services/RewardSignalProcessor.ts +138 -9
  276. package/src/services/SharedStateService.ts +56 -8
  277. package/src/services/TaskEffectivenessService.ts +114 -187
  278. package/src/services/WebSearchService.ts +2 -1
  279. package/src/services/dag/TaskDagService.ts +2 -0
  280. package/src/services/orpar-memory/OrparMemoryCoordinator.ts +86 -10
  281. package/src/types/MemoryUtilityTypes.ts +2 -0
  282. package/src/utils/Logger.ts +116 -40
  283. package/src/utils/MxpEncryption.ts +69 -34
  284. package/dist/mxp/MxpEventForwardingEnhancer.d.ts +0 -134
  285. package/dist/mxp/MxpEventForwardingEnhancer.d.ts.map +0 -1
  286. package/dist/mxp/MxpEventForwardingEnhancer.js +0 -361
  287. package/dist/mxp/MxpEventForwardingEnhancer.js.map +0 -1
  288. package/dist/protocols/mcp/services/ToolSchemaEnhancements.d.ts +0 -56
  289. package/dist/protocols/mcp/services/ToolSchemaEnhancements.d.ts.map +0 -1
  290. package/dist/protocols/mcp/services/ToolSchemaEnhancements.js +0 -57
  291. package/dist/protocols/mcp/services/ToolSchemaEnhancements.js.map +0 -1
  292. package/dist/protocols/mcp/tools/ControlLoopLifecycle.d.ts +0 -270
  293. package/dist/protocols/mcp/tools/ControlLoopLifecycle.d.ts.map +0 -1
  294. package/dist/protocols/mcp/tools/ControlLoopLifecycle.js +0 -256
  295. package/dist/protocols/mcp/tools/ControlLoopLifecycle.js.map +0 -1
  296. package/dist/protocols/mcp/tools/LspTools.d.ts +0 -495
  297. package/dist/protocols/mcp/tools/LspTools.d.ts.map +0 -1
  298. package/dist/protocols/mcp/tools/LspTools.js +0 -469
  299. package/dist/protocols/mcp/tools/LspTools.js.map +0 -1
  300. package/src/mxp/MxpEventForwardingEnhancer.ts +0 -471
  301. package/src/protocols/mcp/services/ToolSchemaEnhancements.ts +0 -92
  302. package/src/protocols/mcp/tools/ControlLoopLifecycle.ts +0 -302
  303. package/src/protocols/mcp/tools/LspTools.ts +0 -476
@@ -20,27 +20,41 @@
20
20
 
21
21
  /**
22
22
  * WebTools.ts
23
- *
24
- * Web search, navigation, and content extraction tools for MXF
25
- * Ported from external MCP-WWW server for better integration
23
+ *
24
+ * Web search, navigation, content extraction, screenshots, and HTTP fetches.
25
+ *
26
+ * Every tool here is declared with defineTool, so a failure arrives as one
27
+ * envelope with `isError: true` rather than as a string starting with "Error:"
28
+ * that a caller has to parse.
29
+ *
30
+ * api_fetch runs from inside the server's trust boundary, so its target URL is
31
+ * checked by HttpTargetGuard before the request goes out — see that module for
32
+ * why an unrestricted fetch is a server-side request forgery hole.
26
33
  */
27
34
 
28
- import { WEB_TOOLS } from '../../../constants/ToolNames.js';
35
+ import { WEB_TOOLS, TOOL_CATEGORIES } from '../../../constants/ToolNames.js';
29
36
  import { WebSearchService } from '../../../services/WebSearchService.js';
30
- import { BrowserManager } from '../../../services/BrowserManager.js';
31
- import { ContentProcessor } from '../../../services/ContentProcessor.js';
37
+ import { defineTool } from '../defineTool.js';
38
+ import { ToolError } from '../ToolError.js';
39
+ import { checkHttpTarget } from '../security/HttpTargetGuard.js';
32
40
 
33
- // Initialize singleton services
41
+ // WebSearchService owns the browser and content-processing plumbing these tools
42
+ // need; they do not touch BrowserManager or ContentProcessor directly.
34
43
  const webSearchService = new WebSearchService();
35
- const browserManager = new BrowserManager();
36
- const contentProcessor = new ContentProcessor();
37
44
 
38
45
  /**
39
- * Web Search Tool - Performs web searches with content extraction
46
+ * Search the web and optionally pull the content of each result.
40
47
  */
41
- export const webSearchTool = {
48
+ export const webSearchTool = defineTool<{
49
+ query: string;
50
+ maxResults?: number;
51
+ searchEngine?: string;
52
+ extractContent?: boolean;
53
+ format?: string;
54
+ }, unknown>({
42
55
  name: WEB_TOOLS.WEB_SEARCH,
43
- description: 'Perform web searches with optional content extraction and structured output',
56
+ category: TOOL_CATEGORIES.WEB,
57
+ description: 'Search the web and return results, optionally with the full text of each page.',
44
58
  inputSchema: {
45
59
  type: 'object',
46
60
  properties: {
@@ -75,61 +89,31 @@ export const webSearchTool = {
75
89
  },
76
90
  required: ['query']
77
91
  },
78
- handler: async (input: {
79
- query: string;
80
- maxResults?: number;
81
- searchEngine?: string;
82
- extractContent?: boolean;
83
- format?: string;
84
- }, context: {
85
- requestId: string;
86
- agentId?: string;
87
- channelId?: string;
88
- }) => {
89
- try {
90
- const result = await webSearchService.search({
91
- query: input.query,
92
- maxResults: input.maxResults || 10,
93
- searchEngine: input.searchEngine || 'google',
94
- extractContent: input.extractContent ?? true,
95
- format: input.format || 'structured'
96
- });
97
-
98
- return {
99
- content: {
100
- type: 'text',
101
- text: JSON.stringify(result, null, 2)
102
- },
103
- metadata: {
104
- toolName: WEB_TOOLS.WEB_SEARCH,
105
- requestId: context.requestId,
106
- timestamp: new Date().toISOString()
107
- }
108
- };
109
- } catch (error) {
110
- return {
111
- content: {
112
- type: 'text',
113
- text: `Error: ${error instanceof Error ? error.message : 'Web search failed'}`
114
- },
115
- metadata: {
116
- toolName: WEB_TOOLS.WEB_SEARCH,
117
- requestId: context.requestId,
118
- timestamp: new Date().toISOString(),
119
- error: true
120
- }
121
- };
122
- }
123
- },
124
- enabled: true
125
- };
92
+ run: async (input) => {
93
+ return webSearchService.search({
94
+ query: input.query,
95
+ maxResults: input.maxResults ?? 10,
96
+ searchEngine: input.searchEngine ?? 'google',
97
+ extractContent: input.extractContent ?? true,
98
+ format: input.format ?? 'structured'
99
+ });
100
+ }
101
+ });
126
102
 
127
103
  /**
128
- * Web Navigation Tool - Navigate to URLs and extract content
104
+ * Load a URL in a browser and extract its content.
129
105
  */
130
- export const webNavigationTool = {
106
+ export const webNavigationTool = defineTool<{
107
+ url: string;
108
+ waitStrategy?: string;
109
+ includeScreenshot?: boolean;
110
+ screenshotFormat?: string;
111
+ extractContent?: boolean;
112
+ format?: string;
113
+ }, unknown>({
131
114
  name: WEB_TOOLS.WEB_NAVIGATE,
132
- description: 'Navigate to a URL and extract content with optional screenshot capture',
115
+ category: TOOL_CATEGORIES.WEB,
116
+ description: 'Load a URL in a headless browser and extract its content, optionally with a screenshot.',
133
117
  inputSchema: {
134
118
  type: 'object',
135
119
  properties: {
@@ -169,63 +153,29 @@ export const webNavigationTool = {
169
153
  },
170
154
  required: ['url']
171
155
  },
172
- handler: async (input: {
173
- url: string;
174
- waitStrategy?: string;
175
- includeScreenshot?: boolean;
176
- screenshotFormat?: string;
177
- extractContent?: boolean;
178
- format?: string;
179
- }, context: {
180
- requestId: string;
181
- agentId?: string;
182
- channelId?: string;
183
- }) => {
184
- try {
185
- const result = await webSearchService.navigate({
186
- url: input.url,
187
- waitStrategy: input.waitStrategy || 'networkidle2',
188
- includeScreenshot: input.includeScreenshot || false,
189
- screenshotFormat: input.screenshotFormat || 'png',
190
- extractContent: input.extractContent ?? true,
191
- format: input.format || 'structured'
192
- });
193
-
194
- return {
195
- content: {
196
- type: 'text',
197
- text: JSON.stringify(result, null, 2)
198
- },
199
- metadata: {
200
- toolName: WEB_TOOLS.WEB_NAVIGATE,
201
- requestId: context.requestId,
202
- timestamp: new Date().toISOString()
203
- }
204
- };
205
- } catch (error) {
206
- return {
207
- content: {
208
- type: 'text',
209
- text: `Error: ${error instanceof Error ? error.message : 'Web navigation failed'}`
210
- },
211
- metadata: {
212
- toolName: WEB_TOOLS.WEB_NAVIGATE,
213
- requestId: context.requestId,
214
- timestamp: new Date().toISOString(),
215
- error: true
216
- }
217
- };
218
- }
219
- },
220
- enabled: true
221
- };
156
+ run: async (input) => {
157
+ return webSearchService.navigate({
158
+ url: input.url,
159
+ waitStrategy: input.waitStrategy ?? 'networkidle2',
160
+ includeScreenshot: input.includeScreenshot ?? false,
161
+ screenshotFormat: input.screenshotFormat ?? 'png',
162
+ extractContent: input.extractContent ?? true,
163
+ format: input.format ?? 'structured'
164
+ });
165
+ }
166
+ });
222
167
 
223
168
  /**
224
- * Web Content Extraction Tool - Extract content from multiple URLs
169
+ * Extract content from several URLs at once.
225
170
  */
226
- export const webContentExtractionTool = {
171
+ export const webContentExtractionTool = defineTool<{
172
+ urls: string[];
173
+ concurrency?: number;
174
+ format?: string;
175
+ }, unknown>({
227
176
  name: WEB_TOOLS.WEB_BULK_EXTRACT,
228
- description: 'Extract content from multiple URLs simultaneously',
177
+ category: TOOL_CATEGORIES.WEB,
178
+ description: 'Extract the content of several URLs in one call.',
229
179
  inputSchema: {
230
180
  type: 'object',
231
181
  properties: {
@@ -255,57 +205,28 @@ export const webContentExtractionTool = {
255
205
  },
256
206
  required: ['urls']
257
207
  },
258
- handler: async (input: {
259
- urls: string[];
260
- concurrency?: number;
261
- format?: string;
262
- }, context: {
263
- requestId: string;
264
- agentId?: string;
265
- channelId?: string;
266
- }) => {
267
- try {
268
- const result = await webSearchService.bulkExtract({
269
- urls: input.urls,
270
- concurrency: input.concurrency || 3,
271
- format: input.format || 'structured'
272
- });
273
-
274
- return {
275
- content: {
276
- type: 'text',
277
- text: JSON.stringify(result, null, 2)
278
- },
279
- metadata: {
280
- toolName: WEB_TOOLS.WEB_BULK_EXTRACT,
281
- requestId: context.requestId,
282
- timestamp: new Date().toISOString()
283
- }
284
- };
285
- } catch (error) {
286
- return {
287
- content: {
288
- type: 'text',
289
- text: `Error: ${error instanceof Error ? error.message : 'Bulk content extraction failed'}`
290
- },
291
- metadata: {
292
- toolName: WEB_TOOLS.WEB_BULK_EXTRACT,
293
- requestId: context.requestId,
294
- timestamp: new Date().toISOString(),
295
- error: true
296
- }
297
- };
298
- }
299
- },
300
- enabled: true
301
- };
208
+ run: async (input) => {
209
+ return webSearchService.bulkExtract({
210
+ urls: input.urls,
211
+ concurrency: input.concurrency ?? 3,
212
+ format: input.format ?? 'structured'
213
+ });
214
+ }
215
+ });
302
216
 
303
217
  /**
304
- * Web Screenshot Tool - Capture screenshots of web pages
218
+ * Capture a screenshot of a page.
305
219
  */
306
- export const webScreenshotTool = {
220
+ export const webScreenshotTool = defineTool<{
221
+ url: string;
222
+ format?: string;
223
+ fullPage?: boolean;
224
+ width?: number;
225
+ height?: number;
226
+ }, { url: string; format: string; byteLength: number }>({
307
227
  name: WEB_TOOLS.WEB_SCREENSHOT,
308
- description: 'Capture screenshots of web pages',
228
+ category: TOOL_CATEGORIES.WEB,
229
+ description: 'Capture a screenshot of a web page.',
309
230
  inputSchema: {
310
231
  type: 'object',
311
232
  properties: {
@@ -342,71 +263,56 @@ export const webScreenshotTool = {
342
263
  },
343
264
  required: ['url']
344
265
  },
345
- handler: async (input: {
346
- url: string;
347
- format?: string;
348
- fullPage?: boolean;
349
- width?: number;
350
- height?: number;
351
- }, context: {
352
- requestId: string;
353
- agentId?: string;
354
- channelId?: string;
355
- }) => {
356
- try {
357
- const result = await webSearchService.screenshot({
358
- url: input.url,
359
- format: input.format || 'png',
360
- fullPage: input.fullPage || false,
361
- width: input.width || 1280,
362
- height: input.height || 720
363
- });
266
+ run: async (input) => {
267
+ const format = input.format ?? 'png';
268
+ const screenshot = await webSearchService.screenshot({
269
+ url: input.url,
270
+ format,
271
+ fullPage: input.fullPage ?? false,
272
+ width: input.width ?? 1280,
273
+ height: input.height ?? 720
274
+ });
364
275
 
365
- return {
366
- content: {
367
- type: 'text',
368
- text: `Screenshot captured for ${input.url} (${result.length} bytes)`
369
- },
370
- metadata: {
371
- toolName: WEB_TOOLS.WEB_SCREENSHOT,
372
- requestId: context.requestId,
373
- timestamp: new Date().toISOString(),
374
- screenshotSize: result.length
375
- }
376
- };
377
- } catch (error) {
378
- return {
379
- content: {
380
- type: 'text',
381
- text: `Error: ${error instanceof Error ? error.message : 'Screenshot capture failed'}`
382
- },
383
- metadata: {
384
- toolName: WEB_TOOLS.WEB_SCREENSHOT,
385
- requestId: context.requestId,
386
- timestamp: new Date().toISOString(),
387
- error: true
388
- }
389
- };
390
- }
391
- },
392
- enabled: true
393
- };
276
+ return {
277
+ url: input.url,
278
+ format,
279
+ byteLength: screenshot.length
280
+ };
281
+ }
282
+ });
394
283
 
395
284
  /**
396
- * Export all web tools
397
- */
398
- /**
399
- * API Fetch Tool - Fetch JSON from API endpoints
285
+ * Fetch a URL and return the response body.
286
+ *
287
+ * The target is checked before the request goes out: the server can reach the
288
+ * MXF API on localhost, Meilisearch, MongoDB, and a cloud metadata endpoint, and
289
+ * an unrestricted fetch would let an agent reach all of them through us.
400
290
  */
401
- export const apiFetchTool = {
402
- name: 'api_fetch',
403
- description: 'Fetch JSON data from API endpoints. Use this for APIs, not web_navigate (which is for HTML pages).',
291
+ export const apiFetchTool = defineTool<{
292
+ url: string;
293
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
294
+ headers?: Record<string, string>;
295
+ body?: unknown;
296
+ timeout?: number;
297
+ }, {
298
+ status: number;
299
+ contentType: string;
300
+ dataType: 'json' | 'text';
301
+ url: string;
302
+ data: unknown;
303
+ }>({
304
+ name: WEB_TOOLS.API_FETCH,
305
+ category: TOOL_CATEGORIES.WEB_REQUEST,
306
+ description:
307
+ 'Fetch a public HTTP(S) endpoint and return the response body, parsed as JSON when the ' +
308
+ 'response says it is JSON. Use this for APIs; use web_navigate for HTML pages. ' +
309
+ 'Private and loopback addresses are refused.',
404
310
  inputSchema: {
405
311
  type: 'object',
406
312
  properties: {
407
313
  url: {
408
314
  type: 'string',
409
- description: 'API endpoint URL',
315
+ description: 'API endpoint URL (http or https, public host)',
410
316
  format: 'uri'
411
317
  },
412
318
  method: {
@@ -427,127 +333,123 @@ export const apiFetchTool = {
427
333
  timeout: {
428
334
  type: 'number',
429
335
  description: 'Request timeout in milliseconds',
430
- default: 30000
336
+ default: 30000,
337
+ minimum: 1,
338
+ maximum: 120000
431
339
  }
432
340
  },
433
341
  required: ['url']
434
342
  },
435
- handler: async (input: {
436
- url: string;
437
- method?: string;
438
- headers?: Record<string, string>;
439
- body?: any;
440
- timeout?: number;
441
- }, context: {
442
- requestId: string;
443
- agentId?: string;
444
- channelId?: string;
445
- }) => {
343
+ run: async (input) => {
344
+ // Refuse targets inside the trust boundary before opening a socket.
345
+ const targetCheck = await checkHttpTarget(input.url);
346
+ if (!targetCheck.allowed) {
347
+ throw ToolError.permissionDenied(
348
+ targetCheck.reason ?? `Refusing to fetch ${input.url}`,
349
+ { url: input.url }
350
+ );
351
+ }
352
+
353
+ const method = input.method ?? 'GET';
354
+ const controller = new AbortController();
355
+ const timeoutId = setTimeout(() => controller.abort(), input.timeout ?? 30000);
356
+
446
357
  try {
447
- const controller = new AbortController();
448
- const timeoutId = setTimeout(() => controller.abort(), input.timeout || 30000);
358
+ const headers: Record<string, string> = {
359
+ Accept: 'application/json',
360
+ ...input.headers
361
+ };
449
362
 
450
363
  const fetchOptions: RequestInit = {
451
- method: input.method || 'GET',
452
- headers: {
453
- 'Accept': 'application/json',
454
- ...input.headers
455
- },
456
- signal: controller.signal
364
+ method,
365
+ headers,
366
+ signal: controller.signal,
367
+ // A redirect can point back at a blocked host after the check above,
368
+ // so follow none of them — the agent can fetch the new location
369
+ // explicitly and have it checked in turn.
370
+ redirect: 'manual'
457
371
  };
458
372
 
459
- if (input.body && (input.method === 'POST' || input.method === 'PUT')) {
373
+ if (input.body !== undefined && (method === 'POST' || method === 'PUT')) {
460
374
  fetchOptions.body = JSON.stringify(input.body);
461
- fetchOptions.headers = {
462
- ...fetchOptions.headers,
463
- 'Content-Type': 'application/json'
464
- };
375
+ headers['Content-Type'] = 'application/json';
465
376
  }
466
377
 
467
378
  const response = await fetch(input.url, fetchOptions);
468
- clearTimeout(timeoutId);
379
+
380
+ if (response.status >= 300 && response.status < 400) {
381
+ const location = response.headers.get('location');
382
+ throw ToolError.upstream(
383
+ `${input.url} redirected to ${location ?? 'an unspecified location'}. ` +
384
+ `Redirects are not followed — call api_fetch again with that URL if you want it.`,
385
+ { details: { status: response.status, location, url: input.url } }
386
+ );
387
+ }
388
+
389
+ const responseText = await response.text();
390
+ const contentType = response.headers.get('content-type') ?? '';
469
391
 
470
392
  if (!response.ok) {
471
- const errorText = await response.text();
472
- return {
473
- content: {
474
- type: 'text',
475
- text: JSON.stringify({
476
- error: true,
393
+ throw ToolError.upstream(
394
+ `${method} ${input.url} returned ${response.status} ${response.statusText}`,
395
+ {
396
+ details: {
477
397
  status: response.status,
478
398
  statusText: response.statusText,
479
399
  url: input.url,
480
- body: errorText.substring(0, 500) // Truncate error responses
481
- }, null, 2)
482
- },
483
- metadata: {
484
- toolName: 'api_fetch',
485
- requestId: context.requestId,
486
- timestamp: new Date().toISOString(),
487
- error: true
400
+ body: responseText.slice(0, 500)
401
+ }
488
402
  }
489
- };
403
+ );
490
404
  }
491
405
 
492
- // Get raw response text (don't assume JSON)
493
- const responseText = await response.text();
494
- const contentType = response.headers.get('content-type') || '';
495
-
496
- // Try to parse as JSON if content-type suggests it
497
- let data: any = responseText;
498
- let dataType = 'text';
406
+ // Parse as JSON only when the response claims to be JSON. A body that
407
+ // says it is JSON but does not parse is an upstream error, not a
408
+ // string to hand back as if nothing happened.
409
+ let data: unknown = responseText;
410
+ let dataType: 'json' | 'text' = 'text';
499
411
 
500
412
  if (contentType.includes('application/json') || contentType.includes('text/json')) {
501
413
  try {
502
414
  data = JSON.parse(responseText);
503
415
  dataType = 'json';
504
- } catch (e) {
505
- // JSON parse failed - return as text
506
- data = responseText;
507
- dataType = 'text (JSON parse failed)';
416
+ } catch (parseError) {
417
+ throw ToolError.upstream(
418
+ `${input.url} declared Content-Type "${contentType}" but the body is not valid JSON: ` +
419
+ `${parseError instanceof Error ? parseError.message : String(parseError)}`,
420
+ { details: { url: input.url, contentType, bodyPreview: responseText.slice(0, 200) } }
421
+ );
508
422
  }
509
423
  }
510
424
 
511
425
  return {
512
- content: {
513
- type: 'text',
514
- text: JSON.stringify({
515
- success: true,
516
- status: response.status,
517
- contentType: contentType,
518
- dataType: dataType,
519
- url: input.url,
520
- data: data
521
- }, null, 2)
522
- },
523
- metadata: {
524
- toolName: 'api_fetch',
525
- requestId: context.requestId,
526
- timestamp: new Date().toISOString()
527
- }
426
+ status: response.status,
427
+ contentType,
428
+ dataType,
429
+ url: input.url,
430
+ data
528
431
  };
529
432
 
530
433
  } catch (error) {
531
- return {
532
- content: {
533
- type: 'text',
534
- text: JSON.stringify({
535
- error: true,
536
- message: error instanceof Error ? error.message : 'API fetch failed',
537
- url: input.url
538
- }, null, 2)
539
- },
540
- metadata: {
541
- toolName: 'api_fetch',
542
- requestId: context.requestId,
543
- timestamp: new Date().toISOString(),
544
- error: true
545
- }
546
- };
434
+ // A ToolError from the branches above is already the right shape.
435
+ if (error instanceof ToolError) {
436
+ throw error;
437
+ }
438
+ if (error instanceof Error && error.name === 'AbortError') {
439
+ throw ToolError.upstream(
440
+ `${method} ${input.url} timed out after ${input.timeout ?? 30000}ms`,
441
+ { details: { url: input.url } }
442
+ );
443
+ }
444
+ throw ToolError.upstream(
445
+ `${method} ${input.url} failed: ${error instanceof Error ? error.message : String(error)}`,
446
+ { cause: error, details: { url: input.url } }
447
+ );
448
+ } finally {
449
+ clearTimeout(timeoutId);
547
450
  }
548
- },
549
- enabled: true
550
- };
451
+ }
452
+ });
551
453
 
552
454
  export const webTools = [
553
455
  webSearchTool,
@@ -555,4 +457,4 @@ export const webTools = [
555
457
  webContentExtractionTool,
556
458
  webScreenshotTool,
557
459
  apiFetchTool
558
- ];
460
+ ];