foliko 1.1.6 → 1.1.8

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 (307) hide show
  1. package/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
  2. package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
  3. package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
  4. package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
  5. package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
  6. package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
  7. package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
  8. package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  9. package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  10. package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  11. package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  12. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  13. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  14. package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  15. package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
  16. package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  17. package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  18. package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  19. package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  20. package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
  21. package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
  22. package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  23. package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  24. package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
  25. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  26. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  27. package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
  28. package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
  29. package/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
  30. package/.agent/ARCHITECTURE.md +288 -0
  31. package/.agent/agents/ambient-agent.md +57 -0
  32. package/.agent/agents/debugger.md +55 -0
  33. package/.agent/agents/email-assistant.md +49 -0
  34. package/.agent/agents/file-manager.md +42 -0
  35. package/.agent/agents/python-developer.md +60 -0
  36. package/.agent/agents/scheduler.md +59 -0
  37. package/.agent/agents/web-developer.md +45 -0
  38. package/.agent/data/default.json +412 -3
  39. package/.agent/data/plugins-state.json +177 -174
  40. package/.agent/data/puppeteer-sessions/undefined.json +6 -0
  41. package/.agent/data/weixin-media/2026-04-08/img_1775618677512.jpg +0 -0
  42. package/.agent/data/weixin-media/2026-04-08/img_1775619073340.jpg +0 -0
  43. package/.agent/data/weixin-media/2026-04-08/img_1775619097536.jpg +0 -0
  44. package/.agent/data/weixin-media/2026-04-08/img_1775619209388.jpg +0 -0
  45. package/.agent/mcp_config.json +11 -3
  46. package/.agent/memory/feedback/mnrdvj5i-ca3dkd.md +9 -0
  47. package/.agent/memory/feedback/mnre365e-7s4zax.md +9 -0
  48. package/.agent/memory/feedback/mnre36jn-nkfgmp.md +9 -0
  49. package/.agent/memory/feedback/mnre3805-kjiq6h.md +9 -0
  50. package/.agent/memory/feedback/mnsf66kp-b10rcd.md +9 -0
  51. package/.agent/memory/feedback/mnsi3sz8-p5g2cw.md +9 -0
  52. package/.agent/memory/feedback/mnsibe47-sv2ni1.md +9 -0
  53. package/.agent/memory/feedback/mnsic89w-nn228o.md +9 -0
  54. package/.agent/memory/feedback/mnsj1xe9-x83ba0.md +9 -0
  55. package/.agent/memory/feedback/mnsj21iv-wnwelx.md +9 -0
  56. package/.agent/memory/feedback/mnsj2g4a-cog7a2.md +9 -0
  57. package/.agent/memory/feedback/mnsj4js7-lktjp6.md +9 -0
  58. package/.agent/memory/feedback/mnsj5d4y-uglwvp.md +9 -0
  59. package/.agent/memory/feedback/mnslkuo9-uous66.md +24 -0
  60. package/.agent/memory/feedback/mnsm3vq0-megoil.md +9 -0
  61. package/.agent/memory/feedback/mnsnn5x2-sxcihd.md +9 -0
  62. package/.agent/memory/feedback/mnsnq17s-nabrn9.md +9 -0
  63. package/.agent/memory/feedback/mnsnybet-wz7rn3.md +9 -0
  64. package/.agent/memory/feedback/mnsrw0s7-7s9e30.md +9 -0
  65. package/.agent/memory/feedback/mnu5hpnd-tlm16q.md +9 -0
  66. package/.agent/memory/feedback/mnu60uqe-xuoxp4.md +9 -0
  67. package/.agent/memory/project/mnqx54u5-loqtoe.md +9 -0
  68. package/.agent/memory/project/mnqx84cv-mx6dmd.md +9 -0
  69. package/.agent/memory/project/mnsacuyr-hgtk5n.md +20 -0
  70. package/.agent/memory/project/mnu5hy2x-bjsg7u.md +9 -0
  71. package/.agent/memory/reference/mnre3cww-penbo1.md +9 -0
  72. package/.agent/memory/reference/mns9wn48-luerua.md +14 -0
  73. package/.agent/memory/reference/mns9yz5c-thc2s0.md +16 -0
  74. package/.agent/memory/reference/mnsfy4um-910f1o.md +23 -0
  75. package/.agent/memory/reference/mnsg37dp-lmfj18.md +32 -0
  76. package/.agent/memory/reference/mnsll60q-0j911u.md +36 -0
  77. package/.agent/memory/reference/mnsmlb5y-nej31u.md +16 -0
  78. package/.agent/memory/reference/mnssle72-yrot96.md +9 -0
  79. package/.agent/memory/user/mnsfuon6-l416q1.md +21 -0
  80. package/.agent/memory/user/mnsg9kut-95m7rf.md +20 -0
  81. package/.agent/memory/user/mnu2eo1v-yy6fhe.md +9 -0
  82. package/.agent/memory/user/mnu2etuo-8u8jk8.md +9 -0
  83. package/.agent/plugins/poster-plugin/fonts/NotoColorEmoji-Regular.ttf +0 -0
  84. package/.agent/plugins/poster-plugin/fonts/Symbola_hint.ttf +0 -0
  85. package/.agent/plugins/poster-plugin/package.json +3 -3
  86. package/.agent/plugins/poster-plugin/src/canvas.js +8 -0
  87. package/.agent/plugins/poster-plugin/src/components/barcode.js +5 -2
  88. package/.agent/plugins/poster-plugin/src/components/bubble.js +3 -2
  89. package/.agent/plugins/poster-plugin/src/components/button.js +74 -30
  90. package/.agent/plugins/poster-plugin/src/components/columns.js +97 -83
  91. package/.agent/plugins/poster-plugin/src/components/grid.js +104 -92
  92. package/.agent/plugins/poster-plugin/src/components/highlightText.js +2 -1
  93. package/.agent/plugins/poster-plugin/src/components/imageFrame.js +143 -93
  94. package/.agent/plugins/poster-plugin/src/components/quote.js +85 -13
  95. package/.agent/plugins/poster-plugin/src/components/ribbon.js +13 -9
  96. package/.agent/plugins/poster-plugin/src/components/seal.js +5 -3
  97. package/.agent/plugins/poster-plugin/src/components/star.js +3 -3
  98. package/.agent/plugins/poster-plugin/src/components/table.js +1 -1
  99. package/.agent/plugins/poster-plugin/src/components/watermark.js +4 -2
  100. package/.agent/plugins/poster-plugin/src/composer.js +181 -13
  101. package/.agent/plugins/poster-plugin/src/elements/artText.js +16 -7
  102. package/.agent/plugins/poster-plugin/src/elements/background.js +20 -5
  103. package/.agent/plugins/poster-plugin/src/elements/richText.js +160 -107
  104. package/.agent/plugins/poster-plugin/src/elements/text.js +48 -45
  105. package/.agent/plugins/poster-plugin/src/fonts.js +556 -125
  106. package/.agent/plugins/poster-plugin/src/index.js +46 -1
  107. package/.agent/plugins/poster-plugin/yarn.lock +186 -356
  108. package/.agent/plugins/puppeteer-plugin/README.md +147 -0
  109. package/.agent/plugins/puppeteer-plugin/index.js +1422 -0
  110. package/.agent/plugins/puppeteer-plugin/package.json +9 -0
  111. package/.agent/plugins.json +5 -11
  112. package/.agent/rules/GEMINI.md +273 -0
  113. package/.agent/rules/allow-rule.md +77 -0
  114. package/.agent/rules/log-rule.md +83 -0
  115. package/.agent/rules/security-rule.md +93 -0
  116. package/.agent/scripts/auto_preview.py +148 -0
  117. package/.agent/scripts/checklist.py +217 -0
  118. package/.agent/scripts/session_manager.py +120 -0
  119. package/.agent/scripts/verify_all.py +327 -0
  120. package/.agent/sessions/cli_default.json +128 -5479
  121. package/.agent/skills/api-patterns/SKILL.md +81 -0
  122. package/.agent/skills/api-patterns/api-style.md +42 -0
  123. package/.agent/skills/api-patterns/auth.md +24 -0
  124. package/.agent/skills/api-patterns/documentation.md +26 -0
  125. package/.agent/skills/api-patterns/graphql.md +41 -0
  126. package/.agent/skills/api-patterns/rate-limiting.md +31 -0
  127. package/.agent/skills/api-patterns/response.md +37 -0
  128. package/.agent/skills/api-patterns/rest.md +40 -0
  129. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  130. package/.agent/skills/api-patterns/security-testing.md +122 -0
  131. package/.agent/skills/api-patterns/trpc.md +41 -0
  132. package/.agent/skills/api-patterns/versioning.md +22 -0
  133. package/.agent/skills/app-builder/SKILL.md +75 -0
  134. package/.agent/skills/app-builder/agent-coordination.md +71 -0
  135. package/.agent/skills/app-builder/feature-building.md +53 -0
  136. package/.agent/skills/app-builder/project-detection.md +34 -0
  137. package/.agent/skills/app-builder/scaffolding.md +118 -0
  138. package/.agent/skills/app-builder/tech-stack.md +40 -0
  139. package/.agent/skills/app-builder/templates/SKILL.md +39 -0
  140. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  141. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  142. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  143. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  144. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  145. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  146. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  147. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  148. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  149. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  150. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  151. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  152. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  153. package/.agent/skills/architecture/SKILL.md +55 -0
  154. package/.agent/skills/architecture/context-discovery.md +43 -0
  155. package/.agent/skills/architecture/examples.md +94 -0
  156. package/.agent/skills/architecture/pattern-selection.md +68 -0
  157. package/.agent/skills/architecture/patterns-reference.md +50 -0
  158. package/.agent/skills/architecture/trade-off-analysis.md +77 -0
  159. package/.agent/skills/clean-code/SKILL.md +201 -0
  160. package/.agent/skills/doc.md +177 -0
  161. package/.agent/skills/frontend-design/SKILL.md +418 -0
  162. package/.agent/skills/frontend-design/animation-guide.md +331 -0
  163. package/.agent/skills/frontend-design/color-system.md +311 -0
  164. package/.agent/skills/frontend-design/decision-trees.md +418 -0
  165. package/.agent/skills/frontend-design/motion-graphics.md +306 -0
  166. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  167. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  168. package/.agent/skills/frontend-design/typography-system.md +345 -0
  169. package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  170. package/.agent/skills/frontend-design/visual-effects.md +383 -0
  171. package/.agent/skills/i18n-localization/SKILL.md +154 -0
  172. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  173. package/.agent/skills/mcp-builder/SKILL.md +176 -0
  174. package/.agent/skills/poster-design/SKILL.md +385 -0
  175. package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  176. package/.agent/workflows/brainstorm.md +113 -0
  177. package/.agent/workflows/create.md +59 -0
  178. package/.agent/workflows/debug.md +103 -0
  179. package/.agent/workflows/deploy.md +176 -0
  180. package/.agent/workflows/enhance.md +63 -0
  181. package/.agent/workflows/orchestrate.md +237 -0
  182. package/.agent/workflows/plan.md +89 -0
  183. package/.agent/workflows/preview.md +81 -0
  184. package/.agent/workflows/simple-test.md +42 -0
  185. package/.agent/workflows/status.md +86 -0
  186. package/.agent/workflows/structured-orchestrate.md +180 -0
  187. package/.agent/workflows/test.md +144 -0
  188. package/.agent/workflows/ui-ux-pro-max.md +296 -0
  189. package/.env.example +56 -56
  190. package/README.md +441 -441
  191. package/SPEC.md +735 -696
  192. package/output/foliko-poster.png +0 -0
  193. package/outputs/emoji-font-showcase.png +0 -0
  194. package/outputs/foliko-muji-style.png +0 -0
  195. package/package.json +3 -2
  196. package/plugins/ambient-agent/EventWatcher.js +33 -37
  197. package/plugins/ambient-agent/ExplorerLoop.js +338 -36
  198. package/plugins/ambient-agent/GoalManager.js +7 -3
  199. package/plugins/ambient-agent/StateStore.js +30 -1
  200. package/plugins/ambient-agent/constants.js +15 -1
  201. package/plugins/ambient-agent/index.js +26 -33
  202. package/plugins/coordinator-plugin.js +3 -3
  203. package/plugins/default-plugins.js +4 -3
  204. package/plugins/email/index.js +150 -36
  205. package/plugins/email/monitor.js +79 -5
  206. package/plugins/email/reply.js +15 -25
  207. package/plugins/extension-executor-plugin.js +184 -32
  208. package/plugins/feishu-plugin.js +2 -2
  209. package/plugins/file-system-plugin.js +57 -24
  210. package/plugins/memory-plugin.js +176 -64
  211. package/plugins/python-plugin-loader.js +79 -9
  212. package/plugins/scheduler-plugin.js +64 -24
  213. package/plugins/telegram-plugin.js +2 -2
  214. package/plugins/think-plugin.js +7 -2
  215. package/plugins/web-plugin.js +263 -4
  216. package/plugins/weixin-plugin.js +2 -2
  217. package/skills/ambient-agent/SKILL.md +342 -314
  218. package/skills/find-skills/AGENTS.md +162 -162
  219. package/skills/find-skills/SKILL.md +133 -133
  220. package/src/core/agent-chat.js +64 -9
  221. package/src/core/agent.js +216 -69
  222. package/src/core/tool-registry.js +5 -5
  223. package/src/executors/mcp-executor.js +453 -35
  224. package/src/utils/id.js +5 -0
  225. package/system.md +3629 -0
  226. package/.agent/agents/code-assistant.json +0 -17
  227. package/.agent/agents/email-assistant.json +0 -14
  228. package/.agent/agents/file-assistant.json +0 -18
  229. package/.agent/agents/orchestrator-demo.md +0 -53
  230. package/.agent/agents/orchestrator.json +0 -7
  231. package/.agent/agents/system-assistant.json +0 -15
  232. package/.agent/agents/web-assistant.json +0 -12
  233. package/.agent/data/ambient/goals.json +0 -50
  234. package/.agent/data/ambient/memories.json +0 -7
  235. package/.agent/data/scheduler/tasks.json +0 -1
  236. package/.agent/memory/core.md +0 -1
  237. package/.agent/memory/feedback/mnrsiuoc-e1ru74.md +0 -9
  238. package/.agent/memory/feedback/mnrt2mmz-98az6n.md +0 -9
  239. package/.agent/memory/feedback/mnrtqrhm-kxsicz.md +0 -9
  240. package/.agent/memory/feedback/mnrts8vg-i0ngzp.md +0 -15
  241. package/.agent/memory/feedback/mnrtt7jt-c0trb2.md +0 -9
  242. package/.agent/memory/feedback/mnruc2f0-5s52la.md +0 -16
  243. package/.agent/memory/feedback/mnrumbmx-63sa0v.md +0 -9
  244. package/.agent/memory/project/mnn93ogy-ypjn27.md +0 -9
  245. package/.agent/memory/project/mnn98fqy-5nhc1u.md +0 -25
  246. package/.agent/memory/project/mnrp7p5n-8enm2a.md +0 -31
  247. package/.agent/memory/project/mnrp9ifb-yynks0.md +0 -40
  248. package/.agent/memory/project/mnrpb3b8-f617s4.md +0 -25
  249. package/.agent/memory/project/mnrrmqgg-focprv.md +0 -9
  250. package/.agent/memory/project/mnrtykbh-6atsor.md +0 -9
  251. package/.agent/memory/project/mnru9jiu-kgau16.md +0 -35
  252. package/.agent/memory/reference/mnq3oenw-46haj6.md +0 -63
  253. package/.agent/memory/reference/mnq5qxm2-mjoooh.md +0 -116
  254. package/.agent/memory/reference/mnrnvpwo-rcqv9m.md +0 -52
  255. package/.agent/memory/reference/mnrovxvz-zy9xqm.md +0 -25
  256. package/.agent/memory/reference/mnroxabj-1b3930.md +0 -68
  257. package/.agent/memory/reference/mnrpjtlp-mnb9od.md +0 -35
  258. package/.agent/memory/reference/mnrps1x3-6b8xfm.md +0 -28
  259. package/.agent/memory/reference/mnrpt9ov-15er5w.md +0 -22
  260. package/.agent/memory/reference/mnrq82dn-y9tv9e.md +0 -50
  261. package/.agent/memory/reference/mnrqnr5v-v75drf.md +0 -34
  262. package/.agent/memory/reference/mnrrfzys-urudaf.md +0 -31
  263. package/.agent/memory/reference/mnrrocha-t0027n.md +0 -21
  264. package/.agent/memory/reference/mnrukklc-bxndsb.md +0 -35
  265. package/.agent/memory/user/mnm67t9m-x8rekk.md +0 -9
  266. package/.agent/memory/user/mnn5mmqh-w6aktx.md +0 -11
  267. package/.agent/memory/user/mnnbfhhn-dk1bd1.md +0 -22
  268. package/.agent/memory/user/mnrt39t8-8eosy0.md +0 -9
  269. package/.agent/package.json +0 -8
  270. package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
  271. package/.agent/plugins/daytona/README.md +0 -89
  272. package/.agent/plugins/daytona/index.js +0 -377
  273. package/.agent/plugins/daytona/package.json +0 -12
  274. package/.agent/plugins/marknative/README.md +0 -134
  275. package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
  276. package/.agent/plugins/marknative/fonts.zip +0 -0
  277. package/.agent/plugins/marknative/index.js +0 -256
  278. package/.agent/plugins/marknative/package.json +0 -12
  279. package/.agent/plugins/poster-plugin/emojis/rocket.png +0 -1
  280. package/.agent/plugins/poster-plugin/test-background.svg +0 -1
  281. package/.agent/plugins/poster-plugin/test-full-poster.svg +0 -2
  282. package/.agent/plugins/poster-plugin/test-image.png +0 -0
  283. package/.agent/plugins/system-info/index.js +0 -387
  284. package/.agent/plugins/system-info/package.json +0 -4
  285. package/.agent/plugins/system-info/test.js +0 -40
  286. package/.agent/python-scripts/test_sample.py +0 -24
  287. package/.agent/skills/agent-browser/SKILL.md +0 -311
  288. package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
  289. package/.agent/skills/sysinfo/SKILL.md +0 -38
  290. package/.agent/skills/sysinfo/system-info.sh +0 -130
  291. package/.agent/skills/workflow/SKILL.md +0 -324
  292. package/.agent/test-agent.js +0 -35
  293. package/.agent/weixin.json +0 -6
  294. package/.agent/workflows/email-digest.json +0 -50
  295. package/.agent/workflows/file-backup.json +0 -21
  296. package/.agent/workflows/get-ip-notify.json +0 -32
  297. package/.agent/workflows/news-aggregator.json +0 -93
  298. package/.agent/workflows/news-dashboard-v2.json +0 -94
  299. package/.agent/workflows/notification-batch.json +0 -32
  300. package/foliko-cloud-rising.png +0 -0
  301. package/foliko-dawn-of-ai.png +0 -0
  302. package/foliko-mindful-observation.png +0 -0
  303. package/foliko-stellar-dreams.png +0 -0
  304. package/foliko-zen-jing.png +0 -0
  305. package/foliko-zen-kong.png +0 -0
  306. package/foliko-zen-wu.png +0 -0
  307. package/zen_karesansui.png +0 -0
