@xagent-ai/cli 1.2.2 → 1.3.1

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