@machina.ai/cell-cli-core 1.20.2-rc1 → 1.22.5-rc1

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 (436) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/package.json +1 -1
  5. package/dist/src/agents/delegate-to-agent-tool.d.ts +19 -0
  6. package/dist/src/agents/delegate-to-agent-tool.js +111 -0
  7. package/dist/src/agents/delegate-to-agent-tool.js.map +1 -0
  8. package/dist/src/agents/delegate-to-agent-tool.test.d.ts +6 -0
  9. package/dist/src/agents/delegate-to-agent-tool.test.js +133 -0
  10. package/dist/src/agents/delegate-to-agent-tool.test.js.map +1 -0
  11. package/dist/src/agents/executor.js +1 -1
  12. package/dist/src/agents/executor.js.map +1 -1
  13. package/dist/src/agents/executor.test.js.map +1 -1
  14. package/dist/src/agents/registry.d.ts +15 -0
  15. package/dist/src/agents/registry.js +58 -2
  16. package/dist/src/agents/registry.js.map +1 -1
  17. package/dist/src/agents/registry.test.js +61 -0
  18. package/dist/src/agents/registry.test.js.map +1 -1
  19. package/dist/src/availability/errorClassification.d.ts +7 -0
  20. package/dist/src/availability/errorClassification.js +20 -0
  21. package/dist/src/availability/errorClassification.js.map +1 -0
  22. package/dist/src/availability/modelAvailabilityService.d.ts +1 -0
  23. package/dist/src/availability/modelAvailabilityService.js +3 -0
  24. package/dist/src/availability/modelAvailabilityService.js.map +1 -1
  25. package/dist/src/availability/modelPolicy.d.ts +8 -1
  26. package/dist/src/availability/policyCatalog.d.ts +1 -0
  27. package/dist/src/availability/policyCatalog.js +6 -7
  28. package/dist/src/availability/policyCatalog.js.map +1 -1
  29. package/dist/src/availability/policyCatalog.test.js +2 -2
  30. package/dist/src/availability/policyCatalog.test.js.map +1 -1
  31. package/dist/src/availability/policyHelpers.d.ts +33 -3
  32. package/dist/src/availability/policyHelpers.js +113 -13
  33. package/dist/src/availability/policyHelpers.js.map +1 -1
  34. package/dist/src/availability/policyHelpers.test.js +133 -13
  35. package/dist/src/availability/policyHelpers.test.js.map +1 -1
  36. package/dist/src/availability/testUtils.d.ts +10 -0
  37. package/dist/src/availability/testUtils.js +22 -0
  38. package/dist/src/availability/testUtils.js.map +1 -0
  39. package/dist/src/code_assist/experiments/client_metadata.js +2 -1
  40. package/dist/src/code_assist/experiments/client_metadata.js.map +1 -1
  41. package/dist/src/code_assist/experiments/client_metadata.test.js +7 -10
  42. package/dist/src/code_assist/experiments/client_metadata.test.js.map +1 -1
  43. package/dist/src/code_assist/oauth2.d.ts +2 -0
  44. package/dist/src/code_assist/oauth2.js +38 -12
  45. package/dist/src/code_assist/oauth2.js.map +1 -1
  46. package/dist/src/code_assist/oauth2.test.js +113 -6
  47. package/dist/src/code_assist/oauth2.test.js.map +1 -1
  48. package/dist/src/commands/init.d.ts +7 -0
  49. package/dist/src/commands/init.js +53 -0
  50. package/dist/src/commands/init.js.map +1 -0
  51. package/dist/src/commands/init.test.d.ts +6 -0
  52. package/dist/src/commands/init.test.js +25 -0
  53. package/dist/src/commands/init.test.js.map +1 -0
  54. package/dist/src/commands/restore.d.ts +9 -0
  55. package/dist/src/commands/restore.js +46 -0
  56. package/dist/src/commands/restore.js.map +1 -0
  57. package/dist/src/commands/restore.test.d.ts +6 -0
  58. package/dist/src/commands/restore.test.js +137 -0
  59. package/dist/src/commands/restore.test.js.map +1 -0
  60. package/dist/src/commands/types.d.ts +41 -0
  61. package/dist/src/commands/types.js +7 -0
  62. package/dist/src/commands/types.js.map +1 -0
  63. package/dist/src/config/config.d.ts +29 -3
  64. package/dist/src/config/config.js +146 -29
  65. package/dist/src/config/config.js.map +1 -1
  66. package/dist/src/config/config.test.js +203 -9
  67. package/dist/src/config/config.test.js.map +1 -1
  68. package/dist/src/config/defaultModelConfigs.js +21 -0
  69. package/dist/src/config/defaultModelConfigs.js.map +1 -1
  70. package/dist/src/config/models.d.ts +33 -11
  71. package/dist/src/config/models.js +82 -24
  72. package/dist/src/config/models.js.map +1 -1
  73. package/dist/src/config/models.test.js +70 -76
  74. package/dist/src/config/models.test.js.map +1 -1
  75. package/dist/src/confirmation-bus/message-bus.js +1 -0
  76. package/dist/src/confirmation-bus/message-bus.js.map +1 -1
  77. package/dist/src/confirmation-bus/types.d.ts +4 -0
  78. package/dist/src/core/baseLlmClient.d.ts +3 -1
  79. package/dist/src/core/baseLlmClient.js +40 -3
  80. package/dist/src/core/baseLlmClient.js.map +1 -1
  81. package/dist/src/core/baseLlmClient.test.js +184 -7
  82. package/dist/src/core/baseLlmClient.test.js.map +1 -1
  83. package/dist/src/core/client.js +47 -13
  84. package/dist/src/core/client.js.map +1 -1
  85. package/dist/src/core/client.test.js +133 -6
  86. package/dist/src/core/client.test.js.map +1 -1
  87. package/dist/src/core/contentGenerator.js +5 -3
  88. package/dist/src/core/contentGenerator.js.map +1 -1
  89. package/dist/src/core/contentGenerator.test.js +29 -22
  90. package/dist/src/core/contentGenerator.test.js.map +1 -1
  91. package/dist/src/core/coreToolScheduler.d.ts +1 -1
  92. package/dist/src/core/coreToolScheduler.js +76 -34
  93. package/dist/src/core/coreToolScheduler.js.map +1 -1
  94. package/dist/src/core/coreToolScheduler.test.js +135 -37
  95. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  96. package/dist/src/core/geminiChat.js +60 -29
  97. package/dist/src/core/geminiChat.js.map +1 -1
  98. package/dist/src/core/geminiChat.test.js +236 -188
  99. package/dist/src/core/geminiChat.test.js.map +1 -1
  100. package/dist/src/core/geminiChat_network_retry.test.d.ts +6 -0
  101. package/dist/src/core/geminiChat_network_retry.test.js +198 -0
  102. package/dist/src/core/geminiChat_network_retry.test.js.map +1 -0
  103. package/dist/src/core/logger.js.map +1 -1
  104. package/dist/src/core/nonInteractiveToolExecutor.test.js +4 -5
  105. package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
  106. package/dist/src/core/prompts.js +13 -11
  107. package/dist/src/core/prompts.js.map +1 -1
  108. package/dist/src/core/prompts.test.js +19 -8
  109. package/dist/src/core/prompts.test.js.map +1 -1
  110. package/dist/src/core/sessionHookTriggers.d.ts +28 -0
  111. package/dist/src/core/sessionHookTriggers.js +68 -0
  112. package/dist/src/core/sessionHookTriggers.js.map +1 -0
  113. package/dist/src/core/turn.d.ts +1 -0
  114. package/dist/src/core/turn.js +1 -1
  115. package/dist/src/core/turn.js.map +1 -1
  116. package/dist/src/fallback/handler.js +56 -115
  117. package/dist/src/fallback/handler.js.map +1 -1
  118. package/dist/src/fallback/handler.test.js +124 -278
  119. package/dist/src/fallback/handler.test.js.map +1 -1
  120. package/dist/src/generated/git-commit.d.ts +2 -2
  121. package/dist/src/generated/git-commit.js +2 -2
  122. package/dist/src/hooks/hookEventHandler.js +59 -1
  123. package/dist/src/hooks/hookEventHandler.js.map +1 -1
  124. package/dist/src/hooks/hookEventHandler.test.js +8 -1
  125. package/dist/src/hooks/hookEventHandler.test.js.map +1 -1
  126. package/dist/src/hooks/hookRegistry.d.ts +0 -7
  127. package/dist/src/hooks/hookRegistry.js +8 -21
  128. package/dist/src/hooks/hookRegistry.js.map +1 -1
  129. package/dist/src/hooks/hookRegistry.test.js +2 -7
  130. package/dist/src/hooks/hookRegistry.test.js.map +1 -1
  131. package/dist/src/hooks/hookRunner.js +12 -2
  132. package/dist/src/hooks/hookRunner.js.map +1 -1
  133. package/dist/src/hooks/hookRunner.test.js +1 -1
  134. package/dist/src/hooks/hookRunner.test.js.map +1 -1
  135. package/dist/src/hooks/hookSystem.d.ts +0 -8
  136. package/dist/src/hooks/hookSystem.js +0 -18
  137. package/dist/src/hooks/hookSystem.js.map +1 -1
  138. package/dist/src/hooks/hookSystem.test.js +123 -18
  139. package/dist/src/hooks/hookSystem.test.js.map +1 -1
  140. package/dist/src/hooks/index.d.ts +3 -1
  141. package/dist/src/hooks/index.js +3 -0
  142. package/dist/src/hooks/index.js.map +1 -1
  143. package/dist/src/hooks/types.d.ts +1 -2
  144. package/dist/src/hooks/types.js +0 -1
  145. package/dist/src/hooks/types.js.map +1 -1
  146. package/dist/src/ide/detect-ide.test.js +32 -1
  147. package/dist/src/ide/detect-ide.test.js.map +1 -1
  148. package/dist/src/ide/ide-client.js +2 -0
  149. package/dist/src/ide/ide-client.js.map +1 -1
  150. package/dist/src/ide/ide-installer.test.js +1 -1
  151. package/dist/src/ide/ide-installer.test.js.map +1 -1
  152. package/dist/src/index.d.ts +8 -0
  153. package/dist/src/index.js +8 -0
  154. package/dist/src/index.js.map +1 -1
  155. package/dist/src/mcp/oauth-provider.js.map +1 -1
  156. package/dist/src/output/json-formatter.d.ts +2 -2
  157. package/dist/src/output/json-formatter.js +6 -3
  158. package/dist/src/output/json-formatter.js.map +1 -1
  159. package/dist/src/output/json-formatter.test.js +37 -9
  160. package/dist/src/output/json-formatter.test.js.map +1 -1
  161. package/dist/src/output/stream-json-formatter.js +6 -0
  162. package/dist/src/output/stream-json-formatter.js.map +1 -1
  163. package/dist/src/output/stream-json-formatter.test.js +98 -100
  164. package/dist/src/output/stream-json-formatter.test.js.map +1 -1
  165. package/dist/src/output/types.d.ts +3 -0
  166. package/dist/src/output/types.js.map +1 -1
  167. package/dist/src/policy/config.js +97 -11
  168. package/dist/src/policy/config.js.map +1 -1
  169. package/dist/src/policy/persistence.test.d.ts +6 -0
  170. package/dist/src/policy/persistence.test.js +154 -0
  171. package/dist/src/policy/persistence.test.js.map +1 -0
  172. package/dist/src/policy/policies/agent.toml +31 -0
  173. package/dist/src/policy/policy-engine.d.ts +10 -1
  174. package/dist/src/policy/policy-engine.js +79 -5
  175. package/dist/src/policy/policy-engine.js.map +1 -1
  176. package/dist/src/policy/policy-engine.test.js +26 -2
  177. package/dist/src/policy/policy-engine.test.js.map +1 -1
  178. package/dist/src/policy/policy-updater.test.d.ts +6 -0
  179. package/dist/src/policy/policy-updater.test.js +116 -0
  180. package/dist/src/policy/policy-updater.test.js.map +1 -0
  181. package/dist/src/policy/shell-safety.test.d.ts +6 -0
  182. package/dist/src/policy/shell-safety.test.js +75 -0
  183. package/dist/src/policy/shell-safety.test.js.map +1 -0
  184. package/dist/src/policy/toml-loader.d.ts +11 -5
  185. package/dist/src/policy/toml-loader.js +38 -23
  186. package/dist/src/policy/toml-loader.js.map +1 -1
  187. package/dist/src/policy/toml-loader.test.js +28 -7
  188. package/dist/src/policy/toml-loader.test.js.map +1 -1
  189. package/dist/src/policy/types.d.ts +15 -0
  190. package/dist/src/resources/resource-registry.d.ts +30 -0
  191. package/dist/src/resources/resource-registry.js +57 -0
  192. package/dist/src/resources/resource-registry.js.map +1 -0
  193. package/dist/src/resources/resource-registry.test.d.ts +6 -0
  194. package/dist/src/resources/resource-registry.test.js +54 -0
  195. package/dist/src/resources/resource-registry.test.js.map +1 -0
  196. package/dist/src/routing/modelRouterService.js +0 -15
  197. package/dist/src/routing/modelRouterService.js.map +1 -1
  198. package/dist/src/routing/modelRouterService.test.js +0 -62
  199. package/dist/src/routing/modelRouterService.test.js.map +1 -1
  200. package/dist/src/routing/strategies/classifierStrategy.js +10 -21
  201. package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
  202. package/dist/src/routing/strategies/classifierStrategy.test.js +2 -1
  203. package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -1
  204. package/dist/src/routing/strategies/fallbackStrategy.js +23 -12
  205. package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -1
  206. package/dist/src/routing/strategies/fallbackStrategy.test.js +69 -39
  207. package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -1
  208. package/dist/src/routing/strategies/overrideStrategy.js +4 -3
  209. package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
  210. package/dist/src/safety/checker-runner.js +17 -6
  211. package/dist/src/safety/checker-runner.js.map +1 -1
  212. package/dist/src/services/chatCompressionService.js +15 -1
  213. package/dist/src/services/chatCompressionService.js.map +1 -1
  214. package/dist/src/services/chatCompressionService.test.js +2 -0
  215. package/dist/src/services/chatCompressionService.test.js.map +1 -1
  216. package/dist/src/services/chatRecordingService.d.ts +14 -0
  217. package/dist/src/services/chatRecordingService.js +37 -0
  218. package/dist/src/services/chatRecordingService.js.map +1 -1
  219. package/dist/src/services/fileSystemService.d.ts +0 -9
  220. package/dist/src/services/fileSystemService.js +0 -11
  221. package/dist/src/services/fileSystemService.js.map +1 -1
  222. package/dist/src/services/gitService.js +5 -0
  223. package/dist/src/services/gitService.js.map +1 -1
  224. package/dist/src/services/gitService.test.js +28 -0
  225. package/dist/src/services/gitService.test.js.map +1 -1
  226. package/dist/src/services/loopDetectionService.js +2 -2
  227. package/dist/src/services/loopDetectionService.js.map +1 -1
  228. package/dist/src/services/modelConfig.golden.test.js +32 -0
  229. package/dist/src/services/modelConfig.golden.test.js.map +1 -1
  230. package/dist/src/services/modelConfigService.d.ts +3 -0
  231. package/dist/src/services/modelConfigService.js +3 -2
  232. package/dist/src/services/modelConfigService.js.map +1 -1
  233. package/dist/src/services/modelConfigService.test.js +110 -0
  234. package/dist/src/services/modelConfigService.test.js.map +1 -1
  235. package/dist/src/services/modelConfigServiceTestUtils.d.ts +10 -0
  236. package/dist/src/services/modelConfigServiceTestUtils.js +17 -0
  237. package/dist/src/services/modelConfigServiceTestUtils.js.map +1 -0
  238. package/dist/src/services/sessionSummaryService.d.ts +28 -0
  239. package/dist/src/services/sessionSummaryService.js +131 -0
  240. package/dist/src/services/sessionSummaryService.js.map +1 -0
  241. package/dist/src/services/sessionSummaryService.test.d.ts +6 -0
  242. package/dist/src/services/sessionSummaryService.test.js +785 -0
  243. package/dist/src/services/sessionSummaryService.test.js.map +1 -0
  244. package/dist/src/services/sessionSummaryUtils.d.ts +16 -0
  245. package/dist/src/services/sessionSummaryUtils.js +129 -0
  246. package/dist/src/services/sessionSummaryUtils.js.map +1 -0
  247. package/dist/src/services/sessionSummaryUtils.test.d.ts +6 -0
  248. package/dist/src/services/sessionSummaryUtils.test.js +137 -0
  249. package/dist/src/services/sessionSummaryUtils.test.js.map +1 -0
  250. package/dist/src/services/shellExecutionService.js +28 -22
  251. package/dist/src/services/shellExecutionService.js.map +1 -1
  252. package/dist/src/services/shellExecutionService.test.js +46 -4
  253. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  254. package/dist/src/services/test-data/resolved-aliases-retry.golden.json +238 -0
  255. package/dist/src/services/test-data/resolved-aliases.golden.json +16 -0
  256. package/dist/src/telemetry/activity-detector.test.js.map +1 -1
  257. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +1 -0
  258. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +28 -5
  259. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  260. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +67 -1
  261. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  262. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +1 -0
  263. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +3 -1
  264. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  265. package/dist/src/telemetry/config.js +2 -0
  266. package/dist/src/telemetry/config.js.map +1 -1
  267. package/dist/src/telemetry/config.test.js +25 -0
  268. package/dist/src/telemetry/config.test.js.map +1 -1
  269. package/dist/src/telemetry/gcp-exporters.d.ts +4 -3
  270. package/dist/src/telemetry/gcp-exporters.js +8 -4
  271. package/dist/src/telemetry/gcp-exporters.js.map +1 -1
  272. package/dist/src/telemetry/index.d.ts +1 -1
  273. package/dist/src/telemetry/index.js +1 -1
  274. package/dist/src/telemetry/index.js.map +1 -1
  275. package/dist/src/telemetry/loggers.d.ts +2 -1
  276. package/dist/src/telemetry/loggers.js +345 -335
  277. package/dist/src/telemetry/loggers.js.map +1 -1
  278. package/dist/src/telemetry/loggers.test.js +20 -5
  279. package/dist/src/telemetry/loggers.test.js.map +1 -1
  280. package/dist/src/telemetry/metrics.test.js.map +1 -1
  281. package/dist/src/telemetry/sdk.d.ts +9 -2
  282. package/dist/src/telemetry/sdk.js +143 -17
  283. package/dist/src/telemetry/sdk.js.map +1 -1
  284. package/dist/src/telemetry/sdk.test.js +130 -28
  285. package/dist/src/telemetry/sdk.test.js.map +1 -1
  286. package/dist/src/telemetry/startupProfiler.js +26 -3
  287. package/dist/src/telemetry/startupProfiler.js.map +1 -1
  288. package/dist/src/telemetry/startupProfiler.test.js +49 -7
  289. package/dist/src/telemetry/startupProfiler.test.js.map +1 -1
  290. package/dist/src/telemetry/telemetry.test.js +10 -3
  291. package/dist/src/telemetry/telemetry.test.js.map +1 -1
  292. package/dist/src/telemetry/trace.js.map +1 -1
  293. package/dist/src/telemetry/types.d.ts +31 -6
  294. package/dist/src/telemetry/types.js +47 -8
  295. package/dist/src/telemetry/types.js.map +1 -1
  296. package/dist/src/telemetry/uiTelemetry.d.ts +1 -0
  297. package/dist/src/telemetry/uiTelemetry.js +2 -0
  298. package/dist/src/telemetry/uiTelemetry.js.map +1 -1
  299. package/dist/src/telemetry/uiTelemetry.test.js +4 -0
  300. package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
  301. package/dist/src/test-utils/mock-message-bus.js.map +1 -1
  302. package/dist/src/tools/confirmation-policy.test.d.ts +6 -0
  303. package/dist/src/tools/confirmation-policy.test.js +152 -0
  304. package/dist/src/tools/confirmation-policy.test.js.map +1 -0
  305. package/dist/src/tools/edit.js +5 -0
  306. package/dist/src/tools/edit.js.map +1 -1
  307. package/dist/src/tools/edit.test.js.map +1 -1
  308. package/dist/src/tools/grep.js.map +1 -1
  309. package/dist/src/tools/mcp-client-manager.d.ts +2 -1
  310. package/dist/src/tools/mcp-client-manager.js +20 -4
  311. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  312. package/dist/src/tools/mcp-client-manager.test.js +13 -10
  313. package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
  314. package/dist/src/tools/mcp-client.d.ts +39 -3
  315. package/dist/src/tools/mcp-client.js +433 -168
  316. package/dist/src/tools/mcp-client.js.map +1 -1
  317. package/dist/src/tools/mcp-client.test.js +648 -28
  318. package/dist/src/tools/mcp-client.test.js.map +1 -1
  319. package/dist/src/tools/mcp-tool.js +13 -0
  320. package/dist/src/tools/mcp-tool.js.map +1 -1
  321. package/dist/src/tools/mcp-tool.test.js +25 -0
  322. package/dist/src/tools/mcp-tool.test.js.map +1 -1
  323. package/dist/src/tools/memoryTool.js +1 -0
  324. package/dist/src/tools/memoryTool.js.map +1 -1
  325. package/dist/src/tools/modifiable-tool.js.map +1 -1
  326. package/dist/src/tools/modifiable-tool.test.js +22 -13
  327. package/dist/src/tools/modifiable-tool.test.js.map +1 -1
  328. package/dist/src/tools/read-file.js +1 -1
  329. package/dist/src/tools/read-file.js.map +1 -1
  330. package/dist/src/tools/read-file.test.js.map +1 -1
  331. package/dist/src/tools/read-many-files.js +6 -4
  332. package/dist/src/tools/read-many-files.js.map +1 -1
  333. package/dist/src/tools/read-many-files.test.js +1 -1
  334. package/dist/src/tools/read-many-files.test.js.map +1 -1
  335. package/dist/src/tools/shell.d.ts +2 -1
  336. package/dist/src/tools/shell.js +15 -1
  337. package/dist/src/tools/shell.js.map +1 -1
  338. package/dist/src/tools/shell.test.js +2 -1
  339. package/dist/src/tools/shell.test.js.map +1 -1
  340. package/dist/src/tools/smart-edit.js +5 -0
  341. package/dist/src/tools/smart-edit.js.map +1 -1
  342. package/dist/src/tools/smart-edit.test.js.map +1 -1
  343. package/dist/src/tools/tool-names.d.ts +2 -0
  344. package/dist/src/tools/tool-names.js +2 -0
  345. package/dist/src/tools/tool-names.js.map +1 -1
  346. package/dist/src/tools/tools.d.ts +19 -0
  347. package/dist/src/tools/tools.js +29 -8
  348. package/dist/src/tools/tools.js.map +1 -1
  349. package/dist/src/tools/web-fetch.js +17 -4
  350. package/dist/src/tools/web-fetch.js.map +1 -1
  351. package/dist/src/tools/web-fetch.test.js +1 -0
  352. package/dist/src/tools/web-fetch.test.js.map +1 -1
  353. package/dist/src/tools/write-file.js +5 -0
  354. package/dist/src/tools/write-file.js.map +1 -1
  355. package/dist/src/tools/write-file.test.js.map +1 -1
  356. package/dist/src/utils/bfsFileSearch.d.ts +8 -0
  357. package/dist/src/utils/bfsFileSearch.js +63 -23
  358. package/dist/src/utils/bfsFileSearch.js.map +1 -1
  359. package/dist/src/utils/bfsFileSearch.test.js +65 -1
  360. package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
  361. package/dist/src/utils/checkpointUtils.d.ts +82 -0
  362. package/dist/src/utils/checkpointUtils.js +117 -0
  363. package/dist/src/utils/checkpointUtils.js.map +1 -0
  364. package/dist/src/utils/checkpointUtils.test.d.ts +6 -0
  365. package/dist/src/utils/checkpointUtils.test.js +229 -0
  366. package/dist/src/utils/checkpointUtils.test.js.map +1 -0
  367. package/dist/src/utils/debugLogger.d.ts +3 -0
  368. package/dist/src/utils/debugLogger.js +27 -0
  369. package/dist/src/utils/debugLogger.js.map +1 -1
  370. package/dist/src/utils/editCorrector.test.js +4 -0
  371. package/dist/src/utils/editCorrector.test.js.map +1 -1
  372. package/dist/src/utils/editor.d.ts +9 -1
  373. package/dist/src/utils/editor.js +23 -14
  374. package/dist/src/utils/editor.js.map +1 -1
  375. package/dist/src/utils/errors.d.ts +8 -0
  376. package/dist/src/utils/errors.js +39 -2
  377. package/dist/src/utils/errors.js.map +1 -1
  378. package/dist/src/utils/errors.test.d.ts +6 -0
  379. package/dist/src/utils/errors.test.js +155 -0
  380. package/dist/src/utils/errors.test.js.map +1 -0
  381. package/dist/src/utils/extensionLoader.d.ts +2 -2
  382. package/dist/src/utils/extensionLoader.js +5 -6
  383. package/dist/src/utils/extensionLoader.js.map +1 -1
  384. package/dist/src/utils/extensionLoader.test.js +11 -0
  385. package/dist/src/utils/extensionLoader.test.js.map +1 -1
  386. package/dist/src/utils/fetch.d.ts +1 -1
  387. package/dist/src/utils/fetch.js +3 -3
  388. package/dist/src/utils/fetch.js.map +1 -1
  389. package/dist/src/utils/fileUtils.test.js +15 -0
  390. package/dist/src/utils/fileUtils.test.js.map +1 -1
  391. package/dist/src/utils/filesearch/crawlCache.js.map +1 -1
  392. package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
  393. package/dist/src/utils/flashFallback.test.js +1 -1
  394. package/dist/src/utils/flashFallback.test.js.map +1 -1
  395. package/dist/src/utils/googleErrors.js +31 -18
  396. package/dist/src/utils/googleErrors.js.map +1 -1
  397. package/dist/src/utils/googleErrors.test.js +10 -2
  398. package/dist/src/utils/googleErrors.test.js.map +1 -1
  399. package/dist/src/utils/googleQuotaErrors.d.ts +3 -3
  400. package/dist/src/utils/googleQuotaErrors.js +32 -6
  401. package/dist/src/utils/googleQuotaErrors.js.map +1 -1
  402. package/dist/src/utils/googleQuotaErrors.test.js +94 -2
  403. package/dist/src/utils/googleQuotaErrors.test.js.map +1 -1
  404. package/dist/src/utils/nextSpeakerChecker.test.js +4 -0
  405. package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
  406. package/dist/src/utils/pathCorrector.js +12 -2
  407. package/dist/src/utils/pathCorrector.js.map +1 -1
  408. package/dist/src/utils/pathCorrector.test.js +6 -2
  409. package/dist/src/utils/pathCorrector.test.js.map +1 -1
  410. package/dist/src/utils/retry.d.ts +11 -0
  411. package/dist/src/utils/retry.js +54 -13
  412. package/dist/src/utils/retry.js.map +1 -1
  413. package/dist/src/utils/retry.test.js +170 -10
  414. package/dist/src/utils/retry.test.js.map +1 -1
  415. package/dist/src/utils/shell-permissions.d.ts +52 -0
  416. package/dist/src/utils/shell-permissions.js +188 -0
  417. package/dist/src/utils/shell-permissions.js.map +1 -0
  418. package/dist/src/utils/shell-permissions.test.d.ts +6 -0
  419. package/dist/src/utils/shell-permissions.test.js +347 -0
  420. package/dist/src/utils/shell-permissions.test.js.map +1 -0
  421. package/dist/src/utils/shell-utils.d.ts +10 -47
  422. package/dist/src/utils/shell-utils.js +1 -182
  423. package/dist/src/utils/shell-utils.js.map +1 -1
  424. package/dist/src/utils/shell-utils.test.js +1 -288
  425. package/dist/src/utils/shell-utils.test.js.map +1 -1
  426. package/dist/src/utils/terminalSerializer.test.js +17 -0
  427. package/dist/src/utils/terminalSerializer.test.js.map +1 -1
  428. package/dist/src/utils/tool-utils.js.map +1 -1
  429. package/dist/src/utils/version.d.ts +6 -0
  430. package/dist/src/utils/version.js +15 -0
  431. package/dist/src/utils/version.js.map +1 -0
  432. package/dist/src/utils/version.test.d.ts +6 -0
  433. package/dist/src/utils/version.test.js +39 -0
  434. package/dist/src/utils/version.test.js.map +1 -0
  435. package/dist/tsconfig.tsbuildinfo +1 -1
  436. package/package.json +1 -1