@@ -10,7 +10,7 @@ const path = require('path');
10
10
  const { z } = require('zod');
11
11
  const { createMCPClient } = require('@ai-sdk/mcp');
12
12
  const { StdioClientTransport } = require('@modelcontextprotocol/sdk/client/stdio.js');
13
- const { zodSchemaToTable } = require('@chnak/zod-to-markdown');
13
+ const { zodSchemaToMarkdown } = require('@chnak/zod-to-markdown');
14
14
  const { logger } = require('../utils/logger');
15
15
 
16
16
  const log = logger.child('MCPExecutor');
@@ -193,7 +193,7 @@ class MCPClientWrapper {
193
193
  class MCPExecutorPlugin extends Plugin {
194
194
  constructor(config = {}) {
195
195
  super();
196
- this.name = 'mcp-executor';
196
+ this.name = 'mcp';
197
197
  this.version = '1.0.0';
198
198
  this.description = 'MCP (Model Context Protocol) 执行器';
199
199
  this.priority = 11;
@@ -202,7 +202,12 @@ class MCPExecutorPlugin extends Plugin {
202
202
  this._framework = null;
203
203
  // serverName -> { client, tools: [{ name, description, inputSchema }], toolObjects: { toolName: actualTool } }
204
204
  this._clients = new Map();
205
+ // 保存服务器配置,用于重新启用
206
+ this._serverConfigs = new Map();
205
207
  this._config = config;
208
+ // 注册的工具对象(extension-executor 会扫描这个)
209
+ // 格式: { 'server_toolname': { name, description, inputSchema, execute } }
210
+ this.tools = {};
206
211
  }
207
212
 
208
213
  install(framework) {
@@ -214,6 +219,12 @@ class MCPExecutorPlugin extends Plugin {
214
219
  // 先连接所有 MCP 服务器
215
220
  if (this._config.servers) {
216
221
  for (const serverConfig of this._config.servers) {
222
+ if (serverConfig.enabled === false) {
223
+ log.info(` Skipping disabled server: ${serverConfig.name}`);
224
+ // 保存完整配置,以便后续动态启用
225
+ this._serverConfigs.set(serverConfig.name, { ...serverConfig });
226
+ continue;
227
+ }
217
228
  await this.addServer(serverConfig);
218
229
  }
219
230
  }
@@ -406,12 +417,26 @@ class MCPExecutorPlugin extends Plugin {
406
417
  inputSchema: z.object({}),
407
418
  execute: async () => {
408
419
  const servers = [];
420
+ // 已连接的服务器
409
421
  for (const [name, info] of this._clients) {
410
422
  servers.push({
411
423
  name,
424
+ enabled: true,
425
+ connected: true,
412
426
  tools: info.tools.map((t) => ({ name: t.name, description: t.description })),
413
427
  });
414
428
  }
429
+ // 未连接的服务器(配置中存在但未启用)
430
+ for (const [name, config] of this._serverConfigs) {
431
+ if (!this._clients.has(name)) {
432
+ servers.push({
433
+ name,
434
+ enabled: false,
435
+ connected: false,
436
+ tools: [],
437
+ });
438
+ }
439
+ }
415
440
  return { success: true, servers };
416
441
  },
417
442
  });
@@ -453,6 +478,77 @@ class MCPExecutorPlugin extends Plugin {
453
478
  },
454
479
  });
455
480
 
481
+ // 注册 mcp_set_enabled 工具 - 动态开启/关闭 MCP 服务器
482
+ framework.registerTool({
483
+ name: 'mcp_set_enabled',
484
+ description: '动态开启或关闭某个 MCP 服务器',
485
+ inputSchema: z.object({
486
+ server: z.string().describe('MCP 服务器名称'),
487
+ enabled: z.boolean().describe('true=开启,false=关闭'),
488
+ }),
489
+ execute: async (args) => {
490
+ const { server, enabled } = args;
491
+ const clientInfo = this._clients.get(server);
492
+ const serverConfig = this._serverConfigs.get(server);
493
+
494
+ if (enabled) {
495
+ // 启用服务器
496
+ if (clientInfo && clientInfo.enabled) {
497
+ return { success: true, message: `MCP 服务器 '${server}' 已经是开启状态` };
498
+ }
499
+ // 如果服务器从未连接过,也检查配置中的 enabled 状态
500
+ if (!clientInfo && serverConfig && serverConfig.enabled === false) {
501
+ // 服务器是被禁用的,可以尝试启用
502
+ }
503
+ log.info(
504
+ `[MCP] Enabling server: ${server}, clientInfo=${!!clientInfo}, serverConfig.enabled=${serverConfig?.enabled}`
505
+ );
506
+ try {
507
+ if (serverConfig) {
508
+ const result = await this.addServer({ ...serverConfig, enabled: true });
509
+ log.info(`[MCP] addServer result:`, JSON.stringify(result));
510
+ if (!result || result.success === false) {
511
+ this._refreshAllAgentsMCPPrompt(this._framework);
512
+ return result;
513
+ }
514
+ // 保存 enabled 状态到配置文件
515
+ await this._saveMCPServerEnabled(server, true);
516
+ this._refreshAllAgentsMCPPrompt(this._framework);
517
+ return { success: true, message: `MCP 服务器 '${server}' 已开启` };
518
+ } else {
519
+ return { success: false, error: '服务器配置不存在,需要重载配置' };
520
+ }
521
+ } catch (err) {
522
+ log.error(`[MCP] Enabling failed:`, err.message);
523
+ return { success: false, error: `开启失败: ${err.message}` };
524
+ }
525
+ } else {
526
+ // 禁用服务器
527
+ if (!clientInfo) {
528
+ return { success: false, error: `MCP server '${server}' not found` };
529
+ }
530
+ log.info(` Disabling MCP server: ${server}`);
531
+ try {
532
+ clientInfo.client.close?.();
533
+ } catch (e) {}
534
+ // 从 clients 中移除
535
+ this._clients.delete(server);
536
+ // 移除该服务器注册的工具
537
+ for (const key of Object.keys(this.tools)) {
538
+ if (key.startsWith(`${server}_`)) {
539
+ delete this.tools[key];
540
+ }
541
+ }
542
+ // 保存 enabled 状态到配置文件
543
+ await this._saveMCPServerEnabled(server, false);
544
+ this._refreshAllAgentsMCPPrompt(this._framework);
545
+ return { success: true, message: `MCP 服务器 '${server}' 已关闭` };
546
+ }
547
+
548
+ return { success: true, message: `MCP 服务器 '${server}' 状态未变化` };
549
+ },
550
+ });
551
+
456
552
  // 监听 agent 创建事件,附加 MCP 信息到系统提示词
457
553
  framework.on('agent:created', (agent) => {
458
554
  if (!this._mainAgent) {
@@ -482,7 +578,7 @@ class MCPExecutorPlugin extends Plugin {
482
578
  const traverse = (agent) => {
483
579
  if (!agent || visited.has(agent)) return;
484
580
  visited.add(agent);
485
- this._refreshAgentMCPPrompt(agent);
581
+ //this._refreshAgentMCPPrompt(agent);
486
582
 
487
583
  // 递归处理子 agent
488
584
  const subAgents = agent.getSubAgents?.() || agent._subAgents || new Map();
@@ -506,11 +602,11 @@ class MCPExecutorPlugin extends Plugin {
506
602
  return;
507
603
  }
508
604
 
509
- const mcpDesc = this._buildMCPServersDescription();
510
- if (!mcpDesc) return;
605
+ // const mcpDesc = this._buildMCPServersDescription();
606
+ // if (!mcpDesc) return;
511
607
 
512
608
  // 将 MCP 描述追加到系统提示词
513
- agent.setSystemPrompt(existingPrompt + '\n\n' + mcpDesc);
609
+ //agent.setSystemPrompt(existingPrompt + '\n\n' + mcpDesc);
514
610
  }
515
611
 
516
612
  /**
@@ -520,6 +616,8 @@ class MCPExecutorPlugin extends Plugin {
520
616
  if (!inputSchema) return {};
521
617
  // 处理 {jsonSchema: {...}} 格式
522
618
  if (inputSchema.jsonSchema) return inputSchema.jsonSchema;
619
+ // 处理 {inputSchema: {...}} 格式 (某些 MCP 服务器返回这种格式)
620
+ if (inputSchema.inputSchema) return inputSchema.inputSchema;
523
621
  // 处理直接是 schema 的格式
524
622
  return inputSchema;
525
623
  }
@@ -532,53 +630,134 @@ class MCPExecutorPlugin extends Plugin {
532
630
  return '';
533
631
  }
534
632
 
535
- let desc = '【MCP Servers】 工具合集\n\n';
536
- desc += '你可以通过 `mcp_call` 工具调用以下 MCP 服务器的工具。\n\n';
633
+ let desc = '## 【MCP Servers】 工具合集\n\n';
634
+ desc += 'MCP 服务器工具已注册为 `服务器_工具名` 格式(如 github_search)。\n';
635
+ desc += '通过 `ext_call` 调用:\n\n';
537
636
 
538
637
  for (const [serverName, info] of this._clients) {
539
638
  desc += `### ${serverName}\n\n`;
540
639
  for (const tool of info.tools) {
541
- desc += `#### ${tool.name}\n`;
542
- desc += `${tool.description || '无描述'}\n\n`;
640
+ const fullName = `${serverName}_${tool.name}`;
641
+ desc += `- **${fullName}**: ${tool.description || '无描述'}\n`;
543
642
 
544
643
  // 使用 zodSchemaToMarkdown 生成参数文档
545
- const schema = tool.inputSchema;
644
+ const rawSchema = tool.inputSchema;
645
+ const schema = this._extractSchema(rawSchema);
546
646
  if (schema) {
547
647
  try {
548
- if (typeof schema.toJSON === 'function') {
648
+ let schemaResult = null;
649
+ let zodSchemaForFallback = null; // 保存 Zod schema 供 fallback 使用
650
+ // 检查是否是 Zod schema (有 shape 方法或 _def 属性)
651
+ const isZodSchema =
652
+ typeof schema.shape === 'function' || (schema._def && schema._def.typeName);
653
+ if (isZodSchema) {
549
654
  // Zod schema 直接转换
550
- desc += `**参数:**\n\n`;
551
- desc += zodSchemaToTable(schema) + '\n\n';
655
+ schemaResult = zodSchemaToMarkdown(schema);
656
+ zodSchemaForFallback = schema;
552
657
  } else if (schema.jsonSchema) {
553
658
  // JSON Schema 格式,尝试转换为 Zod schema
554
659
  const zodSchema = this._jsonSchemaToZod(schema.jsonSchema || schema);
555
660
  if (zodSchema) {
556
- desc += `**参数:**\n\n`;
557
- desc += zodSchemaToTable(zodSchema) + '\n\n';
661
+ schemaResult = zodSchemaToMarkdown(zodSchema);
662
+ zodSchemaForFallback = zodSchema;
558
663
  }
559
664
  } else if (schema.properties) {
560
665
  // 已经是对象格式
561
666
  const zodSchema = this._jsonSchemaToZod(schema);
562
667
  if (zodSchema) {
668
+ schemaResult = zodSchemaToMarkdown(zodSchema);
669
+ zodSchemaForFallback = zodSchema;
670
+ }
671
+ }
672
+
673
+ // 检查是否包含未解析的原始 Zod 类型名或只有类型信息没有参数
674
+ if (schemaResult) {
675
+ const hasUnparsedTypes = /\|.*\bZod\w+\b.*\|/.test(schemaResult);
676
+ // 检查是否只有类型信息而没有实际参数(如 "Type: Object" 或 "Type: ZodAny")
677
+ const hasOnlyType =
678
+ /^-\s+\w+:\s+.+\n?$/.test(schemaResult.trim()) && !schemaResult.includes('`');
679
+ if (hasUnparsedTypes || hasOnlyType) {
680
+ // zodSchemaToMarkdown 未正确解析,使用 fallback
681
+ desc += this._fallbackParamsDesc(zodSchemaForFallback || schema);
682
+ } else {
563
683
  desc += `**参数:**\n\n`;
564
- desc += zodSchemaToTable(zodSchema) + '\n\n';
684
+ desc += schemaResult + '\n\n';
565
685
  }
566
686
  }
567
687
  } catch (e) {
568
- // 如果转换失败,使用简化格式
569
- desc += this._fallbackParamsDesc(schema);
688
+ // 如果转换失败,使用 fallback
689
+ try {
690
+ desc += this._fallbackParamsDesc(zodSchemaForFallback || schema);
691
+ } catch (e2) {
692
+ // fallback 也失败,忽略参数描述
693
+ }
570
694
  }
571
695
  }
572
696
  }
573
- desc += '---\n\n';
697
+ desc += '\n';
574
698
  }
575
699
 
576
700
  desc += '**调用格式:**\n';
577
- desc += '```\nmcp_call({ server: "服务器", tool: "工具", args_json: \'{"参数": "值"}\' })\n';
701
+ desc += '```\next_call({ plugin: "mcp", tool: "服务器_工具名", args: {参数} })\n';
578
702
  desc += '```\n';
579
703
  return desc.trim();
580
704
  }
581
705
 
706
+ _bindMcpParamsDesc(rawSchema) {
707
+ let desc = '';
708
+ const schema = this._extractSchema(rawSchema);
709
+ if (!schema) return desc;
710
+ try {
711
+ let schemaResult = null;
712
+ let zodSchemaForFallback = null; // 保存 Zod schema 供 fallback 使用
713
+ // 检查是否是 Zod schema (有 shape 方法或 _def 属性)
714
+ const isZodSchema =
715
+ typeof schema.shape === 'function' || (schema._def && schema._def.typeName);
716
+ if (isZodSchema) {
717
+ // Zod schema 直接转换
718
+ schemaResult = zodSchemaToMarkdown(schema);
719
+ zodSchemaForFallback = schema;
720
+ } else if (schema.jsonSchema) {
721
+ // JSON Schema 格式,尝试转换为 Zod schema
722
+ const zodSchema = this._jsonSchemaToZod(schema.jsonSchema || schema);
723
+ if (zodSchema) {
724
+ schemaResult = zodSchemaToMarkdown(zodSchema);
725
+ zodSchemaForFallback = zodSchema;
726
+ }
727
+ } else if (schema.properties) {
728
+ // 已经是对象格式
729
+ const zodSchema = this._jsonSchemaToZod(schema);
730
+ if (zodSchema) {
731
+ schemaResult = zodSchemaToMarkdown(zodSchema);
732
+ zodSchemaForFallback = zodSchema;
733
+ }
734
+ }
735
+
736
+ // 检查是否包含未解析的原始 Zod 类型名或只有类型信息没有参数
737
+ if (schemaResult) {
738
+ const hasUnparsedTypes = /\|.*\bZod\w+\b.*\|/.test(schemaResult);
739
+ // 检查是否只有类型信息而没有实际参数(如 "Type: Object" 或 "Type: ZodAny")
740
+ const hasOnlyType =
741
+ /^-\s+\w+:\s+.+\n?$/.test(schemaResult.trim()) && !schemaResult.includes('`');
742
+ if (hasUnparsedTypes || hasOnlyType) {
743
+ // zodSchemaToMarkdown 未正确解析,使用 fallback
744
+ desc += this._fallbackParamsDesc(zodSchemaForFallback || schema);
745
+ } else {
746
+ desc += `**参数:**\n\n`;
747
+ desc += schemaResult + '\n\n';
748
+ }
749
+ }
750
+ } catch (e) {
751
+ // 如果转换失败,使用 fallback
752
+ try {
753
+ desc += this._fallbackParamsDesc(zodSchemaForFallback || schema);
754
+ } catch (e2) {
755
+ // fallback 也失败,忽略参数描述
756
+ }
757
+ }
758
+ return desc;
759
+ }
760
+
582
761
  /**
583
762
  * 将 JSON Schema 转换为 Zod schema
584
763
  */
@@ -648,21 +827,152 @@ class MCPExecutorPlugin extends Plugin {
648
827
  * 回退的参数描述(当 zodSchemaToMarkdown 失败时)
649
828
  */
650
829
  _fallbackParamsDesc(schema) {
830
+ // 优先尝试 JSON Schema 格式
651
831
  const props = schema.properties || {};
652
832
  const required = schema.required || [];
653
833
 
654
- if (Object.keys(props).length === 0) {
655
- return '';
834
+ if (Object.keys(props).length > 0) {
835
+ let desc = '**参数:**\n\n';
836
+ for (const [key, prop] of Object.entries(props)) {
837
+ const isRequired = required.includes(key);
838
+ const type = prop.type || 'any';
839
+ const desc_text = prop.description || '';
840
+ desc += `- \`${key}\`${isRequired ? ' (必填)' : ''}: ${type} ${desc_text}\n`;
841
+ }
842
+ return desc + '\n';
843
+ }
844
+
845
+ // 尝试 Zod schema 格式
846
+ if (typeof schema.shape === 'function' || (schema._def && schema._def.shape)) {
847
+ const shape = typeof schema.shape === 'function' ? schema.shape() : schema._def.shape();
848
+ if (shape && typeof shape === 'object') {
849
+ let desc = '**参数:**\n\n';
850
+ for (const [key, field] of Object.entries(shape)) {
851
+ const typeInfo = this._extractZodFieldType(field);
852
+ const isOptional = typeInfo.isOptional ? ' (可选)' : ' (必填)';
853
+ desc += `- \`${key}\`${isOptional}: ${typeInfo.type}\n`;
854
+ }
855
+ return desc + '\n';
856
+ }
857
+ }
858
+
859
+ return '';
860
+ }
861
+
862
+ /**
863
+ * 从 Zod schema 字段提取类型信息
864
+ */
865
+ _extractZodFieldType(field) {
866
+ if (!field) {
867
+ return { type: 'unknown', isOptional: false, description: '' };
656
868
  }
657
869
 
658
- let desc = '**参数:**\n\n';
659
- for (const [key, prop] of Object.entries(props)) {
660
- const isRequired = required.includes(key);
661
- const type = prop.type || 'any';
662
- const desc_text = prop.description || '';
663
- desc += `- \`${key}\`${isRequired ? ' (必填)' : ''}: ${type} ${desc_text}\n`;
870
+ const typeName = field._def?.typeName || field.constructor?.name || '';
871
+ const description = field.description || field._def?.description || '';
872
+
873
+ switch (typeName) {
874
+ case 'ZodOptional': {
875
+ const inner = field._def?.innerType;
876
+ if (!inner) return { type: 'optional', isOptional: true, description };
877
+ return this._extractZodFieldType(inner);
878
+ }
879
+ case 'ZodArray': {
880
+ const inner = field._def?.type;
881
+ if (!inner) return { type: 'array', isOptional: false, description };
882
+ const innerInfo = this._extractZodFieldType(inner);
883
+ return { type: `${innerInfo.type}[]`, isOptional: false, description };
884
+ }
885
+ case 'ZodObject': {
886
+ const shapeFn = field._def?.shape;
887
+ if (typeof shapeFn !== 'function')
888
+ return { type: 'object', isOptional: false, description };
889
+ const shape = shapeFn();
890
+ if (!shape) return { type: 'object', isOptional: false, description };
891
+ const props = Object.keys(shape).join(', ');
892
+ return { type: `object{${props}}`, isOptional: false, description };
893
+ }
894
+ case 'ZodString':
895
+ return { type: 'string', isOptional: false, description };
896
+ case 'ZodNumber':
897
+ return { type: 'number', isOptional: false, description };
898
+ case 'ZodBoolean':
899
+ return { type: 'boolean', isOptional: false, description };
900
+ case 'ZodEnum': {
901
+ const values = field._def?.values;
902
+ if (!values) return { type: 'enum', isOptional: false, description };
903
+ return {
904
+ type: values.map((v) => `"${v}"`).join(' | '),
905
+ isOptional: false,
906
+ description,
907
+ };
908
+ }
909
+ case 'ZodUnion': {
910
+ const options = field._def?.options;
911
+ if (!options) return { type: 'union', isOptional: false, description };
912
+ const types = options.map((opt) => this._extractZodFieldType(opt).type);
913
+ return { type: `union(${types.join(' | ')})`, isOptional: false, description };
914
+ }
915
+ case 'ZodLiteral':
916
+ return { type: JSON.stringify(field._def?.value), isOptional: false, description };
917
+ case 'ZodRecord': {
918
+ const keyType = this._extractZodFieldType(field._def?.keyType);
919
+ const valueType = this._extractZodFieldType(field._def?.valueType);
920
+ return {
921
+ type: `record<${keyType?.type || 'any'}, ${valueType?.type || 'any'}>`,
922
+ isOptional: false,
923
+ description,
924
+ };
925
+ }
926
+ case 'ZodMap': {
927
+ const keyType = this._extractZodFieldType(field._def?.keyType);
928
+ const valueType = this._extractZodFieldType(field._def?.valueType);
929
+ return {
930
+ type: `map<${keyType?.type || 'any'}, ${valueType?.type || 'any'}>`,
931
+ isOptional: false,
932
+ description,
933
+ };
934
+ }
935
+ case 'ZodSet': {
936
+ const valueType = this._extractZodFieldType(field._def?.valueType);
937
+ return { type: `set<${valueType?.type || 'any'}>`, isOptional: false, description };
938
+ }
939
+ case 'ZodAny':
940
+ return { type: 'any', isOptional: false, description };
941
+ case 'ZodUnknown':
942
+ return { type: 'unknown', isOptional: false, description };
943
+ case 'ZodNever':
944
+ return { type: 'never', isOptional: false, description };
945
+ case 'ZodNull':
946
+ return { type: 'null', isOptional: false, description };
947
+ case 'ZodUndefined':
948
+ return { type: 'undefined', isOptional: false, description };
949
+ case 'ZodDate':
950
+ return { type: 'date', isOptional: false, description };
951
+ case 'ZodBigInt':
952
+ return { type: 'bigint', isOptional: false, description };
953
+ case 'ZodFunction':
954
+ return { type: 'function', isOptional: false, description };
955
+ case 'ZodLazy':
956
+ return { type: 'lazy', isOptional: false, description };
957
+ case 'ZodNativeEnum':
958
+ return { type: 'nativeEnum', isOptional: false, description };
959
+ case 'ZodDefault': {
960
+ const inner = field._def?.innerType;
961
+ if (!inner) return { type: 'default', isOptional: false, description };
962
+ const innerInfo = this._extractZodFieldType(inner);
963
+ return { type: innerInfo.type, isOptional: false, description };
964
+ }
965
+ case 'ZodEffects':
966
+ return { type: 'effects', isOptional: false, description };
967
+ case 'ZodPipeline':
968
+ return { type: 'pipeline', isOptional: false, description };
969
+ default:
970
+ return {
971
+ type: typeName.replace('Zod', '').toLowerCase() || 'any',
972
+ isOptional: false,
973
+ description,
974
+ };
664
975
  }
665
- return desc + '\n';
666
976
  }
667
977
 
668
978
  _getParentAgent() {
@@ -703,11 +1013,44 @@ class MCPExecutorPlugin extends Plugin {
703
1013
  * 添加 MCP 服务器
704
1014
  */
705
1015
  async addServer(config) {
706
- const { name, command, args = [], env, url, type, headers = {}, authProvider } = config;
1016
+ const {
1017
+ name,
1018
+ command,
1019
+ args = [],
1020
+ env,
1021
+ url,
1022
+ type,
1023
+ headers = {},
1024
+ authProvider,
1025
+ enabled,
1026
+ } = config;
1027
+ log.info(
1028
+ `[MCP] addServer called: ${name}, enabled=${enabled}, hasClient=${this._clients.has(name)}`
1029
+ );
1030
+
707
1031
  if (this._clients.has(name)) {
708
1032
  log.warn(` Server '${name}' already exists, skipping`);
709
- return;
1033
+ return { success: false, error: `Server '${name}' already connected` };
710
1034
  }
1035
+
1036
+ // 如果 enabled === false,跳过连接(用于 mcp_set_enabled 禁用后再开启的场景)
1037
+ if (enabled === false) {
1038
+ log.info(` Server '${name}' is disabled, skipping connection`);
1039
+ return { success: false, error: `Server '${name}' is disabled` };
1040
+ }
1041
+
1042
+ // 保存配置,用于重新启用
1043
+ this._serverConfigs.set(name, {
1044
+ name,
1045
+ command,
1046
+ args,
1047
+ env,
1048
+ url,
1049
+ type,
1050
+ headers,
1051
+ authProvider,
1052
+ enabled,
1053
+ });
711
1054
  log.info(` Connecting to ${name}...`);
712
1055
  let client;
713
1056
  try {
@@ -741,7 +1084,7 @@ class MCPExecutorPlugin extends Plugin {
741
1084
  }
742
1085
  } catch (err) {
743
1086
  log.error(` Failed to create client '${name}':`, err.message);
744
- return;
1087
+ return { success: false, error: `创建客户端失败: ${err.message}` };
745
1088
  }
746
1089
 
747
1090
  // 获取 MCP 服务器的工具列表
@@ -750,7 +1093,8 @@ class MCPExecutorPlugin extends Plugin {
750
1093
  mcpTools = await this._withTimeout(client.tools(), 10000, `client.tools ${name}`);
751
1094
  } catch (err) {
752
1095
  log.error(` Failed to get tools from '${name}':`, err.message);
753
- return;
1096
+ client.close?.();
1097
+ return { success: false, error: `获取工具列表失败: ${err.message}` };
754
1098
  }
755
1099
 
756
1100
  // 提取工具信息和实际工具对象
@@ -765,6 +1109,22 @@ class MCPExecutorPlugin extends Plugin {
765
1109
  description: tool.description || '',
766
1110
  inputSchema: tool.inputSchema || {},
767
1111
  });
1112
+
1113
+ // 注册为 server_toolname 格式,供 ext_call 使用
1114
+ const registeredName = `${name}_${toolName}`;
1115
+ this.tools[registeredName] = {
1116
+ name: registeredName,
1117
+ description: `[${name}] ${tool.description || ''}`,
1118
+ inputSchema: tool.inputSchema || {},
1119
+ execute: async (args) => {
1120
+ // 路由到 mcp_call
1121
+ return await this._framework.executeTool('mcp_call', {
1122
+ server: name,
1123
+ tool: toolName,
1124
+ args_json: JSON.stringify(args || {}),
1125
+ });
1126
+ },
1127
+ };
768
1128
  }
769
1129
  }
770
1130
 
@@ -773,9 +1133,18 @@ class MCPExecutorPlugin extends Plugin {
773
1133
  client,
774
1134
  tools: toolsInfo,
775
1135
  toolObjects, // 实际工具对象,供 mcp_call 直接调用
1136
+ enabled: config.enabled !== false,
776
1137
  });
777
1138
 
778
- log.info(` Added server '${name}' with ${toolsInfo.length} tools`);
1139
+ log.info(
1140
+ ` Added server '${name}' with ${toolsInfo.length} tools (ext_call names: ${Object.keys(
1141
+ this.tools
1142
+ )
1143
+ .filter((k) => k.startsWith(name + '_'))
1144
+ .join(', ')})`
1145
+ );
1146
+
1147
+ return { success: true, name, toolsCount: toolsInfo.length };
779
1148
  }
780
1149
 
781
1150
  /**
@@ -796,6 +1165,14 @@ class MCPExecutorPlugin extends Plugin {
796
1165
  } catch (e) {
797
1166
  // ignore
798
1167
  }
1168
+
1169
+ // 清理已注册的工具
1170
+ for (const toolName of Object.keys(this.tools)) {
1171
+ if (toolName.startsWith(name + '_')) {
1172
+ delete this.tools[toolName];
1173
+ }
1174
+ }
1175
+
799
1176
  this._clients.delete(name);
800
1177
  }
801
1178
  }
@@ -832,10 +1209,18 @@ class MCPExecutorPlugin extends Plugin {
832
1209
  } catch (e) {}
833
1210
  }
834
1211
  this._clients.clear();
1212
+ // 清理服务器配置
1213
+ this._serverConfigs.clear();
835
1214
 
836
1215
  // 2. 并行添加新服务器
837
1216
  log.info(' Adding new servers...');
838
1217
  const addPromises = Object.entries(newServers).map(async ([name, serverConfig]) => {
1218
+ if (serverConfig.enabled === false) {
1219
+ log.info(` Skipping disabled server: ${name}`);
1220
+ // 仍保存配置,以便后续动态启用
1221
+ this._serverConfigs.set(name, { name, ...serverConfig });
1222
+ return;
1223
+ }
839
1224
  const normalizedConfig = {
840
1225
  name,
841
1226
  type: serverConfig.type,
@@ -845,6 +1230,7 @@ class MCPExecutorPlugin extends Plugin {
845
1230
  command: serverConfig.command,
846
1231
  args: serverConfig.args,
847
1232
  env: serverConfig.env,
1233
+ enabled: true,
848
1234
  };
849
1235
  await this.addServer(normalizedConfig);
850
1236
  });
@@ -858,6 +1244,38 @@ class MCPExecutorPlugin extends Plugin {
858
1244
  }
859
1245
  }
860
1246
 
1247
+ /**
1248
+ * 保存 MCP 服务器的 enabled 状态到配置文件
1249
+ */
1250
+ async _saveMCPServerEnabled(serverName, enabled) {
1251
+ const fs = require('fs');
1252
+ const path = require('path');
1253
+ const configPath = path.resolve('.agent/mcp_config.json');
1254
+
1255
+ try {
1256
+ if (!fs.existsSync(configPath)) {
1257
+ log.warn(` MCP config file not found: ${configPath}`);
1258
+ return false;
1259
+ }
1260
+
1261
+ const configContent = fs.readFileSync(configPath, 'utf8');
1262
+ const config = JSON.parse(configContent);
1263
+
1264
+ if (!config.mcpServers || !config.mcpServers[serverName]) {
1265
+ log.warn(` Server '${serverName}' not found in MCP config`);
1266
+ return false;
1267
+ }
1268
+
1269
+ config.mcpServers[serverName].enabled = enabled;
1270
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
1271
+ log.info(` Saved enabled=${enabled} for server '${serverName}' to config`);
1272
+ return true;
1273
+ } catch (err) {
1274
+ log.error(` Failed to save MCP config:`, err.message);
1275
+ return false;
1276
+ }
1277
+ }
1278
+
861
1279
  async uninstall(framework) {
862
1280
  // 断开所有 MCP 连接
863
1281
  for (const [name, clientInfo] of this._clients) {
package/src/utils/id.js CHANGED
@@ -130,4 +130,9 @@ module.exports = {
130
130
  messageId,
131
131
  ruleId,
132
132
  resetSnowflake,
133
+ // 通用 ID 生成器(向后兼容)
134
+ generateId: () => {
135
+ const random = crypto.randomBytes(8).toString('base64url');
136
+ return `id_${Date.now()}_${random}`;
137
+ },
133
138
  };