@xagent-ai/cli 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (568) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  3. package/.github/workflows/ci.yml +72 -0
  4. package/.github/workflows/release.yml +109 -0
  5. package/.gitmodules +3 -3
  6. package/README.md +326 -280
  7. package/README_CN.md +325 -279
  8. package/dist/ai-client/factory.d.ts +52 -0
  9. package/dist/ai-client/factory.d.ts.map +1 -0
  10. package/dist/ai-client/factory.js +132 -0
  11. package/dist/ai-client/factory.js.map +1 -0
  12. package/dist/ai-client/index.d.ts +20 -0
  13. package/dist/ai-client/index.d.ts.map +1 -0
  14. package/dist/ai-client/index.js +49 -0
  15. package/dist/ai-client/index.js.map +1 -0
  16. package/dist/ai-client/providers/anthropic.d.ts +57 -0
  17. package/dist/ai-client/providers/anthropic.d.ts.map +1 -0
  18. package/dist/ai-client/providers/anthropic.js +400 -0
  19. package/dist/ai-client/providers/anthropic.js.map +1 -0
  20. package/dist/ai-client/providers/openai.d.ts +57 -0
  21. package/dist/ai-client/providers/openai.d.ts.map +1 -0
  22. package/dist/ai-client/providers/openai.js +286 -0
  23. package/dist/ai-client/providers/openai.js.map +1 -0
  24. package/dist/ai-client/providers/remote.d.ts +111 -0
  25. package/dist/ai-client/providers/remote.d.ts.map +1 -0
  26. package/dist/ai-client/providers/remote.js +351 -0
  27. package/dist/ai-client/providers/remote.js.map +1 -0
  28. package/dist/ai-client/registry.d.ts +51 -0
  29. package/dist/ai-client/registry.d.ts.map +1 -0
  30. package/dist/ai-client/registry.js +81 -0
  31. package/dist/ai-client/registry.js.map +1 -0
  32. package/dist/ai-client/types.d.ts +260 -0
  33. package/dist/ai-client/types.d.ts.map +1 -0
  34. package/dist/ai-client/types.js +73 -0
  35. package/dist/ai-client/types.js.map +1 -0
  36. package/dist/ai-client-factory.d.ts +62 -0
  37. package/dist/ai-client-factory.d.ts.map +1 -0
  38. package/dist/ai-client-factory.js +157 -0
  39. package/dist/ai-client-factory.js.map +1 -0
  40. package/dist/auth.d.ts +23 -1
  41. package/dist/auth.d.ts.map +1 -1
  42. package/dist/auth.js +160 -168
  43. package/dist/auth.js.map +1 -1
  44. package/dist/cancellation.d.ts +5 -4
  45. package/dist/cancellation.d.ts.map +1 -1
  46. package/dist/cancellation.js +55 -32
  47. package/dist/cancellation.js.map +1 -1
  48. package/dist/checkpoint.d.ts +1 -1
  49. package/dist/checkpoint.d.ts.map +1 -1
  50. package/dist/checkpoint.js +2 -2
  51. package/dist/checkpoint.js.map +1 -1
  52. package/dist/cli.js +626 -13
  53. package/dist/cli.js.map +1 -1
  54. package/dist/config.d.ts +10 -4
  55. package/dist/config.d.ts.map +1 -1
  56. package/dist/config.js +62 -25
  57. package/dist/config.js.map +1 -1
  58. package/dist/context-compressor.d.ts +81 -16
  59. package/dist/context-compressor.d.ts.map +1 -1
  60. package/dist/context-compressor.js +712 -153
  61. package/dist/context-compressor.js.map +1 -1
  62. package/dist/gui-subagent/action-parser/actionParser.d.ts.map +1 -1
  63. package/dist/gui-subagent/action-parser/actionParser.js +4 -2
  64. package/dist/gui-subagent/action-parser/actionParser.js.map +1 -1
  65. package/dist/gui-subagent/agent/gui-agent.d.ts +29 -2
  66. package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -1
  67. package/dist/gui-subagent/agent/gui-agent.js +87 -45
  68. package/dist/gui-subagent/agent/gui-agent.js.map +1 -1
  69. package/dist/gui-subagent/index.d.ts +16 -1
  70. package/dist/gui-subagent/index.d.ts.map +1 -1
  71. package/dist/gui-subagent/index.js +4 -0
  72. package/dist/gui-subagent/index.js.map +1 -1
  73. package/dist/gui-subagent/operator/base-operator.d.ts.map +1 -1
  74. package/dist/gui-subagent/operator/base-operator.js +0 -1
  75. package/dist/gui-subagent/operator/base-operator.js.map +1 -1
  76. package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -1
  77. package/dist/gui-subagent/operator/computer-operator.js +29 -8
  78. package/dist/gui-subagent/operator/computer-operator.js.map +1 -1
  79. package/dist/gui-subagent/types/actions.d.ts +1 -1
  80. package/dist/gui-subagent/types/actions.d.ts.map +1 -1
  81. package/dist/gui-subagent/types/actions.js +0 -1
  82. package/dist/gui-subagent/types/actions.js.map +1 -1
  83. package/dist/gui-subagent/types/operator.d.ts +1 -1
  84. package/dist/gui-subagent/types/operator.d.ts.map +1 -1
  85. package/dist/index.d.ts +1 -2
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +1 -2
  88. package/dist/index.js.map +1 -1
  89. package/dist/input-processor.d.ts.map +1 -1
  90. package/dist/input-processor.js +6 -3
  91. package/dist/input-processor.js.map +1 -1
  92. package/dist/mcp.d.ts +5 -0
  93. package/dist/mcp.d.ts.map +1 -1
  94. package/dist/mcp.js +81 -35
  95. package/dist/mcp.js.map +1 -1
  96. package/dist/ripgrep.d.ts +29 -0
  97. package/dist/ripgrep.d.ts.map +1 -0
  98. package/dist/ripgrep.js +292 -0
  99. package/dist/ripgrep.js.map +1 -0
  100. package/dist/session.d.ts +23 -7
  101. package/dist/session.d.ts.map +1 -1
  102. package/dist/session.js +624 -243
  103. package/dist/session.js.map +1 -1
  104. package/dist/shell.d.ts +33 -0
  105. package/dist/shell.d.ts.map +1 -0
  106. package/dist/shell.js +125 -0
  107. package/dist/shell.js.map +1 -0
  108. package/dist/skill-installer.d.ts +38 -0
  109. package/dist/skill-installer.d.ts.map +1 -0
  110. package/dist/skill-installer.js +447 -0
  111. package/dist/skill-installer.js.map +1 -0
  112. package/dist/skill-invoker.d.ts +7 -1
  113. package/dist/skill-invoker.d.ts.map +1 -1
  114. package/dist/skill-invoker.js +34 -13
  115. package/dist/skill-invoker.js.map +1 -1
  116. package/dist/skill-loader.d.ts +8 -3
  117. package/dist/skill-loader.d.ts.map +1 -1
  118. package/dist/skill-loader.js +46 -44
  119. package/dist/skill-loader.js.map +1 -1
  120. package/dist/skill-manager.d.ts +85 -0
  121. package/dist/skill-manager.d.ts.map +1 -0
  122. package/dist/skill-manager.js +340 -0
  123. package/dist/skill-manager.js.map +1 -0
  124. package/dist/slash-commands.d.ts +38 -1
  125. package/dist/slash-commands.d.ts.map +1 -1
  126. package/dist/slash-commands.js +912 -296
  127. package/dist/slash-commands.js.map +1 -1
  128. package/dist/smart-approval.d.ts.map +1 -1
  129. package/dist/smart-approval.js +67 -55
  130. package/dist/smart-approval.js.map +1 -1
  131. package/dist/system-prompt-generator.d.ts +6 -0
  132. package/dist/system-prompt-generator.d.ts.map +1 -1
  133. package/dist/system-prompt-generator.js +84 -34
  134. package/dist/system-prompt-generator.js.map +1 -1
  135. package/dist/terminal.d.ts +28 -0
  136. package/dist/terminal.d.ts.map +1 -0
  137. package/dist/terminal.js +82 -0
  138. package/dist/terminal.js.map +1 -0
  139. package/dist/tools.d.ts +23 -7
  140. package/dist/tools.d.ts.map +1 -1
  141. package/dist/tools.js +797 -437
  142. package/dist/tools.js.map +1 -1
  143. package/dist/truncate.d.ts +55 -0
  144. package/dist/truncate.d.ts.map +1 -0
  145. package/dist/truncate.js +130 -0
  146. package/dist/truncate.js.map +1 -0
  147. package/dist/types.d.ts +27 -9
  148. package/dist/types.d.ts.map +1 -1
  149. package/dist/update.d.ts.map +1 -1
  150. package/dist/update.js +17 -28
  151. package/dist/update.js.map +1 -1
  152. package/dist/workflow.d.ts +5 -1
  153. package/dist/workflow.d.ts.map +1 -1
  154. package/dist/workflow.js +60 -47
  155. package/dist/workflow.js.map +1 -1
  156. package/docs/architecture/mcp-integration-guide.md +304 -194
  157. package/docs/architecture/overview.md +169 -169
  158. package/docs/architecture/tool-system-design.md +134 -134
  159. package/docs/cli/commands.md +349 -238
  160. package/docs/smart-mode.md +281 -281
  161. package/docs/third-party-models.md +439 -439
  162. package/find-skills/SKILL.md +133 -0
  163. package/package.json +89 -90
  164. package/scripts/install-ripgrep.js +241 -0
  165. package/src/ai-client/factory.ts +151 -0
  166. package/src/ai-client/index.ts +61 -0
  167. package/src/ai-client/providers/anthropic.ts +466 -0
  168. package/src/ai-client/providers/openai.ts +342 -0
  169. package/src/ai-client/providers/remote.ts +436 -0
  170. package/src/ai-client/registry.ts +97 -0
  171. package/src/ai-client/types.ts +345 -0
  172. package/src/ai-client-factory.ts +204 -0
  173. package/src/auth.ts +663 -614
  174. package/src/cancellation.ts +205 -176
  175. package/src/checkpoint.ts +219 -219
  176. package/src/cli.ts +1406 -743
  177. package/src/config.ts +341 -297
  178. package/src/context-compressor.ts +982 -290
  179. package/src/conversation.ts +288 -288
  180. package/src/gui-subagent/action-parser/actionParser.ts +318 -315
  181. package/src/gui-subagent/action-parser/constants.ts +14 -14
  182. package/src/gui-subagent/action-parser/index.ts +8 -8
  183. package/src/gui-subagent/action-parser/types.ts +31 -31
  184. package/src/gui-subagent/agent/gui-agent.ts +1151 -1089
  185. package/src/gui-subagent/agent/index.ts +5 -5
  186. package/src/gui-subagent/index.ts +177 -163
  187. package/src/gui-subagent/operator/base-operator.ts +244 -245
  188. package/src/gui-subagent/operator/computer-operator.ts +540 -520
  189. package/src/gui-subagent/operator/index.ts +6 -6
  190. package/src/gui-subagent/types/actions.ts +260 -262
  191. package/src/gui-subagent/types/index.ts +6 -6
  192. package/src/gui-subagent/types/operator.ts +106 -106
  193. package/src/gui-subagent/utils.ts +51 -51
  194. package/src/index.ts +17 -18
  195. package/src/input-processor.ts +6 -3
  196. package/src/logger.ts +438 -438
  197. package/src/mcp.ts +730 -682
  198. package/src/memory.ts +344 -344
  199. package/src/ripgrep.ts +368 -0
  200. package/src/session-manager.ts +308 -308
  201. package/src/session.ts +948 -386
  202. package/src/shell.ts +133 -0
  203. package/src/skill-installer.ts +518 -0
  204. package/src/skill-invoker.ts +960 -935
  205. package/src/skill-loader.ts +501 -496
  206. package/src/skill-manager.ts +384 -0
  207. package/src/slash-commands.ts +2181 -1389
  208. package/src/smart-approval.ts +117 -73
  209. package/src/system-prompt-generator.ts +89 -34
  210. package/src/terminal.ts +96 -0
  211. package/src/theme.ts +738 -738
  212. package/src/tools.ts +1336 -773
  213. package/src/truncate.ts +173 -0
  214. package/src/types.ts +219 -198
  215. package/src/update.ts +22 -32
  216. package/src/workflow.ts +523 -508
  217. package/tsconfig.json +22 -22
  218. package/vitest.config.ts +19 -19
  219. package/dist/ai-client.d.ts +0 -86
  220. package/dist/ai-client.d.ts.map +0 -1
  221. package/dist/ai-client.js +0 -1372
  222. package/dist/ai-client.js.map +0 -1
  223. package/dist/gui-subagent/operator/browser-operator.d.ts +0 -36
  224. package/dist/gui-subagent/operator/browser-operator.d.ts.map +0 -1
  225. package/dist/gui-subagent/operator/browser-operator.js +0 -306
  226. package/dist/gui-subagent/operator/browser-operator.js.map +0 -1
  227. package/dist/gui-subagent/operator/desktop-operator.d.ts +0 -55
  228. package/dist/gui-subagent/operator/desktop-operator.d.ts.map +0 -1
  229. package/dist/gui-subagent/operator/desktop-operator.js +0 -527
  230. package/dist/gui-subagent/operator/desktop-operator.js.map +0 -1
  231. package/dist/hook.d.ts +0 -73
  232. package/dist/hook.d.ts.map +0 -1
  233. package/dist/hook.js +0 -156
  234. package/dist/hook.js.map +0 -1
  235. package/dist/input-history.d.ts +0 -24
  236. package/dist/input-history.d.ts.map +0 -1
  237. package/dist/input-history.js +0 -94
  238. package/dist/input-history.js.map +0 -1
  239. package/dist/keyboard-manager.d.ts +0 -151
  240. package/dist/keyboard-manager.d.ts.map +0 -1
  241. package/dist/keyboard-manager.js +0 -396
  242. package/dist/keyboard-manager.js.map +0 -1
  243. package/dist/print-system-prompt.d.ts +0 -2
  244. package/dist/print-system-prompt.d.ts.map +0 -1
  245. package/dist/print-system-prompt.js +0 -40
  246. package/dist/print-system-prompt.js.map +0 -1
  247. package/dist/remote-ai-client.d.ts +0 -104
  248. package/dist/remote-ai-client.d.ts.map +0 -1
  249. package/dist/remote-ai-client.js +0 -552
  250. package/dist/remote-ai-client.js.map +0 -1
  251. package/dist/sdk-output-adapter.d.ts +0 -232
  252. package/dist/sdk-output-adapter.d.ts.map +0 -1
  253. package/dist/sdk-output-adapter.js +0 -636
  254. package/dist/sdk-output-adapter.js.map +0 -1
  255. package/dist/sdk-session-v2.d.ts +0 -13
  256. package/dist/sdk-session-v2.d.ts.map +0 -1
  257. package/dist/sdk-session-v2.js +0 -46
  258. package/dist/sdk-session-v2.js.map +0 -1
  259. package/dist/sdk-session.d.ts +0 -13
  260. package/dist/sdk-session.d.ts.map +0 -1
  261. package/dist/sdk-session.js +0 -48
  262. package/dist/sdk-session.js.map +0 -1
  263. package/dist/test-boundary-conditions.d.ts.map +0 -1
  264. package/dist/test-boundary-conditions.js.map +0 -1
  265. package/dist/test-cancellation-fix.d.ts.map +0 -1
  266. package/dist/test-cancellation-fix.js.map +0 -1
  267. package/dist/test-input-history.d.ts.map +0 -1
  268. package/dist/test-input-history.js.map +0 -1
  269. package/dist/test-interaction-flow.d.ts.map +0 -1
  270. package/dist/test-interaction-flow.js.map +0 -1
  271. package/dist/test-quick.d.ts.map +0 -1
  272. package/dist/test-quick.js.map +0 -1
  273. package/dist/test-user-interaction.d.ts.map +0 -1
  274. package/dist/test-user-interaction.js.map +0 -1
  275. package/dist/tools/edit-diff.d.ts +0 -32
  276. package/dist/tools/edit-diff.d.ts.map +0 -1
  277. package/dist/tools/edit-diff.js +0 -185
  278. package/dist/tools/edit-diff.js.map +0 -1
  279. package/dist/tools/edit.d.ts +0 -11
  280. package/dist/tools/edit.d.ts.map +0 -1
  281. package/dist/tools/edit.js +0 -129
  282. package/dist/tools/edit.js.map +0 -1
  283. package/dist/unified-session.d.ts +0 -42
  284. package/dist/unified-session.d.ts.map +0 -1
  285. package/dist/unified-session.js +0 -271
  286. package/dist/unified-session.js.map +0 -1
  287. package/skills/.claude-plugin/marketplace.json +0 -45
  288. package/skills/README.md +0 -94
  289. package/skills/THIRD_PARTY_NOTICES.md +0 -405
  290. package/skills/skills/algorithmic-art/LICENSE.txt +0 -202
  291. package/skills/skills/algorithmic-art/SKILL.md +0 -405
  292. package/skills/skills/algorithmic-art/templates/generator_template.js +0 -223
  293. package/skills/skills/algorithmic-art/templates/viewer.html +0 -599
  294. package/skills/skills/brand-guidelines/LICENSE.txt +0 -202
  295. package/skills/skills/brand-guidelines/SKILL.md +0 -73
  296. package/skills/skills/canvas-design/LICENSE.txt +0 -202
  297. package/skills/skills/canvas-design/SKILL.md +0 -130
  298. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
  299. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  300. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  301. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
  302. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  303. package/skills/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
  304. package/skills/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  305. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  306. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
  307. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  308. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  309. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  310. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
  311. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  312. package/skills/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
  313. package/skills/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  314. package/skills/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
  315. package/skills/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  316. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  317. package/skills/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
  318. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  319. package/skills/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
  320. package/skills/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  321. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  322. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
  323. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  324. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  325. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  326. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  327. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  328. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  329. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  330. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  331. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
  332. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  333. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  334. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  335. package/skills/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
  336. package/skills/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  337. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  338. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
  339. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  340. package/skills/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  341. package/skills/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  342. package/skills/skills/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
  343. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
  344. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  345. package/skills/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  346. package/skills/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  347. package/skills/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  348. package/skills/skills/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
  349. package/skills/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  350. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  351. package/skills/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
  352. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  353. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
  354. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  355. package/skills/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  356. package/skills/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
  357. package/skills/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  358. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  359. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
  360. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
  361. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  362. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  363. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
  364. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  365. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
  366. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  367. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  368. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
  369. package/skills/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  370. package/skills/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
  371. package/skills/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  372. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  373. package/skills/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  374. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  375. package/skills/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
  376. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  377. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
  378. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  379. package/skills/skills/doc-coauthoring/SKILL.md +0 -375
  380. package/skills/skills/docx/LICENSE.txt +0 -30
  381. package/skills/skills/docx/SKILL.md +0 -197
  382. package/skills/skills/docx/docx-js.md +0 -350
  383. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  384. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  385. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  386. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  387. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  388. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  389. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  390. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  391. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  392. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  393. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  394. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  395. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  396. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  397. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  398. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  399. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  400. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  401. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  402. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  403. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  404. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  405. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  406. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  407. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  408. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  409. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  410. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  411. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  412. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  413. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  414. package/skills/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
  415. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  416. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  417. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  418. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  419. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  420. package/skills/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  421. package/skills/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  422. package/skills/skills/docx/ooxml/scripts/pack.py +0 -159
  423. package/skills/skills/docx/ooxml/scripts/unpack.py +0 -29
  424. package/skills/skills/docx/ooxml/scripts/validate.py +0 -69
  425. package/skills/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
  426. package/skills/skills/docx/ooxml/scripts/validation/base.py +0 -951
  427. package/skills/skills/docx/ooxml/scripts/validation/docx.py +0 -274
  428. package/skills/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
  429. package/skills/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
  430. package/skills/skills/docx/ooxml.md +0 -610
  431. package/skills/skills/docx/scripts/__init__.py +0 -1
  432. package/skills/skills/docx/scripts/document.py +0 -1276
  433. package/skills/skills/docx/scripts/templates/comments.xml +0 -3
  434. package/skills/skills/docx/scripts/templates/commentsExtended.xml +0 -3
  435. package/skills/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
  436. package/skills/skills/docx/scripts/templates/commentsIds.xml +0 -3
  437. package/skills/skills/docx/scripts/templates/people.xml +0 -3
  438. package/skills/skills/docx/scripts/utilities.py +0 -374
  439. package/skills/skills/frontend-design/LICENSE.txt +0 -177
  440. package/skills/skills/frontend-design/SKILL.md +0 -42
  441. package/skills/skills/internal-comms/LICENSE.txt +0 -202
  442. package/skills/skills/internal-comms/SKILL.md +0 -32
  443. package/skills/skills/internal-comms/examples/3p-updates.md +0 -47
  444. package/skills/skills/internal-comms/examples/company-newsletter.md +0 -65
  445. package/skills/skills/internal-comms/examples/faq-answers.md +0 -30
  446. package/skills/skills/internal-comms/examples/general-comms.md +0 -16
  447. package/skills/skills/mcp-builder/LICENSE.txt +0 -202
  448. package/skills/skills/mcp-builder/SKILL.md +0 -236
  449. package/skills/skills/mcp-builder/reference/evaluation.md +0 -602
  450. package/skills/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  451. package/skills/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  452. package/skills/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  453. package/skills/skills/mcp-builder/scripts/connections.py +0 -151
  454. package/skills/skills/mcp-builder/scripts/evaluation.py +0 -373
  455. package/skills/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  456. package/skills/skills/mcp-builder/scripts/requirements.txt +0 -2
  457. package/skills/skills/pdf/LICENSE.txt +0 -30
  458. package/skills/skills/pdf/SKILL.md +0 -294
  459. package/skills/skills/pdf/forms.md +0 -205
  460. package/skills/skills/pdf/reference.md +0 -612
  461. package/skills/skills/pdf/scripts/check_bounding_boxes.py +0 -70
  462. package/skills/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
  463. package/skills/skills/pdf/scripts/check_fillable_fields.py +0 -12
  464. package/skills/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
  465. package/skills/skills/pdf/scripts/create_validation_image.py +0 -41
  466. package/skills/skills/pdf/scripts/extract_form_field_info.py +0 -152
  467. package/skills/skills/pdf/scripts/fill_fillable_fields.py +0 -114
  468. package/skills/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
  469. package/skills/skills/pptx/LICENSE.txt +0 -30
  470. package/skills/skills/pptx/SKILL.md +0 -484
  471. package/skills/skills/pptx/html2pptx.md +0 -625
  472. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  473. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  474. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  475. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  476. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  477. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  478. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  479. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  480. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  481. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  482. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  483. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  484. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  485. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  486. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  487. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  488. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  489. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  490. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  491. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  492. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  493. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  494. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  495. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  496. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  497. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  498. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  499. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  500. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  501. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  502. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  503. package/skills/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
  504. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  505. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  506. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  507. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  508. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  509. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  510. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  511. package/skills/skills/pptx/ooxml/scripts/pack.py +0 -159
  512. package/skills/skills/pptx/ooxml/scripts/unpack.py +0 -29
  513. package/skills/skills/pptx/ooxml/scripts/validate.py +0 -69
  514. package/skills/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
  515. package/skills/skills/pptx/ooxml/scripts/validation/base.py +0 -951
  516. package/skills/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
  517. package/skills/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
  518. package/skills/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
  519. package/skills/skills/pptx/ooxml.md +0 -427
  520. package/skills/skills/pptx/scripts/html2pptx.js +0 -979
  521. package/skills/skills/pptx/scripts/inventory.py +0 -1020
  522. package/skills/skills/pptx/scripts/rearrange.py +0 -231
  523. package/skills/skills/pptx/scripts/replace.py +0 -385
  524. package/skills/skills/pptx/scripts/thumbnail.py +0 -450
  525. package/skills/skills/skill-creator/LICENSE.txt +0 -202
  526. package/skills/skills/skill-creator/SKILL.md +0 -356
  527. package/skills/skills/skill-creator/references/output-patterns.md +0 -82
  528. package/skills/skills/skill-creator/references/workflows.md +0 -28
  529. package/skills/skills/skill-creator/scripts/init_skill.py +0 -303
  530. package/skills/skills/skill-creator/scripts/package_skill.py +0 -110
  531. package/skills/skills/skill-creator/scripts/quick_validate.py +0 -95
  532. package/skills/skills/slack-gif-creator/LICENSE.txt +0 -202
  533. package/skills/skills/slack-gif-creator/SKILL.md +0 -254
  534. package/skills/skills/slack-gif-creator/core/easing.py +0 -234
  535. package/skills/skills/slack-gif-creator/core/frame_composer.py +0 -176
  536. package/skills/skills/slack-gif-creator/core/gif_builder.py +0 -269
  537. package/skills/skills/slack-gif-creator/core/validators.py +0 -136
  538. package/skills/skills/slack-gif-creator/requirements.txt +0 -4
  539. package/skills/skills/theme-factory/LICENSE.txt +0 -202
  540. package/skills/skills/theme-factory/SKILL.md +0 -59
  541. package/skills/skills/theme-factory/theme-showcase.pdf +0 -0
  542. package/skills/skills/theme-factory/themes/arctic-frost.md +0 -19
  543. package/skills/skills/theme-factory/themes/botanical-garden.md +0 -19
  544. package/skills/skills/theme-factory/themes/desert-rose.md +0 -19
  545. package/skills/skills/theme-factory/themes/forest-canopy.md +0 -19
  546. package/skills/skills/theme-factory/themes/golden-hour.md +0 -19
  547. package/skills/skills/theme-factory/themes/midnight-galaxy.md +0 -19
  548. package/skills/skills/theme-factory/themes/modern-minimalist.md +0 -19
  549. package/skills/skills/theme-factory/themes/ocean-depths.md +0 -19
  550. package/skills/skills/theme-factory/themes/sunset-boulevard.md +0 -19
  551. package/skills/skills/theme-factory/themes/tech-innovation.md +0 -19
  552. package/skills/skills/web-artifacts-builder/LICENSE.txt +0 -202
  553. package/skills/skills/web-artifacts-builder/SKILL.md +0 -74
  554. package/skills/skills/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
  555. package/skills/skills/web-artifacts-builder/scripts/init-artifact.sh +0 -322
  556. package/skills/skills/webapp-testing/LICENSE.txt +0 -202
  557. package/skills/skills/webapp-testing/SKILL.md +0 -96
  558. package/skills/skills/webapp-testing/examples/console_logging.py +0 -35
  559. package/skills/skills/webapp-testing/examples/element_discovery.py +0 -40
  560. package/skills/skills/webapp-testing/examples/static_html_automation.py +0 -33
  561. package/skills/skills/webapp-testing/scripts/with_server.py +0 -106
  562. package/skills/skills/xlsx/LICENSE.txt +0 -30
  563. package/skills/skills/xlsx/SKILL.md +0 -289
  564. package/skills/skills/xlsx/recalc.py +0 -178
  565. package/skills/spec/agent-skills-spec.md +0 -3
  566. package/skills/template/SKILL.md +0 -6
  567. package/src/ai-client.ts +0 -1560
  568. package/src/remote-ai-client.ts +0 -664