@@ -8,7 +8,7 @@ import { AjvJsonSchemaValidator } from '@modelcontextprotocol/sdk/validation/ajv
8
8
  import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
9
9
  import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
10
10
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
11
- import { ListRootsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
11
+ import { ListResourcesResultSchema, ListRootsRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, ToolListChangedNotificationSchema, } from '@modelcontextprotocol/sdk/types.js';
12
12
  import { parse } from 'shell-quote';
13
13
  import { AuthProviderType } from '../config/config.js';
14
14
  import { GoogleCredentialProvider } from '../mcp/google-auth-provider.js';
@@ -19,7 +19,7 @@ import { pathToFileURL } from 'node:url';
19
19
  import { MCPOAuthProvider } from '../mcp/oauth-provider.js';
20
20
  import { MCPOAuthTokenStorage } from '../mcp/oauth-token-storage.js';
21
21
  import { OAuthUtils } from '../mcp/oauth-utils.js';
22
- import { getErrorMessage } from '../utils/errors.js';
22
+ import { getErrorMessage, isAuthenticationError, UnauthorizedError, } from '../utils/errors.js';
23
23
  import { debugLogger } from '../utils/debugLogger.js';
24
24
  import { coreEvents } from '../utils/events.js';
25
25
  import { loadYamlConfig } from '@machina.ai/config-yaml';
@@ -95,18 +95,28 @@ export class McpClient {
95
95
  serverConfig;
96
96
  toolRegistry;
97
97
  promptRegistry;
98
+ resourceRegistry;
98
99
  workspaceContext;
100
+ cliConfig;
99
101
  debugMode;
102
+ onToolsUpdated;
100
103
  client;
101
104
  transport;
102
105
  status = MCPServerStatus.DISCONNECTED;
103
- constructor(serverName, serverConfig, toolRegistry, promptRegistry, workspaceContext, debugMode) {
106
+ isRefreshingTools = false;
107
+ pendingToolRefresh = false;
108
+ isRefreshingResources = false;
109
+ pendingResourceRefresh = false;
110
+ constructor(serverName, serverConfig, toolRegistry, promptRegistry, resourceRegistry, workspaceContext, cliConfig, debugMode, onToolsUpdated) {
104
111
  this.serverName = serverName;
105
112
  this.serverConfig = serverConfig;
106
113
  this.toolRegistry = toolRegistry;
107
114
  this.promptRegistry = promptRegistry;
115
+ this.resourceRegistry = resourceRegistry;
108
116
  this.workspaceContext = workspaceContext;
117
+ this.cliConfig = cliConfig;
109
118
  this.debugMode = debugMode;
119
+ this.onToolsUpdated = onToolsUpdated;
110
120
  }
111
121
  /**
112
122
  * Connects to the MCP server.
@@ -118,6 +128,7 @@ export class McpClient {
118
128
  this.updateStatus(MCPServerStatus.CONNECTING);
119
129
  try {
120
130
  this.client = await connectToMcpServer(this.serverName, this.serverConfig, this.debugMode, this.workspaceContext);
131
+ this.registerNotificationHandlers();
121
132
  const originalOnError = this.client.onerror;
122
133
  this.client.onerror = (error) => {
123
134
  if (this.status !== MCPServerStatus.CONNECTED) {
@@ -142,8 +153,10 @@ export class McpClient {
142
153
  this.assertConnected();
143
154
  const prompts = await this.discoverPrompts();
144
155
  const tools = await this.discoverTools(cliConfig);
145
- if (prompts.length === 0 && tools.length === 0) {
146
- throw new Error('No prompts or tools found on the server.');
156
+ const resources = await this.discoverResources();
157
+ this.updateResourceRegistry(resources);
158
+ if (prompts.length === 0 && tools.length === 0 && resources.length === 0) {
159
+ throw new Error('No prompts, tools, or resources found on the server.');
147
160
  }
148
161
  for (const tool of tools) {
149
162
  this.toolRegistry.registerTool(tool);
@@ -159,6 +172,7 @@ export class McpClient {
159
172
  }
160
173
  this.toolRegistry.removeMcpToolsByServer(this.serverName);
161
174
  this.promptRegistry.removePromptsByServer(this.serverName);
175
+ this.resourceRegistry.removeResourcesByServer(this.serverName);
162
176
  this.updateStatus(MCPServerStatus.DISCONNECTING);
163
177
  const client = this.client;
164
178
  this.client = undefined;
@@ -185,20 +199,157 @@ export class McpClient {
185
199
  throw new Error(`Client is not connected, must connect before interacting with the server. Current state is ${this.status}`);
186
200
  }
187
201
  }
188
- async discoverTools(cliConfig) {
202
+ async discoverTools(cliConfig, options) {
189
203
  this.assertConnected();
190
- return discoverTools(this.serverName, this.serverConfig, this.client, cliConfig, this.toolRegistry.getMessageBus());
204
+ return discoverTools(this.serverName, this.serverConfig, this.client, cliConfig, this.toolRegistry.getMessageBus(), options ?? {
205
+ timeout: this.serverConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
206
+ });
191
207
  }
192
208
  async discoverPrompts() {
193
209
  this.assertConnected();
194
210
  return discoverPrompts(this.serverName, this.client, this.promptRegistry);
195
211
  }
212
+ async discoverResources() {
213
+ this.assertConnected();
214
+ return discoverResources(this.serverName, this.client);
215
+ }
216
+ updateResourceRegistry(resources) {
217
+ this.resourceRegistry.setResourcesForServer(this.serverName, resources);
218
+ }
219
+ async readResource(uri) {
220
+ this.assertConnected();
221
+ return this.client.request({
222
+ method: 'resources/read',
223
+ params: { uri },
224
+ }, ReadResourceResultSchema);
225
+ }
226
+ /**
227
+ * Registers notification handlers for dynamic updates from the MCP server.
228
+ * This includes handlers for tool list changes and resource list changes.
229
+ */
230
+ registerNotificationHandlers() {
231
+ if (!this.client) {
232
+ return;
233
+ }
234
+ const capabilities = this.client.getServerCapabilities();
235
+ if (capabilities?.tools?.listChanged) {
236
+ debugLogger.log(`Server '${this.serverName}' supports tool updates. Listening for changes...`);
237
+ this.client.setNotificationHandler(ToolListChangedNotificationSchema, async () => {
238
+ debugLogger.log(`🔔 Received tool update notification from '${this.serverName}'`);
239
+ await this.refreshTools();
240
+ });
241
+ }
242
+ if (capabilities?.resources?.listChanged) {
243
+ debugLogger.log(`Server '${this.serverName}' supports resource updates. Listening for changes...`);
244
+ this.client.setNotificationHandler(ResourceListChangedNotificationSchema, async () => {
245
+ debugLogger.log(`🔔 Received resource update notification from '${this.serverName}'`);
246
+ await this.refreshResources();
247
+ });
248
+ }
249
+ }
250
+ /**
251
+ * Refreshes the resources for this server by re-querying the MCP `resources/list` endpoint.
252
+ *
253
+ * This method implements a **Coalescing Pattern** to handle rapid bursts of notifications
254
+ * (e.g., during server startup or bulk updates) without overwhelming the server or
255
+ * creating race conditions in the ResourceRegistry.
256
+ */
257
+ async refreshResources() {
258
+ if (this.isRefreshingResources) {
259
+ debugLogger.log(`Resource refresh for '${this.serverName}' is already in progress. Pending update.`);
260
+ this.pendingResourceRefresh = true;
261
+ return;
262
+ }
263
+ this.isRefreshingResources = true;
264
+ try {
265
+ do {
266
+ this.pendingResourceRefresh = false;
267
+ if (this.status !== MCPServerStatus.CONNECTED || !this.client)
268
+ break;
269
+ const timeoutMs = this.serverConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC;
270
+ const abortController = new AbortController();
271
+ const timeoutId = setTimeout(() => abortController.abort(), timeoutMs);
272
+ let newResources;
273
+ try {
274
+ newResources = await this.discoverResources();
275
+ }
276
+ catch (err) {
277
+ debugLogger.error(`Resource discovery failed during refresh: ${getErrorMessage(err)}`);
278
+ clearTimeout(timeoutId);
279
+ break;
280
+ }
281
+ this.updateResourceRegistry(newResources);
282
+ clearTimeout(timeoutId);
283
+ coreEvents.emitFeedback('info', `Resources updated for server: ${this.serverName}`);
284
+ } while (this.pendingResourceRefresh);
285
+ }
286
+ catch (error) {
287
+ debugLogger.error(`Critical error in resource refresh loop for ${this.serverName}: ${getErrorMessage(error)}`);
288
+ }
289
+ finally {
290
+ this.isRefreshingResources = false;
291
+ this.pendingResourceRefresh = false;
292
+ }
293
+ }
196
294
  getServerConfig() {
197
295
  return this.serverConfig;
198
296
  }
199
297
  getInstructions() {
200
298
  return this.client?.getInstructions();
201
299
  }
300
+ /**
301
+ * Refreshes the tools for this server by re-querying the MCP `tools/list` endpoint.
302
+ *
303
+ * This method implements a **Coalescing Pattern** to handle rapid bursts of notifications
304
+ * (e.g., during server startup or bulk updates) without overwhelming the server or
305
+ * creating race conditions in the global ToolRegistry.
306
+ */
307
+ async refreshTools() {
308
+ if (this.isRefreshingTools) {
309
+ debugLogger.log(`Tool refresh for '${this.serverName}' is already in progress. Pending update.`);
310
+ this.pendingToolRefresh = true;
311
+ return;
312
+ }
313
+ this.isRefreshingTools = true;
314
+ try {
315
+ do {
316
+ this.pendingToolRefresh = false;
317
+ if (this.status !== MCPServerStatus.CONNECTED || !this.client)
318
+ break;
319
+ const timeoutMs = this.serverConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC;
320
+ const abortController = new AbortController();
321
+ const timeoutId = setTimeout(() => abortController.abort(), timeoutMs);
322
+ let newTools;
323
+ try {
324
+ newTools = await this.discoverTools(this.cliConfig, {
325
+ signal: abortController.signal,
326
+ });
327
+ }
328
+ catch (err) {
329
+ debugLogger.error(`Discovery failed during refresh: ${getErrorMessage(err)}`);
330
+ clearTimeout(timeoutId);
331
+ break;
332
+ }
333
+ this.toolRegistry.removeMcpToolsByServer(this.serverName);
334
+ for (const tool of newTools) {
335
+ this.toolRegistry.registerTool(tool);
336
+ }
337
+ this.toolRegistry.sortTools();
338
+ if (this.onToolsUpdated) {
339
+ await this.onToolsUpdated(abortController.signal);
340
+ }
341
+ clearTimeout(timeoutId);
342
+ coreEvents.emitFeedback('info', `Tools updated for server: ${this.serverName}`);
343
+ } while (this.pendingToolRefresh);
344
+ }
345
+ catch (error) {
346
+ debugLogger.error(`Critical error in refresh loop for ${this.serverName}: ${getErrorMessage(error)}`);
347
+ }
348
+ finally {
349
+ this.isRefreshingTools = false;
350
+ this.pendingToolRefresh = false;
351
+ }
352
+ }
202
353
  }
203
354
  /**
204
355
  * Map to track the status of each MCP server within the core package
@@ -357,21 +508,6 @@ function createAuthProvider(mcpServerConfig) {
357
508
  }
358
509
  return undefined;
359
510
  }
360
- /**
361
- * Create a transport for URL based servers (remote servers).
362
- *
363
- * @param mcpServerConfig The MCP server configuration
364
- * @param transportOptions The transport options
365
- */
366
- function createUrlTransport(mcpServerConfig, transportOptions) {
367
- if (mcpServerConfig.httpUrl) {
368
- return new StreamableHTTPClientTransport(new URL(mcpServerConfig.httpUrl), transportOptions);
369
- }
370
- if (mcpServerConfig.url) {
371
- return new SSEClientTransport(new URL(mcpServerConfig.url), transportOptions);
372
- }
373
- throw new Error('No URL configured for MCP Server');
374
- }
375
511
  /**
376
512
  * Create a transport with OAuth token for the given server configuration.
377
513
  *
@@ -388,7 +524,7 @@ async function createTransportWithOAuth(mcpServerName, mcpServerConfig, accessTo
388
524
  const transportOptions = {
389
525
  requestInit: createTransportRequestInit(mcpServerConfig, headers),
390
526
  };
391
- return createUrlTransport(mcpServerConfig, transportOptions);
527
+ return createUrlTransport(mcpServerName, mcpServerConfig, transportOptions);
392
528
  }
393
529
  catch (error) {
394
530
  coreEvents.emitFeedback('error', `Failed to create OAuth transport for server '${mcpServerName}': ${getErrorMessage(error)}`, error);
@@ -480,7 +616,7 @@ export async function connectAndDiscover(mcpServerName, mcpServerConfig, toolReg
480
616
  };
481
617
  // Attempt to discover both prompts and tools
482
618
  const prompts = await discoverPrompts(mcpServerName, mcpClient, promptRegistry);
483
- const tools = await discoverTools(mcpServerName, mcpServerConfig, mcpClient, cliConfig, toolRegistry.getMessageBus());
619
+ const tools = await discoverTools(mcpServerName, mcpServerConfig, mcpClient, cliConfig, toolRegistry.getMessageBus(), { timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC });
484
620
  // If we have neither prompts nor tools, it's a failed discovery
485
621
  if (prompts.length === 0 && tools.length === 0) {
486
622
  throw new Error('No prompts or tools found on the server.');
@@ -495,6 +631,7 @@ export async function connectAndDiscover(mcpServerName, mcpServerConfig, toolReg
495
631
  }
496
632
  catch (error) {
497
633
  if (mcpClient) {
634
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
498
635
  mcpClient.close();
499
636
  }
500
637
  coreEvents.emitFeedback('error', `Error connecting to MCP server '${mcpServerName}': ${getErrorMessage(error)}`, error);
@@ -514,12 +651,12 @@ export async function connectAndDiscover(mcpServerName, mcpServerConfig, toolReg
514
651
  * @returns A promise that resolves to an array of discovered and enabled tools.
515
652
  * @throws An error if no enabled tools are found or if the server provides invalid function declarations.
516
653
  */
517
- export async function discoverTools(mcpServerName, mcpServerConfig, mcpClient, cliConfig, messageBus) {
654
+ export async function discoverTools(mcpServerName, mcpServerConfig, mcpClient, cliConfig, messageBus, options) {
518
655
  try {
519
656
  // Only request tools if the server supports them.
520
657
  if (mcpClient.getServerCapabilities()?.tools == null)
521
658
  return [];
522
- const response = await mcpClient.listTools({});
659
+ const response = await mcpClient.listTools({}, options);
523
660
  const discoveredTools = [];
524
661
  for (const toolDef of response.tools) {
525
662
  try {
@@ -634,6 +771,35 @@ export async function discoverPrompts(mcpServerName, mcpClient, promptRegistry)
634
771
  return [];
635
772
  }
636
773
  }
774
+ export async function discoverResources(mcpServerName, mcpClient) {
775
+ if (mcpClient.getServerCapabilities()?.resources == null) {
776
+ return [];
777
+ }
778
+ const resources = await listResources(mcpServerName, mcpClient);
779
+ return resources;
780
+ }
781
+ async function listResources(mcpServerName, mcpClient) {
782
+ const resources = [];
783
+ let cursor;
784
+ try {
785
+ do {
786
+ const response = await mcpClient.request({
787
+ method: 'resources/list',
788
+ params: cursor ? { cursor } : {},
789
+ }, ListResourcesResultSchema);
790
+ resources.push(...(response.resources ?? []));
791
+ cursor = response.nextCursor ?? undefined;
792
+ } while (cursor);
793
+ }
794
+ catch (error) {
795
+ if (error instanceof Error && error.message?.includes('Method not found')) {
796
+ return [];
797
+ }
798
+ coreEvents.emitFeedback('error', `Error discovering resources from ${mcpServerName}: ${getErrorMessage(error)}`, error);
799
+ throw error;
800
+ }
801
+ return resources;
802
+ }
637
803
  /**
638
804
  * Invokes a prompt on a connected MCP client.
639
805
  *
@@ -674,6 +840,116 @@ export async function invokeMcpPrompt(mcpServerName, mcpClient, promptName, prom
674
840
  export function hasNetworkTransport(config) {
675
841
  return !!(config.url || config.httpUrl);
676
842
  }
843
+ /**
844
+ * Helper function to retrieve a stored OAuth token for an MCP server.
845
+ * Handles token validation and refresh automatically.
846
+ *
847
+ * @param serverName The name of the MCP server
848
+ * @returns The valid access token, or null if no token is stored
849
+ */
850
+ async function getStoredOAuthToken(serverName) {
851
+ const tokenStorage = new MCPOAuthTokenStorage();
852
+ const credentials = await tokenStorage.getCredentials(serverName);
853
+ if (!credentials)
854
+ return null;
855
+ const authProvider = new MCPOAuthProvider(tokenStorage);
856
+ return authProvider.getValidToken(serverName, {
857
+ // Pass client ID if available
858
+ clientId: credentials.clientId,
859
+ });
860
+ }
861
+ /**
862
+ * Helper function to create an SSE transport with optional OAuth authentication.
863
+ *
864
+ * @param config The MCP server configuration
865
+ * @param accessToken Optional OAuth access token for authentication
866
+ * @returns A configured SSE transport ready for connection
867
+ */
868
+ function createSSETransportWithAuth(config, accessToken) {
869
+ const headers = {
870
+ ...config.headers,
871
+ ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}),
872
+ };
873
+ const options = {};
874
+ if (Object.keys(headers).length > 0) {
875
+ options.requestInit = { headers };
876
+ }
877
+ return new SSEClientTransport(new URL(config.url), options);
878
+ }
879
+ /**
880
+ * Helper function to connect a client using SSE transport with optional OAuth.
881
+ *
882
+ * @param client The MCP client to connect
883
+ * @param config The MCP server configuration
884
+ * @param accessToken Optional OAuth access token for authentication
885
+ */
886
+ async function connectWithSSETransport(client, config, accessToken) {
887
+ const transport = createSSETransportWithAuth(config, accessToken);
888
+ await client.connect(transport, {
889
+ timeout: config.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
890
+ });
891
+ }
892
+ /**
893
+ * Helper function to show authentication required message and throw error.
894
+ * Checks if there's a stored token that was rejected (requires re-auth).
895
+ *
896
+ * @param serverName The name of the MCP server
897
+ * @throws Always throws an error with authentication instructions
898
+ */
899
+ async function showAuthRequiredMessage(serverName) {
900
+ const hasRejectedToken = !!(await getStoredOAuthToken(serverName));
901
+ const message = hasRejectedToken
902
+ ? `MCP server '${serverName}' rejected stored OAuth token. Please re-authenticate using: /mcp auth ${serverName}`
903
+ : `MCP server '${serverName}' requires authentication using: /mcp auth ${serverName}`;
904
+ coreEvents.emitFeedback('info', message);
905
+ throw new UnauthorizedError(message);
906
+ }
907
+ /**
908
+ * Helper function to retry connection with OAuth token after authentication.
909
+ * Handles both HTTP and SSE transports based on what previously failed.
910
+ *
911
+ * @param client The MCP client to connect
912
+ * @param serverName The name of the MCP server
913
+ * @param config The MCP server configuration
914
+ * @param accessToken The OAuth access token to use
915
+ * @param httpReturned404 Whether the HTTP transport returned 404 (indicating SSE-only server)
916
+ */
917
+ async function retryWithOAuth(client, serverName, config, accessToken, httpReturned404) {
918
+ if (httpReturned404) {
919
+ // HTTP returned 404, only try SSE
920
+ debugLogger.log(`Retrying SSE connection to '${serverName}' with OAuth token...`);
921
+ await connectWithSSETransport(client, config, accessToken);
922
+ debugLogger.log(`Successfully connected to '${serverName}' using SSE with OAuth.`);
923
+ return;
924
+ }
925
+ // HTTP returned 401, try HTTP with OAuth first
926
+ debugLogger.log(`Retrying connection to '${serverName}' with OAuth token...`);
927
+ const httpTransport = await createTransportWithOAuth(serverName, config, accessToken);
928
+ if (!httpTransport) {
929
+ throw new Error(`Failed to create OAuth transport for server '${serverName}'`);
930
+ }
931
+ try {
932
+ await client.connect(httpTransport, {
933
+ timeout: config.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
934
+ });
935
+ debugLogger.log(`Successfully connected to '${serverName}' using HTTP with OAuth.`);
936
+ }
937
+ catch (httpError) {
938
+ await httpTransport.close();
939
+ // If HTTP+OAuth returns 404 and auto-detection enabled, try SSE+OAuth
940
+ if (String(httpError).includes('404') &&
941
+ config.url &&
942
+ !config.type &&
943
+ !config.httpUrl) {
944
+ debugLogger.log(`HTTP with OAuth returned 404, trying SSE with OAuth...`);
945
+ await connectWithSSETransport(client, config, accessToken);
946
+ debugLogger.log(`Successfully connected to '${serverName}' using SSE with OAuth.`);
947
+ }
948
+ else {
949
+ throw httpError;
950
+ }
951
+ }
952
+ }
677
953
  /**
678
954
  * Creates and connects an MCP client to a server based on the provided configuration.
679
955
  * It determines the appropriate transport (Stdio, SSE, or Streamable HTTP) and
@@ -733,6 +1009,9 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
733
1009
  unlistenDirectories?.();
734
1010
  unlistenDirectories = undefined;
735
1011
  };
1012
+ let firstAttemptError = null;
1013
+ let httpReturned404 = false; // Track if HTTP returned 404 to skip it in OAuth retry
1014
+ let sseError = null; // Track SSE fallback error
736
1015
  try {
737
1016
  const transport = await createTransport(mcpServerName, mcpServerConfig, debugMode);
738
1017
  try {
@@ -743,52 +1022,92 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
743
1022
  }
744
1023
  catch (error) {
745
1024
  await transport.close();
1025
+ firstAttemptError = error;
746
1026
  throw error;
747
1027
  }
748
1028
  }
749
- catch (error) {
1029
+ catch (initialError) {
1030
+ let error = initialError;
1031
+ // Check if this is a 401 error FIRST (before attempting SSE fallback)
1032
+ // This ensures OAuth flow happens before we try SSE
1033
+ if (isAuthenticationError(error) && hasNetworkTransport(mcpServerConfig)) {
1034
+ // Continue to OAuth handling below (after SSE fallback section)
1035
+ }
1036
+ else if (
1037
+ // If not 401, and HTTP failed with url without explicit type, try SSE fallback
1038
+ firstAttemptError &&
1039
+ mcpServerConfig.url &&
1040
+ !mcpServerConfig.type &&
1041
+ !mcpServerConfig.httpUrl) {
1042
+ // Check if HTTP returned 404 - if so, we know it's not an HTTP server
1043
+ httpReturned404 = String(firstAttemptError).includes('404');
1044
+ const logMessage = httpReturned404
1045
+ ? `HTTP returned 404, trying SSE transport...`
1046
+ : `HTTP connection failed, attempting SSE fallback...`;
1047
+ debugLogger.log(`MCP server '${mcpServerName}': ${logMessage}`);
1048
+ try {
1049
+ // Try SSE with stored OAuth token if available
1050
+ // This ensures that SSE fallback works for authenticated servers
1051
+ await connectWithSSETransport(mcpClient, mcpServerConfig, await getStoredOAuthToken(mcpServerName));
1052
+ debugLogger.log(`MCP server '${mcpServerName}': Successfully connected using SSE transport.`);
1053
+ return mcpClient;
1054
+ }
1055
+ catch (sseFallbackError) {
1056
+ sseError = sseFallbackError;
1057
+ // If SSE also returned 401, handle OAuth below
1058
+ if (isAuthenticationError(sseError)) {
1059
+ debugLogger.log(`MCP server '${mcpServerName}': SSE returned 401, OAuth authentication required.`);
1060
+ // Update error to be the SSE error for OAuth handling
1061
+ error = sseError;
1062
+ // Continue to OAuth handling below
1063
+ }
1064
+ else {
1065
+ debugLogger.log(`MCP server '${mcpServerName}': SSE fallback also failed.`);
1066
+ // Both failed without 401, throw the original error
1067
+ throw firstAttemptError;
1068
+ }
1069
+ }
1070
+ }
750
1071
  // Check if this is a 401 error that might indicate OAuth is required
751
- const errorString = String(error);
752
- if (errorString.includes('401') && hasNetworkTransport(mcpServerConfig)) {
1072
+ if (isAuthenticationError(error) && hasNetworkTransport(mcpServerConfig)) {
753
1073
  mcpServerRequiresOAuth.set(mcpServerName, true);
754
- // Only trigger automatic OAuth discovery for HTTP servers or when OAuth is explicitly configured
755
- // For SSE servers, we should not trigger new OAuth flows automatically
756
- const shouldTriggerOAuth = mcpServerConfig.httpUrl || mcpServerConfig.oauth?.enabled;
1074
+ // Only trigger automatic OAuth if explicitly enabled in config
1075
+ // Otherwise, show error and tell user to run /mcp auth command
1076
+ const shouldTriggerOAuth = mcpServerConfig.oauth?.enabled;
757
1077
  if (!shouldTriggerOAuth) {
758
- // For SSE servers without explicit OAuth config, if a token was found but rejected, report it accurately.
759
- const tokenStorage = new MCPOAuthTokenStorage();
760
- const credentials = await tokenStorage.getCredentials(mcpServerName);
761
- if (credentials) {
762
- const authProvider = new MCPOAuthProvider(tokenStorage);
763
- const hasStoredTokens = await authProvider.getValidToken(mcpServerName, {
764
- // Pass client ID if available
765
- clientId: credentials.clientId,
766
- });
767
- if (hasStoredTokens) {
768
- coreEvents.emitFeedback('error', `Stored OAuth token for SSE server '${mcpServerName}' was rejected. ` +
769
- `Please re-authenticate using: /mcp auth ${mcpServerName}`);
770
- }
771
- else {
772
- coreEvents.emitFeedback('error', `401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
773
- `Please authenticate using: /mcp auth ${mcpServerName}`);
774
- }
775
- }
776
- throw new Error(`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
777
- `Please authenticate using: /mcp auth ${mcpServerName}`);
1078
+ await showAuthRequiredMessage(mcpServerName);
778
1079
  }
779
1080
  // Try to extract www-authenticate header from the error
1081
+ const errorString = String(error);
780
1082
  let wwwAuthenticate = extractWWWAuthenticateHeader(errorString);
781
1083
  // If we didn't get the header from the error string, try to get it from the server
782
1084
  if (!wwwAuthenticate && hasNetworkTransport(mcpServerConfig)) {
783
1085
  debugLogger.log(`No www-authenticate header in error, trying to fetch it from server...`);
784
1086
  try {
785
1087
  const urlToFetch = mcpServerConfig.httpUrl || mcpServerConfig.url;
1088
+ // Determine correct Accept header based on what transport failed
1089
+ let acceptHeader;
1090
+ if (mcpServerConfig.httpUrl) {
1091
+ acceptHeader = 'application/json';
1092
+ }
1093
+ else if (mcpServerConfig.type === 'http') {
1094
+ acceptHeader = 'application/json';
1095
+ }
1096
+ else if (mcpServerConfig.type === 'sse') {
1097
+ acceptHeader = 'text/event-stream';
1098
+ }
1099
+ else if (httpReturned404) {
1100
+ // HTTP failed with 404, SSE returned 401 - use SSE header
1101
+ acceptHeader = 'text/event-stream';
1102
+ }
1103
+ else {
1104
+ // HTTP returned 401 - use HTTP header
1105
+ acceptHeader = 'application/json';
1106
+ }
786
1107
  const response = await fetch(urlToFetch, {
787
1108
  method: 'HEAD',
788
1109
  headers: {
789
- Accept: mcpServerConfig.httpUrl
790
- ? 'application/json'
791
- : 'text/event-stream',
1110
+ Accept: acceptHeader,
792
1111
  },
793
1112
  signal: AbortSignal.timeout(5000),
794
1113
  });
@@ -809,38 +1128,12 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
809
1128
  const oauthSuccess = await handleAutomaticOAuth(mcpServerName, mcpServerConfig, wwwAuthenticate);
810
1129
  if (oauthSuccess) {
811
1130
  // Retry connection with OAuth token
812
- debugLogger.log(`Retrying connection to '${mcpServerName}' with OAuth token...`);
813
- // Get the valid token - we need to create a proper OAuth config
814
- // The token should already be available from the authentication process
815
- const tokenStorage = new MCPOAuthTokenStorage();
816
- const credentials = await tokenStorage.getCredentials(mcpServerName);
817
- if (credentials) {
818
- const authProvider = new MCPOAuthProvider(tokenStorage);
819
- const accessToken = await authProvider.getValidToken(mcpServerName, {
820
- // Pass client ID if available
821
- clientId: credentials.clientId,
822
- });
823
- if (accessToken) {
824
- // Create transport with OAuth token
825
- const oauthTransport = await createTransportWithOAuth(mcpServerName, mcpServerConfig, accessToken);
826
- if (oauthTransport) {
827
- await mcpClient.connect(oauthTransport, {
828
- timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
829
- });
830
- // Connection successful with OAuth
831
- return mcpClient;
832
- }
833
- else {
834
- throw new Error(`Failed to create OAuth transport for server '${mcpServerName}'`);
835
- }
836
- }
837
- else {
838
- throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
839
- }
840
- }
841
- else {
842
- throw new Error(`Failed to get credentials for server '${mcpServerName}' after successful OAuth authentication`);
1131
+ const accessToken = await getStoredOAuthToken(mcpServerName);
1132
+ if (!accessToken) {
1133
+ throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
843
1134
  }
1135
+ await retryWithOAuth(mcpClient, mcpServerName, mcpServerConfig, accessToken, httpReturned404);
1136
+ return mcpClient;
844
1137
  }
845
1138
  else {
846
1139
  throw new Error(`Failed to handle automatic OAuth for server '${mcpServerName}'`);
@@ -848,29 +1141,10 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
848
1141
  }
849
1142
  else {
850
1143
  // No www-authenticate header found, but we got a 401
851
- // Only try OAuth discovery for HTTP servers or when OAuth is explicitly configured
852
- // For SSE servers, we should not trigger new OAuth flows automatically
853
- const shouldTryDiscovery = mcpServerConfig.httpUrl || mcpServerConfig.oauth?.enabled;
1144
+ // Only try OAuth discovery when OAuth is explicitly enabled in config
1145
+ const shouldTryDiscovery = mcpServerConfig.oauth?.enabled;
854
1146
  if (!shouldTryDiscovery) {
855
- const tokenStorage = new MCPOAuthTokenStorage();
856
- const credentials = await tokenStorage.getCredentials(mcpServerName);
857
- if (credentials) {
858
- const authProvider = new MCPOAuthProvider(tokenStorage);
859
- const hasStoredTokens = await authProvider.getValidToken(mcpServerName, {
860
- // Pass client ID if available
861
- clientId: credentials.clientId,
862
- });
863
- if (hasStoredTokens) {
864
- coreEvents.emitFeedback('error', `Stored OAuth token for SSE server '${mcpServerName}' was rejected. ` +
865
- `Please re-authenticate using: /mcp auth ${mcpServerName}`);
866
- }
867
- else {
868
- coreEvents.emitFeedback('error', `401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
869
- `Please authenticate using: /mcp auth ${mcpServerName}`);
870
- }
871
- }
872
- throw new Error(`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
873
- `Please authenticate using: /mcp auth ${mcpServerName}`);
1147
+ await showAuthRequiredMessage(mcpServerName);
874
1148
  }
875
1149
  // For SSE/HTTP servers, try to discover OAuth configuration from the base URL
876
1150
  debugLogger.log(`🔍 Attempting OAuth discovery for '${mcpServerName}'...`);
@@ -895,35 +1169,20 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
895
1169
  const authProvider = new MCPOAuthProvider(new MCPOAuthTokenStorage());
896
1170
  await authProvider.authenticate(mcpServerName, oauthAuthConfig, authServerUrl);
897
1171
  // Retry connection with OAuth token
898
- const tokenStorage = new MCPOAuthTokenStorage();
899
- const credentials = await tokenStorage.getCredentials(mcpServerName);
900
- if (credentials) {
901
- const authProvider = new MCPOAuthProvider(tokenStorage);
902
- const accessToken = await authProvider.getValidToken(mcpServerName, {
903
- // Pass client ID if available
904
- clientId: credentials.clientId,
905
- });
906
- if (accessToken) {
907
- // Create transport with OAuth token
908
- const oauthTransport = await createTransportWithOAuth(mcpServerName, mcpServerConfig, accessToken);
909
- if (oauthTransport) {
910
- await mcpClient.connect(oauthTransport, {
911
- timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
912
- });
913
- // Connection successful with OAuth
914
- return mcpClient;
915
- }
916
- else {
917
- throw new Error(`Failed to create OAuth transport for server '${mcpServerName}'`);
918
- }
919
- }
920
- else {
921
- throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
922
- }
1172
+ const accessToken = await getStoredOAuthToken(mcpServerName);
1173
+ if (!accessToken) {
1174
+ throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
923
1175
  }
924
- else {
925
- throw new Error(`Failed to get stored credentials for server '${mcpServerName}'`);
1176
+ // Create transport with OAuth token
1177
+ const oauthTransport = await createTransportWithOAuth(mcpServerName, mcpServerConfig, accessToken);
1178
+ if (!oauthTransport) {
1179
+ throw new Error(`Failed to create OAuth transport for server '${mcpServerName}'`);
926
1180
  }
1181
+ await mcpClient.connect(oauthTransport, {
1182
+ timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
1183
+ });
1184
+ // Connection successful with OAuth
1185
+ return mcpClient;
927
1186
  }
928
1187
  else {
929
1188
  throw new Error(`OAuth configuration failed for '${mcpServerName}'. Please authenticate manually with /mcp auth ${mcpServerName}`);
@@ -936,24 +1195,39 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
936
1195
  }
937
1196
  else {
938
1197
  // Handle other connection errors
939
- // Create a concise error message
940
- const errorMessage = error.message || String(error);
941
- const isNetworkError = errorMessage.includes('ENOTFOUND') ||
942
- errorMessage.includes('ECONNREFUSED');
943
- let conciseError;
944
- if (isNetworkError) {
945
- conciseError = `Cannot connect to '${mcpServerName}' - server may be down or URL incorrect`;
946
- }
947
- else {
948
- conciseError = `Connection failed for '${mcpServerName}': ${errorMessage}`;
949
- }
950
- if (process.env['SANDBOX']) {
951
- conciseError += ` (check sandbox availability)`;
952
- }
953
- throw new Error(conciseError);
1198
+ // Re-throw the original error to preserve its structure
1199
+ throw error;
954
1200
  }
955
1201
  }
956
1202
  }
1203
+ /**
1204
+ * Helper function to create the appropriate transport based on config
1205
+ * This handles the logic for httpUrl/url/type consistently
1206
+ */
1207
+ function createUrlTransport(mcpServerName, mcpServerConfig, transportOptions) {
1208
+ // Priority 1: httpUrl (deprecated)
1209
+ if (mcpServerConfig.httpUrl) {
1210
+ if (mcpServerConfig.url) {
1211
+ debugLogger.warn(`MCP server '${mcpServerName}': Both 'httpUrl' and 'url' are configured. ` +
1212
+ `Using deprecated 'httpUrl'. Please migrate to 'url' with 'type: "http"'.`);
1213
+ }
1214
+ return new StreamableHTTPClientTransport(new URL(mcpServerConfig.httpUrl), transportOptions);
1215
+ }
1216
+ // Priority 2 & 3: url with explicit type
1217
+ if (mcpServerConfig.url && mcpServerConfig.type) {
1218
+ if (mcpServerConfig.type === 'http') {
1219
+ return new StreamableHTTPClientTransport(new URL(mcpServerConfig.url), transportOptions);
1220
+ }
1221
+ else if (mcpServerConfig.type === 'sse') {
1222
+ return new SSEClientTransport(new URL(mcpServerConfig.url), transportOptions);
1223
+ }
1224
+ }
1225
+ // Priority 4: url without type (default to HTTP)
1226
+ if (mcpServerConfig.url) {
1227
+ return new StreamableHTTPClientTransport(new URL(mcpServerConfig.url), transportOptions);
1228
+ }
1229
+ throw new Error(`No URL configured for MCP server '${mcpServerName}'`);
1230
+ }
957
1231
  /** Visible for Testing */
958
1232
  export async function createTransport(mcpServerName, mcpServerConfig, debugMode) {
959
1233
  const noUrl = !mcpServerConfig.url && !mcpServerConfig.httpUrl;
@@ -970,35 +1244,26 @@ export async function createTransport(mcpServerName, mcpServerConfig, debugMode)
970
1244
  const authProvider = createAuthProvider(mcpServerConfig);
971
1245
  const headers = (await authProvider?.getRequestHeaders?.()) ?? {};
972
1246
  let accessToken = null;
973
- let hasOAuthConfig = mcpServerConfig.oauth?.enabled;
1247
+ const hasOAuthConfig = mcpServerConfig.oauth?.enabled;
974
1248
  if (authProvider === undefined) {
975
1249
  // Check if we have OAuth configuration or stored tokens
976
- if (hasOAuthConfig && mcpServerConfig.oauth) {
1250
+ if (mcpServerConfig.oauth?.enabled && mcpServerConfig.oauth) {
977
1251
  const tokenStorage = new MCPOAuthTokenStorage();
978
1252
  const mcpAuthProvider = new MCPOAuthProvider(tokenStorage);
979
1253
  accessToken = await mcpAuthProvider.getValidToken(mcpServerName, mcpServerConfig.oauth);
980
1254
  if (!accessToken) {
981
- throw new Error(`MCP server '${mcpServerName}' requires OAuth authentication. ` +
982
- `Please authenticate using the /mcp auth command.`);
1255
+ // Emit info message (not error) since this is expected behavior
1256
+ coreEvents.emitFeedback('info', `MCP server '${mcpServerName}' requires authentication using: /mcp auth ${mcpServerName}`);
983
1257
  }
984
1258
  }
985
1259
  else {
986
1260
  // Check if we have stored OAuth tokens for this server (from previous authentication)
987
- const tokenStorage = new MCPOAuthTokenStorage();
988
- const credentials = await tokenStorage.getCredentials(mcpServerName);
989
- if (credentials) {
990
- const mcpAuthProvider = new MCPOAuthProvider(tokenStorage);
991
- accessToken = await mcpAuthProvider.getValidToken(mcpServerName, {
992
- // Pass client ID if available
993
- clientId: credentials.clientId,
994
- });
995
- if (accessToken) {
996
- hasOAuthConfig = true;
997
- debugLogger.log(`Found stored OAuth token for server '${mcpServerName}'`);
998
- }
1261
+ accessToken = await getStoredOAuthToken(mcpServerName);
1262
+ if (accessToken) {
1263
+ debugLogger.log(`Found stored OAuth token for server '${mcpServerName}'`);
999
1264
  }
1000
1265
  }
1001
- if (hasOAuthConfig && accessToken) {
1266
+ if (accessToken) {
1002
1267
  headers['Authorization'] = `Bearer ${accessToken}`;
1003
1268
  }
1004
1269
  }
@@ -1016,7 +1281,7 @@ export async function createTransport(mcpServerName, mcpServerConfig, debugMode)
1016
1281
  };
1017
1282
  }
1018
1283
  await applyAgentAuthHeaderIfNeeded(mcpServerConfig, transportOptions);
1019
- return createUrlTransport(mcpServerConfig, transportOptions);
1284
+ return createUrlTransport(mcpServerName, mcpServerConfig, transportOptions);
1020
1285
  }
1021
1286
  if (mcpServerConfig.command) {
1022
1287
  const transport = new StdioClientTransport({