package/src/mcp.ts CHANGED
@@ -1,682 +1,730 @@
1
- import { spawn, ChildProcess } from 'child_process';
2
- import { MCPServerConfig } from './types.js';
3
-
4
- export interface MCPTool {
5
- name: string;
6
- description: string;
7
- inputSchema: any;
8
- }
9
-
10
- export class MCPServer {
11
- private config: MCPServerConfig;
12
- private process: ChildProcess | null = null;
13
- private tools: Map<string, MCPTool> = new Map();
14
- private isConnected: boolean = false;
15
- private sessionId: string | null = null; // Save MCP session-id
16
-
17
- constructor(config: MCPServerConfig) {
18
- this.config = config;
19
- }
20
-
21
- /**
22
- * Get transport type, supporting both 'transport' and 'type' fields
23
- * for MCP spec compatibility
24
- */
25
- private getTransportType(): 'stdio' | 'sse' | 'http' | undefined {
26
- return this.config.transport || this.config.type;
27
- }
28
-
29
- async connect(): Promise<void> {
30
- if (this.isConnected) {
31
- return;
32
- }
33
-
34
- const transportType = this.getTransportType();
35
-
36
- try {
37
- if (transportType === 'http' || transportType === 'sse') {
38
- await this.connectHttp();
39
- } else {
40
- await this.connectStdio();
41
- }
42
-
43
- this.isConnected = true;
44
- console.log(`✅ MCP Server connected`);
45
- } catch (error) {
46
- console.error(`❌ Failed to connect MCP Server:`, error);
47
- throw error;
48
- }
49
- }
50
-
51
- private async connectStdio(): Promise<void> {
52
- return new Promise((resolve, reject) => {
53
- if (!this.config.command) {
54
- reject(new Error('Command is required for stdio transport'));
55
- return;
56
- }
57
-
58
- let toolsLoaded = false;
59
- const toolsLoadTimeout = 5000; // 5 seconds max wait
60
-
61
- this.process = spawn(this.config.command, this.config.args || [], {
62
- env: { ...process.env, ...this.config.env },
63
- cwd: this.config.cwd,
64
- stdio: ['pipe', 'pipe', 'pipe']
65
- });
66
-
67
- this.process.on('error', (error) => {
68
- console.error('MCP Server error:', error);
69
- reject(error);
70
- });
71
-
72
- this.process.on('exit', (code, signal) => {
73
- console.log(`MCP Server exited with code ${code}, signal ${signal}`);
74
- this.isConnected = false;
75
- });
76
-
77
- if (this.process.stdout) {
78
- this.process.stdout.on('data', (data) => {
79
- this.handleMessage(data.toString());
80
- // Check if tools have been loaded after each message
81
- if (!toolsLoaded && this.tools.size > 0) {
82
- toolsLoaded = true;
83
- }
84
- });
85
- }
86
-
87
- if (this.process.stderr) {
88
- this.process.stderr.on('data', (data) => {
89
- console.error('MCP Server stderr:', data.toString());
90
- });
91
- }
92
-
93
- this.sendMessage({
94
- jsonrpc: '2.0',
95
- id: 1,
96
- method: 'initialize',
97
- params: {
98
- protocolVersion: '2024-11-05',
99
- capabilities: {
100
- tools: {}
101
- }
102
- }
103
- });
104
-
105
- // Wait for tools to be loaded or timeout
106
- const checkInterval = setInterval(() => {
107
- if (this.tools.size > 0) {
108
- clearInterval(checkInterval);
109
- clearTimeout(timeout);
110
- resolve();
111
- }
112
- }, 100);
113
-
114
- const timeout = setTimeout(() => {
115
- clearInterval(checkInterval);
116
- if (this.tools.size === 0) {
117
- console.warn('MCP Server tools not loaded within timeout');
118
- }
119
- resolve();
120
- }, toolsLoadTimeout);
121
- });
122
- }
123
-
124
- private async connectHttp(): Promise<void> {
125
- if (!this.config.url) {
126
- throw new Error('URL is required for HTTP/SSE transport');
127
- }
128
-
129
- const transportType = this.getTransportType();
130
- console.log(`Connecting to MCP Server at ${this.config.url} (${transportType})`);
131
-
132
- // Build headers with auth token
133
- const headers: Record<string, string> = {
134
- 'Content-Type': 'application/json',
135
- 'Accept': 'text/event-stream, application/json',
136
- ...this.config.headers
137
- };
138
-
139
- if (this.config.authToken) {
140
- if (this.config.authToken.startsWith('Bearer ')) {
141
- headers['Authorization'] = this.config.authToken;
142
- } else {
143
- headers['Authorization'] = `Bearer ${this.config.authToken}`;
144
- }
145
- }
146
-
147
- if (transportType === 'sse') {
148
- // For SSE transport, use fetch with streaming to receive tools/list events
149
- await this.connectSSE(this.config.url, headers);
150
- } else {
151
- // For HTTP transport, use axios POST
152
- const axios = (await import('axios')).default;
153
-
154
- try {
155
- const response = await axios.post(
156
- this.config.url,
157
- {
158
- jsonrpc: '2.0',
159
- id: 1,
160
- method: 'initialize',
161
- params: {
162
- protocolVersion: '2024-11-05',
163
- capabilities: {
164
- tools: {}
165
- }
166
- }
167
- },
168
- { headers }
169
- );
170
-
171
- // Save session-id for subsequent requests (MCP HTTP protocol requirement)
172
- const mcpSessionId = response.headers['mcp-session-id'];
173
- if (mcpSessionId) {
174
- this.sessionId = mcpSessionId;
175
- }
176
-
177
- // Some MCP servers return SSE-over-HTTP format, so we always call loadTools
178
- // which handles both regular JSON and SSE format responses
179
- await this.loadTools(headers);
180
- } catch (error: any) {
181
- console.error(`HTTP connection failed: ${error.message}`);
182
- if (error.response) {
183
- console.error(`Response status: ${error.response.status}`);
184
- if (error.response.data?.message) {
185
- console.error(`Server message: ${error.response.data.message}`);
186
- }
187
- }
188
- throw error;
189
- }
190
- }
191
- }
192
-
193
- private async connectSSE(url: string, headers: Record<string, string>): Promise<void> {
194
- const controller = new AbortController();
195
- const timeoutId = setTimeout(() => controller.abort(), 30000);
196
-
197
- try {
198
- // Send initialize request first
199
- const initResponse = await fetch(url, {
200
- method: 'POST',
201
- headers,
202
- body: JSON.stringify({
203
- jsonrpc: '2.0',
204
- id: 1,
205
- method: 'initialize',
206
- params: {
207
- protocolVersion: '2024-11-05',
208
- capabilities: {
209
- tools: {}
210
- }
211
- }
212
- }),
213
- signal: controller.signal
214
- });
215
-
216
- clearTimeout(timeoutId);
217
-
218
- if (!initResponse.ok) {
219
- throw new Error(`SSE initialize failed: ${initResponse.status} ${initResponse.statusText}`);
220
- }
221
-
222
- // Save session-id (MCP SSE protocol requirement)
223
- const mcpSessionId = initResponse.headers.get('mcp-session-id');
224
- if (mcpSessionId) {
225
- this.sessionId = mcpSessionId;
226
- }
227
-
228
- // For SSE endpoints, try to load tools via a separate POST request
229
- await this.loadTools(headers);
230
-
231
- // If no tools loaded, try reading from the response body if it's a stream
232
- if (this.tools.size === 0 && initResponse.body) {
233
- const reader = initResponse.body.getReader();
234
- const decoder = new TextDecoder();
235
- let buffer = '';
236
-
237
- while (true) {
238
- const { done, value } = await reader.read();
239
- if (done) break;
240
-
241
- buffer += decoder.decode(value, { stream: true });
242
- const lines = buffer.split('\n');
243
- buffer = lines.pop() || '';
244
-
245
- for (const line of lines) {
246
- if (line.startsWith('data: ')) {
247
- try {
248
- const data = JSON.parse(line.slice(6));
249
- this.handleJsonRpcMessage(data);
250
- } catch (e) {
251
- // Ignore parse errors
252
- }
253
- }
254
- }
255
- }
256
- }
257
- } catch (error: any) {
258
- clearTimeout(timeoutId);
259
- const serverInfo = this.config.url || this.config.command || 'MCP server';
260
- if (error.name === 'AbortError') {
261
- console.error(`\n❌ SSE connection timed out`);
262
- console.error(` Server: ${serverInfo}`);
263
- console.error(` The server is not responding. Please try again later.`);
264
- } else {
265
- console.error(`\n❌ SSE connection failed`);
266
- console.error(` Server: ${serverInfo}`);
267
- console.error(` ${error.message}`);
268
- }
269
- throw error;
270
- }
271
- }
272
-
273
- private handleMessage(data: string): void {
274
- const lines = data.split('\n').filter(line => line.trim() !== '');
275
-
276
- for (const line of lines) {
277
- try {
278
- const message = JSON.parse(line);
279
- this.handleJsonRpcMessage(message);
280
- } catch (error) {
281
- console.warn('Failed to parse MCP message:', line);
282
- }
283
- }
284
- }
285
-
286
- private handleJsonRpcMessage(message: any): void {
287
- // Handle response format: {id: 1, result: {tools: [...]}}
288
- if (message.result && message.result.tools) {
289
- this.handleToolsList(message.result);
290
- return;
291
- }
292
-
293
- // Handle notification format: {method: 'tools/list', params: {...}}
294
- if (message.method === 'tools/list') {
295
- this.handleToolsList(message.params);
296
- } else if (message.method === 'notifications/initialized') {
297
- console.log('MCP Server initialized');
298
- }
299
- }
300
-
301
- private sendMessage(message: any): void {
302
- if (this.process && this.process.stdin) {
303
- this.process.stdin.write(JSON.stringify(message) + '\n');
304
- }
305
- }
306
-
307
- private handleToolsList(result: any): void {
308
- if (result && result.tools) {
309
- for (const tool of result.tools) {
310
- if (!tool.name || typeof tool.name !== 'string' || tool.name.trim() === '') continue;
311
- this.tools.set(tool.name, tool);
312
- }
313
- console.log(`Loaded ${result.tools.length} tools from MCP Server`);
314
- }
315
- }
316
-
317
- private async loadTools(headers?: Record<string, string>): Promise<void> {
318
- if (!this.config.url) {
319
- console.warn('No URL configured, cannot load tools');
320
- return;
321
- }
322
-
323
- const axios = (await import('axios')).default;
324
-
325
- try {
326
- // Build headers with session-id for MCP protocol
327
- const requestHeaders: Record<string, string> = {
328
- 'Content-Type': 'application/json',
329
- ...this.config.headers,
330
- ...headers
331
- };
332
-
333
- if (this.sessionId) {
334
- requestHeaders['MCP-session-id'] = this.sessionId;
335
- }
336
-
337
- const response = await axios.post(
338
- this.config.url,
339
- {
340
- jsonrpc: '2.0',
341
- id: 2,
342
- method: 'tools/list'
343
- },
344
- {
345
- headers: requestHeaders,
346
- timeout: 10000
347
- }
348
- );
349
-
350
- let resultData = response.data;
351
-
352
- // Auto-detect response format (HTTP vs SSE)
353
- const contentType = response.headers['content-type'] || '';
354
- const dataStr = response.data?.toString() || '';
355
-
356
- const isSSE = contentType.includes('text/event-stream') ||
357
- dataStr.startsWith('id:') ||
358
- dataStr.startsWith('data:');
359
-
360
- if (isSSE) {
361
- // Parse SSE format: "id:1\nevent:message\ndata:{...}"
362
- const dataMatch = dataStr.match(/data:(.+)$/m);
363
- if (dataMatch) {
364
- try {
365
- resultData = JSON.parse(dataMatch[1].trim());
366
- } catch (e: any) {
367
- console.error(`Failed to parse SSE data: ${e.message}`);
368
- }
369
- }
370
- }
371
-
372
- if (resultData?.result?.tools) {
373
- this.handleToolsList(resultData.result);
374
- } else if (resultData?.tools) {
375
- this.handleToolsList(resultData);
376
- } else if (resultData?.error) {
377
- console.error(`\n❌ MCP server returned an error`);
378
- console.error(` ${resultData.error.message || 'Unknown error'}`);
379
- }
380
- } catch (error: any) {
381
- const serverInfo = this.config.url || this.config.command || 'MCP server';
382
- console.error(`\n❌ Failed to load MCP tools`);
383
- console.error(` Server: ${serverInfo}`);
384
- console.error(` ${error.message}`);
385
- }
386
- }
387
-
388
- async callTool(toolName: string, params: any): Promise<any> {
389
- if (!this.isConnected) {
390
- throw new Error('MCP Server is not connected');
391
- }
392
-
393
- const tool = this.tools.get(toolName);
394
- if (!tool) {
395
- throw new Error(`Tool not found: ${toolName}`);
396
- }
397
-
398
- const message = {
399
- jsonrpc: '2.0',
400
- id: Date.now(),
401
- method: 'tools/call',
402
- params: {
403
- name: toolName,
404
- arguments: params
405
- }
406
- };
407
-
408
- if (this.getTransportType() === 'http' || this.getTransportType() === 'sse') {
409
- return await this.callToolHttp(message);
410
- } else {
411
- return await this.callToolStdio(message);
412
- }
413
- }
414
-
415
- private async callToolHttp(message: any): Promise<any> {
416
- const axios = (await import('axios')).default;
417
-
418
- try {
419
- // Build headers with auth token
420
- const headers: Record<string, string> = {
421
- 'Content-Type': 'application/json',
422
- 'Accept': 'application/json, text/event-stream',
423
- ...this.config.headers
424
- };
425
-
426
- if (this.config.authToken) {
427
- if (this.config.authToken.startsWith('Bearer ')) {
428
- headers['Authorization'] = this.config.authToken;
429
- } else {
430
- headers['Authorization'] = `Bearer ${this.config.authToken}`;
431
- }
432
- }
433
-
434
- // Add session-id to request headers (MCP HTTP protocol requirement)
435
- if (this.sessionId) {
436
- headers['MCP-session-id'] = this.sessionId;
437
- }
438
-
439
- const response = await axios.post(this.config.url!, message, {
440
- headers,
441
- timeout: this.config.timeout || 30000
442
- });
443
-
444
- // Update session-id if new one provided in response
445
- const responseSessionId = response.headers['mcp-session-id'];
446
- if (responseSessionId) {
447
- this.sessionId = responseSessionId;
448
- }
449
-
450
- // Auto-detect response format (HTTP vs SSE)
451
- const contentType = response.headers['content-type'] || '';
452
- let resultData;
453
-
454
- if (contentType.includes('text/event-stream') ||
455
- (typeof response.data === 'string' && response.data.startsWith('id:'))) {
456
- // Parse SSE format: "id:1\nevent:message\ndata:{...}"
457
- const sseData = response.data;
458
- const dataMatch = sseData.match(/data:(.+)$/m);
459
- if (dataMatch) {
460
- try {
461
- resultData = JSON.parse(dataMatch[1].trim());
462
- } catch (e: any) {
463
- throw new Error(`Failed to parse SSE data: ${e.message}`);
464
- }
465
- } else {
466
- throw new Error('No data field found in SSE response');
467
- }
468
- } else {
469
- // Direct JSON response
470
- resultData = response.data;
471
- }
472
-
473
- // Check for error response
474
- if (resultData?.isError) {
475
- const errorMsg = resultData?.content?.[0]?.text || 'Unknown error';
476
- throw new Error(`MCP server error: ${errorMsg}`);
477
- }
478
-
479
- return resultData?.result;
480
- } catch (error: any) {
481
- throw new Error(`MCP Tool call failed: ${error.message}`);
482
- }
483
- }
484
-
485
- private async callToolStdio(message: any): Promise<any> {
486
- return new Promise((resolve, reject) => {
487
- if (!this.process) {
488
- reject(new Error('MCP Server process not running'));
489
- return;
490
- }
491
-
492
- const timeout = setTimeout(() => {
493
- reject(new Error('MCP Tool call timeout'));
494
- }, this.config.timeout || 30000);
495
-
496
- const responseHandler = (data: Buffer) => {
497
- try {
498
- const rawResponse = data.toString();
499
- const response = JSON.parse(rawResponse);
500
-
501
- if (process.env.DEBUG === 'mcp' || process.env.DEBUG === 'all') {
502
- console.log('\n========== MCP STDIO Raw Response ==========');
503
- console.log('Raw:', rawResponse);
504
- console.log('Parsed:', JSON.stringify(response, null, 2));
505
- console.log('==========================================\n');
506
- }
507
-
508
- if (response.id === message.id) {
509
- clearTimeout(timeout);
510
- this.process?.stdout?.off('data', responseHandler);
511
-
512
- if (response.error) {
513
- reject(new Error(`MCP tool error: ${response.error.message || 'Unknown error'}`));
514
- } else {
515
- resolve(response.result);
516
- }
517
- }
518
- } catch (error) {
519
- console.error('\n========== MCP STDIO Parse Error ==========');
520
- console.error('Raw data:', data.toString());
521
- console.error('Error:', error);
522
- console.error('==========================================\n');
523
- reject(error);
524
- }
525
- };
526
-
527
- this.process.stdout?.on('data', responseHandler);
528
- this.process.stdin?.write(JSON.stringify(message) + '\n');
529
- });
530
- }
531
-
532
- getTools(): MCPTool[] {
533
- return Array.from(this.tools.values());
534
- }
535
-
536
- getToolNames(): string[] {
537
- return Array.from(this.tools.keys());
538
- }
539
-
540
- disconnect(): void {
541
- if (this.process) {
542
- this.process.kill();
543
- this.process = null;
544
- }
545
- this.isConnected = false;
546
- this.tools.clear();
547
- }
548
-
549
- isServerConnected(): boolean {
550
- return this.isConnected;
551
- }
552
- }
553
-
554
- export class MCPManager {
555
- private servers: Map<string, MCPServer> = new Map();
556
-
557
- registerServer(name: string, config: MCPServerConfig): void {
558
- const server = new MCPServer(config);
559
- this.servers.set(name, server);
560
- }
561
-
562
- async connectServer(name: string): Promise<void> {
563
- const server = this.servers.get(name);
564
- if (!server) {
565
- throw new Error(`MCP server not found: ${name}. Please check the server name and try again.`);
566
- }
567
- await server.connect();
568
- }
569
-
570
- async connectAllServers(): Promise<void> {
571
- const connectionPromises = Array.from(this.servers.entries()).map(
572
- async ([name, server]) => {
573
- try {
574
- await server.connect();
575
- } catch (error) {
576
- console.error(`Failed to connect MCP server ${name}:`, error);
577
- }
578
- }
579
- );
580
-
581
- await Promise.all(connectionPromises);
582
- }
583
-
584
- disconnectServer(name: string): void {
585
- const server = this.servers.get(name);
586
- if (server) {
587
- server.disconnect();
588
- }
589
- }
590
-
591
- disconnectAllServers(): void {
592
- this.servers.forEach(server => server.disconnect());
593
- }
594
-
595
- getServer(name: string): MCPServer | undefined {
596
- return this.servers.get(name);
597
- }
598
-
599
- getAllServers(): MCPServer[] {
600
- return Array.from(this.servers.values());
601
- }
602
-
603
- /**
604
- * Get all registered server configurations (without connecting)
605
- * Used for generating system prompt without waiting for MCP initialization
606
- */
607
- getAllServerConfigs(): { name: string; config: MCPServerConfig }[] {
608
- return Array.from(this.servers.entries()).map(([name, server]) => ({
609
- name,
610
- config: (server as any).config
611
- }));
612
- }
613
-
614
- getAllTools(): Map<string, MCPTool> {
615
- const allTools = new Map<string, MCPTool>();
616
-
617
- this.servers.forEach((server, serverName) => {
618
- server.getTools().forEach(tool => {
619
- if (!tool.name) return;
620
- allTools.set(`${serverName}__${tool.name}`, tool);
621
- });
622
- });
623
-
624
- return allTools;
625
- }
626
-
627
- async callTool(toolName: string, params: any): Promise<any> {
628
- // Split only on the first __ to preserve underscores in tool names
629
- const firstUnderscoreIndex = toolName.indexOf('__');
630
- if (firstUnderscoreIndex === -1) {
631
- throw new Error(`Invalid tool name format: ${toolName}`);
632
- }
633
- const serverName = toolName.substring(0, firstUnderscoreIndex);
634
- const actualToolName = toolName.substring(firstUnderscoreIndex + 2);
635
-
636
- const server = this.servers.get(serverName);
637
- if (!server) {
638
- throw new Error(`MCP Server not found: ${serverName}`);
639
- }
640
-
641
- // Lazy connect if not connected
642
- if (!server.isServerConnected()) {
643
- await server.connect();
644
- }
645
-
646
- return await server.callTool(actualToolName, params);
647
- }
648
-
649
- getToolDefinitions(): any[] {
650
- const tools: any[] = [];
651
-
652
- this.servers.forEach((server, serverName) => {
653
- server.getTools().forEach(tool => {
654
- if (!tool.name) return;
655
-
656
- tools.push({
657
- type: 'function',
658
- function: {
659
- name: `${serverName}__${tool.name}`,
660
- description: tool.description || `MCP tool: ${tool.name}`,
661
- parameters: tool.inputSchema || {
662
- type: 'object',
663
- properties: {},
664
- required: []
665
- }
666
- }
667
- });
668
- });
669
- });
670
-
671
- return tools;
672
- }
673
- }
674
-
675
- let mcpManagerInstance: MCPManager | null = null;
676
-
677
- export function getMCPManager(): MCPManager {
678
- if (!mcpManagerInstance) {
679
- mcpManagerInstance = new MCPManager();
680
- }
681
- return mcpManagerInstance;
682
- }
1
+ import { spawn, ChildProcess } from 'child_process';
2
+ import { MCPServerConfig } from './types.js';
3
+
4
+ export interface MCPTool {
5
+ name: string;
6
+ description: string;
7
+ inputSchema: any;
8
+ }
9
+
10
+ export class MCPServer {
11
+ private config: MCPServerConfig;
12
+ private process: ChildProcess | null = null;
13
+ private tools: Map<string, MCPTool> = new Map();
14
+ private isConnected: boolean = false;
15
+ private sessionId: string | null = null; // Save MCP session-id
16
+
17
+ constructor(config: MCPServerConfig) {
18
+ this.config = config;
19
+ }
20
+
21
+ /**
22
+ * Get transport type, supporting both 'transport' and 'type' fields
23
+ * for MCP spec compatibility
24
+ */
25
+ private getTransportType(): 'stdio' | 'sse' | 'http' | undefined {
26
+ return this.config.transport || this.config.type;
27
+ }
28
+
29
+ async connect(): Promise<void> {
30
+ if (this.isConnected) {
31
+ return;
32
+ }
33
+
34
+ const transportType = this.getTransportType();
35
+
36
+ try {
37
+ if (transportType === 'http' || transportType === 'sse') {
38
+ await this.connectHttp();
39
+ } else {
40
+ await this.connectStdio();
41
+ }
42
+
43
+ // Wait for tools to be loaded (max 10 seconds)
44
+ await this.waitForTools(10000);
45
+
46
+ this.isConnected = true;
47
+ console.log(`✅ MCP Server connected`);
48
+ } catch (error) {
49
+ console.error(`❌ [mcp] Failed to connect MCP Server: ${error instanceof Error ? error.message : String(error)}`);
50
+ throw error;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Wait for tools to be loaded from MCP server
56
+ * @param timeoutMs Maximum time to wait in milliseconds
57
+ */
58
+ async waitForTools(timeoutMs: number = 10000): Promise<void> {
59
+ if (this.tools.size > 0) {
60
+ return; // Tools already loaded
61
+ }
62
+
63
+ return new Promise((resolve, reject) => {
64
+ const checkInterval = 100;
65
+ const startTime = Date.now();
66
+
67
+ const check = () => {
68
+ if (this.tools.size > 0) {
69
+ clearInterval(checkInterval);
70
+ resolve();
71
+ } else if (Date.now() - startTime > timeoutMs) {
72
+ clearInterval(checkInterval);
73
+ console.warn(`[MCP] Timeout waiting for tools (${timeoutMs}ms), proceeding anyway`);
74
+ resolve(); // Don't reject, just proceed without tools
75
+ } else {
76
+ // Continue checking
77
+ }
78
+ };
79
+
80
+ const intervalId = setInterval(check, checkInterval);
81
+ check(); // Check immediately first
82
+ });
83
+ }
84
+
85
+ private async connectStdio(): Promise<void> {
86
+ return new Promise((resolve, reject) => {
87
+ if (!this.config.command) {
88
+ reject(new Error('Command is required for stdio transport'));
89
+ return;
90
+ }
91
+
92
+ this.process = spawn(this.config.command, this.config.args || [], {
93
+ env: { ...process.env, ...this.config.env },
94
+ cwd: this.config.cwd,
95
+ stdio: ['pipe', 'pipe', 'pipe']
96
+ });
97
+
98
+ this.process.on('error', (error) => {
99
+ console.error('MCP Server error:', error);
100
+ reject(error);
101
+ });
102
+
103
+ this.process.on('exit', (code, signal) => {
104
+ console.log(`MCP Server exited with code ${code}, signal ${signal}`);
105
+ this.isConnected = false;
106
+ });
107
+
108
+ if (this.process.stdout) {
109
+ this.process.stdout.on('data', (data) => {
110
+ this.handleMessage(data.toString());
111
+ });
112
+ }
113
+
114
+ if (this.process.stderr) {
115
+ this.process.stderr.on('data', (data) => {
116
+ console.error('MCP Server stderr:', data.toString());
117
+ });
118
+ }
119
+
120
+ this.sendMessage({
121
+ jsonrpc: '2.0',
122
+ id: 1,
123
+ method: 'initialize',
124
+ params: {
125
+ protocolVersion: '2024-11-05',
126
+ capabilities: {
127
+ tools: {}
128
+ }
129
+ }
130
+ });
131
+
132
+ // Connection established, tools loading is handled by waitForTools() in connect()
133
+ resolve();
134
+ });
135
+ }
136
+
137
+ private async connectHttp(): Promise<void> {
138
+ if (!this.config.url) {
139
+ throw new Error('URL is required for HTTP/SSE transport');
140
+ }
141
+
142
+ const transportType = this.getTransportType();
143
+ console.log(`Connecting to MCP Server at ${this.config.url} (${transportType})`);
144
+
145
+ // Build headers with auth token
146
+ const headers: Record<string, string> = {
147
+ 'Content-Type': 'application/json',
148
+ 'Accept': 'text/event-stream, application/json',
149
+ ...this.config.headers
150
+ };
151
+
152
+ if (this.config.authToken) {
153
+ if (this.config.authToken.startsWith('Bearer ')) {
154
+ headers['Authorization'] = this.config.authToken;
155
+ } else {
156
+ headers['Authorization'] = `Bearer ${this.config.authToken}`;
157
+ }
158
+ }
159
+
160
+ if (transportType === 'sse') {
161
+ // For SSE transport, use fetch with streaming to receive tools/list events
162
+ await this.connectSSE(this.config.url, headers);
163
+ } else {
164
+ // For HTTP transport, use axios POST
165
+ const axios = (await import('axios')).default;
166
+
167
+ try {
168
+ const response = await axios.post(
169
+ this.config.url,
170
+ {
171
+ jsonrpc: '2.0',
172
+ id: 1,
173
+ method: 'initialize',
174
+ params: {
175
+ protocolVersion: '2024-11-05',
176
+ capabilities: {
177
+ tools: {}
178
+ }
179
+ }
180
+ },
181
+ { headers }
182
+ );
183
+
184
+ // Save session-id for subsequent requests (MCP HTTP protocol requirement)
185
+ const mcpSessionId = response.headers['mcp-session-id'];
186
+ if (mcpSessionId) {
187
+ this.sessionId = mcpSessionId;
188
+ }
189
+
190
+ // Some MCP servers return SSE-over-HTTP format, so we always call loadTools
191
+ // which handles both regular JSON and SSE format responses
192
+ await this.loadTools(headers);
193
+ } catch (error: any) {
194
+ console.error(`HTTP connection failed: ${error.message}`);
195
+ if (error.response) {
196
+ console.error(`Response status: ${error.response.status}`);
197
+ if (error.response.data?.message) {
198
+ console.error(`Server message: ${error.response.data.message}`);
199
+ }
200
+ }
201
+ throw error;
202
+ }
203
+ }
204
+ }
205
+
206
+ private async connectSSE(url: string, headers: Record<string, string>): Promise<void> {
207
+ const controller = new AbortController();
208
+ const timeoutId = setTimeout(() => controller.abort(), 30000);
209
+
210
+ try {
211
+ // Send initialize request first
212
+ const initResponse = await fetch(url, {
213
+ method: 'POST',
214
+ headers,
215
+ body: JSON.stringify({
216
+ jsonrpc: '2.0',
217
+ id: 1,
218
+ method: 'initialize',
219
+ params: {
220
+ protocolVersion: '2024-11-05',
221
+ capabilities: {
222
+ tools: {}
223
+ }
224
+ }
225
+ }),
226
+ signal: controller.signal
227
+ });
228
+
229
+ clearTimeout(timeoutId);
230
+
231
+ if (!initResponse.ok) {
232
+ throw new Error(`SSE initialize failed: ${initResponse.status} ${initResponse.statusText}`);
233
+ }
234
+
235
+ // Save session-id (MCP SSE protocol requirement)
236
+ const mcpSessionId = initResponse.headers.get('mcp-session-id');
237
+ if (mcpSessionId) {
238
+ this.sessionId = mcpSessionId;
239
+ }
240
+
241
+ // For SSE endpoints, try to load tools via a separate POST request
242
+ await this.loadTools(headers);
243
+
244
+ // If no tools loaded, try reading from the response body if it's a stream
245
+ if (this.tools.size === 0 && initResponse.body) {
246
+ const reader = initResponse.body.getReader();
247
+ const decoder = new TextDecoder();
248
+ let buffer = '';
249
+
250
+ while (true) {
251
+ const { done, value } = await reader.read();
252
+ if (done) break;
253
+
254
+ buffer += decoder.decode(value, { stream: true });
255
+ const lines = buffer.split('\n');
256
+ buffer = lines.pop() || '';
257
+
258
+ for (const line of lines) {
259
+ if (line.startsWith('data: ')) {
260
+ try {
261
+ const data = JSON.parse(line.slice(6));
262
+ this.handleJsonRpcMessage(data);
263
+ } catch (e) {
264
+ // Ignore parse errors
265
+ }
266
+ }
267
+ }
268
+ }
269
+ }
270
+ } catch (error: any) {
271
+ clearTimeout(timeoutId);
272
+ const serverInfo = this.config.url || this.config.command || 'MCP server';
273
+ if (error.name === 'AbortError') {
274
+ console.error(`\n SSE connection timed out`);
275
+ console.error(` Server: ${serverInfo}`);
276
+ console.error(` The server is not responding. Please try again later.`);
277
+ } else {
278
+ console.error(`\n❌ SSE connection failed`);
279
+ console.error(` Server: ${serverInfo}`);
280
+ console.error(` ${error.message}`);
281
+ }
282
+ throw error;
283
+ }
284
+ }
285
+
286
+ private handleMessage(data: string): void {
287
+ const lines = data.split('\n').filter(line => line.trim() !== '');
288
+
289
+ for (const line of lines) {
290
+ try {
291
+ const message = JSON.parse(line);
292
+ this.handleJsonRpcMessage(message);
293
+ } catch (error) {
294
+ console.warn(`[mcp] Failed to parse MCP message: ${error instanceof Error ? error.message : String(error)}`, line);
295
+ }
296
+ }
297
+ }
298
+
299
+ private handleJsonRpcMessage(message: any): void {
300
+ // Handle response format: {id: 1, result: {tools: [...]}}
301
+ if (message.result && message.result.tools) {
302
+ this.handleToolsList(message.result);
303
+ return;
304
+ }
305
+
306
+ // Handle notification format: {method: 'tools/list', params: {...}}
307
+ if (message.method === 'tools/list') {
308
+ this.handleToolsList(message.params);
309
+ } else if (message.method === 'notifications/initialized') {
310
+ console.log('MCP Server initialized');
311
+ }
312
+ }
313
+
314
+ private sendMessage(message: any): void {
315
+ if (this.process && this.process.stdin) {
316
+ this.process.stdin.write(JSON.stringify(message) + '\n');
317
+ }
318
+ }
319
+
320
+ private handleToolsList(result: any): void {
321
+ if (result && result.tools) {
322
+ for (const tool of result.tools) {
323
+ if (!tool.name || typeof tool.name !== 'string' || tool.name.trim() === '') continue;
324
+ this.tools.set(tool.name, tool);
325
+ }
326
+ console.log(`Loaded ${result.tools.length} tools from MCP Server`);
327
+ }
328
+ }
329
+
330
+ private async loadTools(headers?: Record<string, string>): Promise<void> {
331
+ if (!this.config.url) {
332
+ console.warn('No URL configured, cannot load tools');
333
+ return;
334
+ }
335
+
336
+ const axios = (await import('axios')).default;
337
+
338
+ try {
339
+ // Build headers with session-id for MCP protocol
340
+ const requestHeaders: Record<string, string> = {
341
+ 'Content-Type': 'application/json',
342
+ ...this.config.headers,
343
+ ...headers
344
+ };
345
+
346
+ if (this.sessionId) {
347
+ requestHeaders['MCP-session-id'] = this.sessionId;
348
+ }
349
+
350
+ const response = await axios.post(
351
+ this.config.url,
352
+ {
353
+ jsonrpc: '2.0',
354
+ id: 2,
355
+ method: 'tools/list'
356
+ },
357
+ {
358
+ headers: requestHeaders,
359
+ timeout: 10000
360
+ }
361
+ );
362
+
363
+ let resultData = response.data;
364
+
365
+ // Auto-detect response format (HTTP vs SSE)
366
+ const contentType = response.headers['content-type'] || '';
367
+ const dataStr = response.data?.toString() || '';
368
+
369
+ const isSSE = contentType.includes('text/event-stream') ||
370
+ dataStr.startsWith('id:') ||
371
+ dataStr.startsWith('data:');
372
+
373
+ if (isSSE) {
374
+ // Parse SSE format: "id:1\nevent:message\ndata:{...}"
375
+ const dataMatch = dataStr.match(/data:(.+)$/m);
376
+ if (dataMatch) {
377
+ try {
378
+ resultData = JSON.parse(dataMatch[1].trim());
379
+ } catch (e: any) {
380
+ console.error(`Failed to parse SSE data: ${e.message}`);
381
+ }
382
+ }
383
+ }
384
+
385
+ if (resultData?.result?.tools) {
386
+ this.handleToolsList(resultData.result);
387
+ } else if (resultData?.tools) {
388
+ this.handleToolsList(resultData);
389
+ } else if (resultData?.error) {
390
+ console.error(`\n❌ MCP server returned an error`);
391
+ console.error(` ${resultData.error.message || 'Unknown error'}`);
392
+ }
393
+ } catch (error: any) {
394
+ const serverInfo = this.config.url || this.config.command || 'MCP server';
395
+ console.error(`\n❌ Failed to load MCP tools`);
396
+ console.error(` Server: ${serverInfo}`);
397
+ console.error(` ${error.message}`);
398
+ }
399
+ }
400
+
401
+ async callTool(toolName: string, params: any): Promise<any> {
402
+ if (!this.isConnected) {
403
+ throw new Error('MCP Server is not connected');
404
+ }
405
+
406
+ const tool = this.tools.get(toolName);
407
+ if (!tool) {
408
+ throw new Error(`Tool not found: ${toolName}`);
409
+ }
410
+
411
+ const message = {
412
+ jsonrpc: '2.0',
413
+ id: Date.now(),
414
+ method: 'tools/call',
415
+ params: {
416
+ name: toolName,
417
+ arguments: params
418
+ }
419
+ };
420
+
421
+ if (this.getTransportType() === 'http' || this.getTransportType() === 'sse') {
422
+ return await this.callToolHttp(message);
423
+ } else {
424
+ return await this.callToolStdio(message);
425
+ }
426
+ }
427
+
428
+ private async callToolHttp(message: any): Promise<any> {
429
+ const axios = (await import('axios')).default;
430
+
431
+ try {
432
+ // Build headers with auth token
433
+ const headers: Record<string, string> = {
434
+ 'Content-Type': 'application/json',
435
+ 'Accept': 'application/json, text/event-stream',
436
+ ...this.config.headers
437
+ };
438
+
439
+ if (this.config.authToken) {
440
+ if (this.config.authToken.startsWith('Bearer ')) {
441
+ headers['Authorization'] = this.config.authToken;
442
+ } else {
443
+ headers['Authorization'] = `Bearer ${this.config.authToken}`;
444
+ }
445
+ }
446
+
447
+ // Add session-id to request headers (MCP HTTP protocol requirement)
448
+ if (this.sessionId) {
449
+ headers['MCP-session-id'] = this.sessionId;
450
+ }
451
+
452
+ const response = await axios.post(this.config.url!, message, {
453
+ headers,
454
+ timeout: this.config.timeout || 30000
455
+ });
456
+
457
+ // Update session-id if new one provided in response
458
+ const responseSessionId = response.headers['mcp-session-id'];
459
+ if (responseSessionId) {
460
+ this.sessionId = responseSessionId;
461
+ }
462
+
463
+ // Auto-detect response format (HTTP vs SSE)
464
+ const contentType = response.headers['content-type'] || '';
465
+ let resultData;
466
+
467
+ if (contentType.includes('text/event-stream') ||
468
+ (typeof response.data === 'string' && response.data.startsWith('id:'))) {
469
+ // Parse SSE format: "id:1\nevent:message\ndata:{...}"
470
+ // MCP SSE responses may contain multiple data blocks, need to find the one with the result
471
+ const responseStr = typeof response.data === 'string' ? response.data : JSON.stringify(response.data);
472
+ const dataMatches = responseStr.match(/data:(.+)/g);
473
+
474
+ if (dataMatches) {
475
+ // Look for the data block that contains the matching id or result
476
+ for (const dataMatch of dataMatches) {
477
+ try {
478
+ const dataContent = dataMatch.replace('data:', '').trim();
479
+ const parsed = JSON.parse(dataContent);
480
+ // Find the data block that has the matching id or result
481
+ if (parsed.id === message.id || parsed.result) {
482
+ resultData = parsed;
483
+ break;
484
+ }
485
+ } catch (e) {
486
+ continue;
487
+ }
488
+ }
489
+ }
490
+
491
+ // Fallback: try to parse the last data block if no matching one found
492
+ if (!resultData) {
493
+ const dataMatch = responseStr.match(/data:({.*})/);
494
+ if (dataMatch) {
495
+ try {
496
+ resultData = JSON.parse(dataMatch[1]);
497
+ } catch (e) {
498
+ throw new Error('Failed to parse SSE response');
499
+ }
500
+ } else if (!resultData) {
501
+ // Try to parse the entire response as JSON
502
+ try {
503
+ resultData = JSON.parse(responseStr);
504
+ } catch (e) {
505
+ throw new Error('No valid data field found in SSE response');
506
+ }
507
+ }
508
+ }
509
+ } else {
510
+ // Direct JSON response
511
+ resultData = response.data;
512
+ }
513
+
514
+ // Check for error response
515
+ if (resultData?.isError) {
516
+ const errorMsg = resultData?.content?.[0]?.text || 'Unknown error';
517
+ throw new Error(`MCP server error: ${errorMsg}`);
518
+ }
519
+
520
+ // Return the content array from result (MCP result format: { content: [{type: 'text', text: '...'}] })
521
+ if (resultData?.result?.content) {
522
+ return resultData.result.content;
523
+ }
524
+
525
+ // Fallback: return result as-is if no content field
526
+ return resultData?.result;
527
+ } catch (error: any) {
528
+ throw new Error(`MCP Tool call failed: ${error.message}`);
529
+ }
530
+ }
531
+
532
+ private async callToolStdio(message: any): Promise<any> {
533
+ return new Promise((resolve, reject) => {
534
+ if (!this.process) {
535
+ reject(new Error('MCP Server process not running'));
536
+ return;
537
+ }
538
+
539
+ const timeout = setTimeout(() => {
540
+ reject(new Error('MCP Tool call timeout'));
541
+ }, this.config.timeout || 30000);
542
+
543
+ const responseHandler = (data: Buffer) => {
544
+ try {
545
+ const rawResponse = data.toString();
546
+ const response = JSON.parse(rawResponse);
547
+
548
+ if (process.env.DEBUG === 'mcp' || process.env.DEBUG === 'all') {
549
+ console.log('\n========== MCP STDIO Raw Response ==========');
550
+ console.log('Raw:', rawResponse);
551
+ console.log('Parsed:', JSON.stringify(response, null, 2));
552
+ console.log('==========================================\n');
553
+ }
554
+
555
+ if (response.id === message.id) {
556
+ clearTimeout(timeout);
557
+ this.process?.stdout?.off('data', responseHandler);
558
+
559
+ if (response.error) {
560
+ reject(new Error(`MCP tool error: ${response.error.message || 'Unknown error'}`));
561
+ } else {
562
+ resolve(response.result);
563
+ }
564
+ }
565
+ } catch (error) {
566
+ const errorMsg = error instanceof Error ? error.message : String(error);
567
+ console.error('\n========== MCP STDIO Parse Error ==========');
568
+ console.error('Raw data:', data.toString());
569
+ console.error('Error:', errorMsg);
570
+ console.error('==========================================\n');
571
+ reject(error);
572
+ }
573
+ };
574
+
575
+ this.process.stdout?.on('data', responseHandler);
576
+ this.process.stdin?.write(JSON.stringify(message) + '\n');
577
+ });
578
+ }
579
+
580
+ getTools(): MCPTool[] {
581
+ return Array.from(this.tools.values());
582
+ }
583
+
584
+ getToolNames(): string[] {
585
+ return Array.from(this.tools.keys());
586
+ }
587
+
588
+ disconnect(): void {
589
+ if (this.process) {
590
+ this.process.kill();
591
+ this.process = null;
592
+ }
593
+ this.isConnected = false;
594
+ this.tools.clear();
595
+ }
596
+
597
+ isServerConnected(): boolean {
598
+ return this.isConnected;
599
+ }
600
+ }
601
+
602
+ export class MCPManager {
603
+ private servers: Map<string, MCPServer> = new Map();
604
+
605
+ registerServer(name: string, config: MCPServerConfig): void {
606
+ const server = new MCPServer(config);
607
+ this.servers.set(name, server);
608
+ }
609
+
610
+ async connectServer(name: string): Promise<void> {
611
+ const server = this.servers.get(name);
612
+ if (!server) {
613
+ throw new Error(`MCP server not found: ${name}. Please check the server name and try again.`);
614
+ }
615
+ await server.connect();
616
+ }
617
+
618
+ async connectAllServers(): Promise<void> {
619
+ const connectionPromises = Array.from(this.servers.entries()).map(
620
+ async ([name, server]) => {
621
+ try {
622
+ await server.connect();
623
+ } catch (error) {
624
+ console.error(`[mcp] Failed to connect MCP server ${name}: ${error instanceof Error ? error.message : String(error)}`);
625
+ }
626
+ }
627
+ );
628
+
629
+ await Promise.all(connectionPromises);
630
+ }
631
+
632
+ disconnectServer(name: string): void {
633
+ const server = this.servers.get(name);
634
+ if (server) {
635
+ server.disconnect();
636
+ }
637
+ }
638
+
639
+ disconnectAllServers(): void {
640
+ this.servers.forEach(server => server.disconnect());
641
+ }
642
+
643
+ getServer(name: string): MCPServer | undefined {
644
+ return this.servers.get(name);
645
+ }
646
+
647
+ getAllServers(): MCPServer[] {
648
+ return Array.from(this.servers.values());
649
+ }
650
+
651
+ /**
652
+ * Get all registered server configurations (without connecting)
653
+ * Used for generating system prompt without waiting for MCP initialization
654
+ */
655
+ getAllServerConfigs(): { name: string; config: MCPServerConfig }[] {
656
+ return Array.from(this.servers.entries()).map(([name, server]) => ({
657
+ name,
658
+ config: (server as any).config
659
+ }));
660
+ }
661
+
662
+ getAllTools(): Map<string, MCPTool> {
663
+ const allTools = new Map<string, MCPTool>();
664
+
665
+ this.servers.forEach((server, serverName) => {
666
+ server.getTools().forEach(tool => {
667
+ if (!tool.name) return;
668
+ allTools.set(`${serverName}__${tool.name}`, tool);
669
+ });
670
+ });
671
+
672
+ return allTools;
673
+ }
674
+
675
+ async callTool(toolName: string, params: any): Promise<any> {
676
+ // Split only on the first __ to preserve underscores in tool names
677
+ const firstUnderscoreIndex = toolName.indexOf('__');
678
+ if (firstUnderscoreIndex === -1) {
679
+ throw new Error(`Invalid tool name format: ${toolName}`);
680
+ }
681
+ const serverName = toolName.substring(0, firstUnderscoreIndex);
682
+ const actualToolName = toolName.substring(firstUnderscoreIndex + 2);
683
+
684
+ const server = this.servers.get(serverName);
685
+ if (!server) {
686
+ throw new Error(`MCP Server not found: ${serverName}`);
687
+ }
688
+
689
+ // Lazy connect if not connected
690
+ if (!server.isServerConnected()) {
691
+ await server.connect();
692
+ }
693
+
694
+ return await server.callTool(actualToolName, params);
695
+ }
696
+
697
+ getToolDefinitions(): any[] {
698
+ const tools: any[] = [];
699
+
700
+ this.servers.forEach((server, serverName) => {
701
+ server.getTools().forEach(tool => {
702
+ if (!tool.name) return;
703
+
704
+ tools.push({
705
+ type: 'function',
706
+ function: {
707
+ name: `${serverName}__${tool.name}`,
708
+ description: tool.description || `MCP tool: ${tool.name}`,
709
+ parameters: tool.inputSchema || {
710
+ type: 'object',
711
+ properties: {},
712
+ required: []
713
+ }
714
+ }
715
+ });
716
+ });
717
+ });
718
+
719
+ return tools;
720
+ }
721
+ }
722
+
723
+ let mcpManagerInstance: MCPManager | null = null;
724
+
725
+ export function getMCPManager(): MCPManager {
726
+ if (!mcpManagerInstance) {
727
+ mcpManagerInstance = new MCPManager();
728
+ }
729
+ return mcpManagerInstance;
730
+ }