@runfusion/fusion 0.48.0 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/dist/bin.js +6905 -5790
  2. package/dist/client/.vite/manifest.json +251 -250
  3. package/dist/client/assets/{AgentDetailView-CF6isJ51.js → AgentDetailView-B8_IDafM.js} +1 -1
  4. package/dist/client/assets/AgentDetailView-BzSyldiW.css +1 -0
  5. package/dist/client/assets/{AgentPermissionPolicyEditor-DFldf6aS.js → AgentPermissionPolicyEditor-D4U6puHs.js} +1 -1
  6. package/dist/client/assets/{AgentsView-DiGseTuo.js → AgentsView-CafZRACA.js} +3 -3
  7. package/dist/client/assets/{ChatView-BjQBbDyo.js → ChatView-CZv_hIdK.js} +1 -1
  8. package/dist/client/assets/ChatView-DwIIrJxb.css +1 -0
  9. package/dist/client/assets/CommandCenter-B1P49x__.css +1 -0
  10. package/dist/client/assets/CommandCenter-D9qV7yF_.js +71 -0
  11. package/dist/client/assets/{DevServerView-D6RFaGPU.js → DevServerView-C1qppz4E.js} +1 -1
  12. package/dist/client/assets/{DirectoryPicker-DNBB-viz.js → DirectoryPicker-CW_Q-Bup.js} +1 -1
  13. package/dist/client/assets/{DocumentsView-DXG-sctG.js → DocumentsView-DGxrLknh.js} +1 -1
  14. package/dist/client/assets/{EvalsView-Ol6ECKz5.js → EvalsView-BMU01K7i.js} +1 -1
  15. package/dist/client/assets/{ExperimentalAgentOnboardingModal-BQc3GaE_.js → ExperimentalAgentOnboardingModal-B5Mwwwbz.js} +1 -1
  16. package/dist/client/assets/{GoalsView-C_m90anC.js → GoalsView-B9Vwqp8k.js} +1 -1
  17. package/dist/client/assets/{InsightsView-BbFgPsDH.js → InsightsView-C9fVBn7l.js} +1 -1
  18. package/dist/client/assets/{MemoryView-CRS7AjWK.js → MemoryView-Chm5uzjZ.js} +1 -1
  19. package/dist/client/assets/{PiExtensionsManager-BEj5xu45.js → PiExtensionsManager-BhKzgNHh.js} +1 -1
  20. package/dist/client/assets/{PluginManager-CzCM3XUY.js → PluginManager-pEIpbosd.js} +1 -1
  21. package/dist/client/assets/{PullRequestView-9yNYCunb.js → PullRequestView-DG1gPFRJ.js} +1 -1
  22. package/dist/client/assets/{ResearchView-BKdirpiw.js → ResearchView-wy7oLnPg.js} +1 -1
  23. package/dist/client/assets/{SecretsView-qGjo-0Cp.js → SecretsView-Bid0TP7K.js} +1 -1
  24. package/dist/client/assets/{SessionTerminal-C7YlkdGJ.js → SessionTerminal-B3XCQFRu.js} +1 -1
  25. package/dist/client/assets/{SettingsModal-DihNd7g8.js → SettingsModal-BMpP5CkL.js} +1 -1
  26. package/dist/client/assets/{SettingsModal-CvbiSIHS.css → SettingsModal-BzZNPNIh.css} +1 -1
  27. package/dist/client/assets/SettingsModal-Dptq-qYL.js +21 -0
  28. package/dist/client/assets/SettingsModal-tUDR6nJ9.css +1 -0
  29. package/dist/client/assets/{SetupWizardModal-MovTj5pY.js → SetupWizardModal-C_wMNV3H.js} +2 -2
  30. package/dist/client/assets/{ShadcnColorPicker-Bnf5n5R4.js → ShadcnColorPicker-CXxr3ynz.js} +1 -1
  31. package/dist/client/assets/{ShadcnColorPicker-pqVWCC5-.css → ShadcnColorPicker-CzZo9UOD.css} +1 -1
  32. package/dist/client/assets/SkillsView-Cfs7HkwW.css +1 -0
  33. package/dist/client/assets/SkillsView-DcNtAxQI.js +1 -0
  34. package/dist/client/assets/{TodoView-CIsL_uvQ.css → TodoView--YoVYWvw.css} +1 -1
  35. package/dist/client/assets/{TodoView-BEdk6FTU.js → TodoView-Bt5ZY51H.js} +1 -1
  36. package/dist/client/assets/WorkflowNodeEditor-AwHxfoz1.js +8 -0
  37. package/dist/client/assets/WorkflowNodeEditor-WYIxHTxY.css +1 -0
  38. package/dist/client/assets/{agentSkills-D5nDZPRY.js → agentSkills-DlTZq-3b.js} +1 -1
  39. package/dist/client/assets/{app-S8fehQv8.js → app-B7XunYYI.js} +3 -3
  40. package/dist/client/assets/{app-ChkCVQpq.js → app-BV3tiBJo.js} +3 -3
  41. package/dist/client/assets/{app-DMn7Jt9g.js → app-BgStK3QE.js} +3 -3
  42. package/dist/client/assets/{app-D_IT9Buz.js → app-ChEDGcMv.js} +3 -3
  43. package/dist/client/assets/{app-BglOELbc.js → app-Cl4147h6.js} +3 -3
  44. package/dist/client/assets/app-DH6H4_Pi.js +13 -0
  45. package/dist/client/assets/{architectureDiagram-3BPJPVTR-BbkXWBni.js → architectureDiagram-3BPJPVTR-DPevXfXn.js} +1 -1
  46. package/dist/client/assets/{blockDiagram-GPEHLZMM-DhaqpHqZ.js → blockDiagram-GPEHLZMM-iREXBnwN.js} +1 -1
  47. package/dist/client/assets/{c4Diagram-AAUBKEIU-qC0WSHMZ.js → c4Diagram-AAUBKEIU-Ds4gntrv.js} +1 -1
  48. package/dist/client/assets/channel-FTiNgAnt.js +1 -0
  49. package/dist/client/assets/{chunk-2J33WTMH-Dah9zMeT.js → chunk-2J33WTMH-DI8WjOJS.js} +1 -1
  50. package/dist/client/assets/{chunk-4BX2VUAB-epHwnUb_.js → chunk-4BX2VUAB-BSvj2r_a.js} +1 -1
  51. package/dist/client/assets/{chunk-55IACEB6-DpYBy44g.js → chunk-55IACEB6-DXqk_68P.js} +1 -1
  52. package/dist/client/assets/{chunk-727SXJPM-B9b8698e.js → chunk-727SXJPM-CbVz6DAi.js} +1 -1
  53. package/dist/client/assets/{chunk-AQP2D5EJ-DrM8nnhR.js → chunk-AQP2D5EJ-O8p3lAmi.js} +1 -1
  54. package/dist/client/assets/{chunk-FMBD7UC4-jyT6Scwe.js → chunk-FMBD7UC4-8KJJYFeG.js} +1 -1
  55. package/dist/client/assets/{chunk-ND2GUHAM-EoPfF-PK.js → chunk-ND2GUHAM-D_zeaF-K.js} +1 -1
  56. package/dist/client/assets/{chunk-QZHKN3VN-qMwLVfgJ.js → chunk-QZHKN3VN-IzXnlcXm.js} +1 -1
  57. package/dist/client/assets/classDiagram-4FO5ZUOK-sIVsNnoj.js +1 -0
  58. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-sIVsNnoj.js +1 -0
  59. package/dist/client/assets/{cose-bilkent-S5V4N54A-DmPFKoVD.js → cose-bilkent-S5V4N54A-DyB8nAG8.js} +1 -1
  60. package/dist/client/assets/{dagre-BM42HDAG-DeHxd-ej.js → dagre-BM42HDAG-BkFeh-yy.js} +1 -1
  61. package/dist/client/assets/{dashboard-view-Cw5mMJay.js → dashboard-view-Ddw7AZEw.js} +1 -1
  62. package/dist/client/assets/{dashboard-view-DXjNQ5IF.js → dashboard-view-zm0LyiGH.js} +1 -1
  63. package/dist/client/assets/{diagram-2AECGRRQ-C04A2mhr.js → diagram-2AECGRRQ-D6ccxFD_.js} +1 -1
  64. package/dist/client/assets/{diagram-5GNKFQAL-DqtOwADI.js → diagram-5GNKFQAL-pYELzWoc.js} +1 -1
  65. package/dist/client/assets/{diagram-KO2AKTUF-CH0har-Z.js → diagram-KO2AKTUF-DiX408pG.js} +1 -1
  66. package/dist/client/assets/{diagram-LMA3HP47-CxN-U-0W.js → diagram-LMA3HP47-CEZO6Pzz.js} +1 -1
  67. package/dist/client/assets/{diagram-OG6HWLK6-42A7wpwF.js → diagram-OG6HWLK6-C4wPGJ9_.js} +1 -1
  68. package/dist/client/assets/{erDiagram-TEJ5UH35-CnZI5YlN.js → erDiagram-TEJ5UH35-UVoBlCdP.js} +1 -1
  69. package/dist/client/assets/{flowDiagram-I6XJVG4X-BKfQhMVF.js → flowDiagram-I6XJVG4X-BHBVkZYH.js} +1 -1
  70. package/dist/client/assets/{folder-open-STXgbemw.js → folder-open-BS746XqG.js} +1 -1
  71. package/dist/client/assets/{ganttDiagram-6RSMTGT7-BfA0pME8.js → ganttDiagram-6RSMTGT7-JhbzzuUH.js} +1 -1
  72. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-BgDFB7PS.js → gitGraphDiagram-PVQCEYII-Bf9CFASb.js} +1 -1
  73. package/dist/client/assets/index-BNXyfteR.css +1 -0
  74. package/dist/client/assets/index-DZGZRdnt.js +1302 -0
  75. package/dist/client/assets/{infoDiagram-5YYISTIA-Bb5F155s.js → infoDiagram-5YYISTIA-ODZX4ugg.js} +1 -1
  76. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-8Oati7l_.js → ishikawaDiagram-YF4QCWOH-BZ4EmuqN.js} +1 -1
  77. package/dist/client/assets/{journeyDiagram-JHISSGLW-DhHTHXTM.js → journeyDiagram-JHISSGLW-DjPguSQp.js} +1 -1
  78. package/dist/client/assets/{kanban-definition-UN3LZRKU-BWB9EtUX.js → kanban-definition-UN3LZRKU-CDlWdfMu.js} +1 -1
  79. package/dist/client/assets/{mermaid.core-BD-L2gUQ.js → mermaid.core-rI3nyVx8.js} +4 -4
  80. package/dist/client/assets/{mindmap-definition-RKZ34NQL-BSKGd7LE.js → mindmap-definition-RKZ34NQL-BduuAfgW.js} +1 -1
  81. package/dist/client/assets/{pieDiagram-4H26LBE5-BtBFPvSW.js → pieDiagram-4H26LBE5-Df_vjilh.js} +1 -1
  82. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-aWQWYPto.js → quadrantDiagram-W4KKPZXB-DXVZfmAq.js} +1 -1
  83. package/dist/client/assets/{requirementDiagram-4Y6WPE33-CprlEpIa.js → requirementDiagram-4Y6WPE33-UJTrQjTm.js} +1 -1
  84. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-Cw-AcRAV.js → sankeyDiagram-5OEKKPKP-DDERoUXV.js} +1 -1
  85. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BMW5slyv.js → sequenceDiagram-3UESZ5HK-DaULWS9L.js} +1 -1
  86. package/dist/client/assets/{shield-alert-Bzf8yNOc.js → shield-alert-BKmP809x.js} +1 -1
  87. package/dist/client/assets/{stateDiagram-AJRCARHV-CcxvIVwM.js → stateDiagram-AJRCARHV-tbFQ1nvS.js} +1 -1
  88. package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-awOfoFOB.js → stateDiagram-v2-BHNVJYJU-DQ0cOptx.js} +1 -1
  89. package/dist/client/assets/{timeline-definition-PNZ67QCA-DIEAc2YP.js → timeline-definition-PNZ67QCA-BE_RPHyh.js} +1 -1
  90. package/dist/client/assets/{upload-DuwyPTKe.js → upload-CKPEXc39.js} +1 -1
  91. package/dist/client/assets/{users-D1Qhfyro.js → users-BFmWR-bN.js} +1 -1
  92. package/dist/client/assets/{vennDiagram-CIIHVFJN-DOkqg5Wi.js → vennDiagram-CIIHVFJN-TwZvt3sz.js} +1 -1
  93. package/dist/client/assets/{wardley-L42UT6IY-DoPK1Q6d.js → wardley-L42UT6IY-C6ZavOUS.js} +1 -1
  94. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-l1vun-m2.js → wardleyDiagram-YWT4CUSO-B2i11Jb0.js} +1 -1
  95. package/dist/client/assets/{xychartDiagram-2RQKCTM6-DcUOUKvl.js → xychartDiagram-2RQKCTM6-DbfolZx7.js} +1 -1
  96. package/dist/client/index.html +2 -2
  97. package/dist/client/version.json +1 -1
  98. package/dist/droid-cli/package.json +6 -25
  99. package/dist/extension.js +4529 -4120
  100. package/dist/pi-claude-cli/index.ts +14 -6
  101. package/dist/pi-claude-cli/package.json +6 -20
  102. package/dist/pi-claude-cli/src/mcp-config.ts +58 -7
  103. package/dist/plugin-sdk/index.d.ts +220 -185
  104. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  105. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +2 -9
  106. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  107. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  108. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  109. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  110. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  111. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  112. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  113. package/dist/plugins/fusion-plugin-reports/package.json +2 -10
  114. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  115. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +3 -15
  116. package/package.json +1 -1
  117. package/skill/fusion/references/engine-tools.md +4 -0
  118. package/dist/client/assets/AgentDetailView-CgbB51Iw.css +0 -1
  119. package/dist/client/assets/ChatView-BtjkE0V7.css +0 -1
  120. package/dist/client/assets/CommandCenter-DDjpYkPe.css +0 -1
  121. package/dist/client/assets/CommandCenter-DwpiADSX.js +0 -71
  122. package/dist/client/assets/SettingsModal-DpaptT6t.js +0 -21
  123. package/dist/client/assets/SettingsModal-ino68pI2.css +0 -1
  124. package/dist/client/assets/SkillsView-Br2LkA3x.js +0 -1
  125. package/dist/client/assets/SkillsView-CJ8snrma.css +0 -1
  126. package/dist/client/assets/WorkflowNodeEditor-BOouksjw.css +0 -1
  127. package/dist/client/assets/WorkflowNodeEditor-e-eR6yzw.js +0 -8
  128. package/dist/client/assets/app-BM6bAO0b.js +0 -13
  129. package/dist/client/assets/channel-CCKvUami.js +0 -1
  130. package/dist/client/assets/classDiagram-4FO5ZUOK-C_HqY7AI.js +0 -1
  131. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C_HqY7AI.js +0 -1
  132. package/dist/client/assets/index-BnfnLXyO.css +0 -1
  133. package/dist/client/assets/index-CHy0WNjH.js +0 -1301
@@ -21,6 +21,7 @@ import {
21
21
  writeMcpConfig,
22
22
  buildAcpMcpServers,
23
23
  type McpToolDef,
24
+ type UserMcpServerSpec,
24
25
  } from "./src/mcp-config.js";
25
26
 
26
27
  /**
@@ -83,6 +84,11 @@ function debugMcp(message: string): void {
83
84
  console.error(`[pi-claude-cli] ${message}`);
84
85
  }
85
86
 
87
+ function getUserMcpServers(options: unknown): UserMcpServerSpec[] {
88
+ const servers = (options as { mcpServers?: unknown } | undefined)?.mcpServers;
89
+ return Array.isArray(servers) ? servers.filter((server): server is UserMcpServerSpec => Boolean(server && typeof server === "object" && "name" in server)) : [];
90
+ }
91
+
86
92
  /**
87
93
  * Resolve the MCP config path for the current request, regenerating it when
88
94
  * the set of custom tools changes.
@@ -113,6 +119,7 @@ function ensureMcpConfig(
113
119
  description: string;
114
120
  parameters: Record<string, unknown>;
115
121
  }>,
122
+ userMcpServers: UserMcpServerSpec[] = [],
116
123
  ): string | undefined {
117
124
  try {
118
125
  let toolDefs: McpToolDef[] = toolsFromContext(contextTools);
@@ -132,13 +139,13 @@ function ensureMcpConfig(
132
139
  toolDefs = getCustomToolDefs(pi);
133
140
  }
134
141
 
135
- if (toolDefs.length === 0) {
142
+ if (toolDefs.length === 0 && userMcpServers.length === 0) {
136
143
  cachedMcpConfig = undefined;
137
144
  return undefined;
138
145
  }
139
146
 
140
147
  const hash = createHash("sha1")
141
- .update(JSON.stringify(toolDefs))
148
+ .update(JSON.stringify({ toolDefs, userMcpServerNames: userMcpServers.map((server) => server.name) }))
142
149
  .digest("hex")
143
150
  .slice(0, 12);
144
151
 
@@ -147,7 +154,7 @@ function ensureMcpConfig(
147
154
  return cachedMcpConfig.configPath;
148
155
  }
149
156
 
150
- const configPath = writeMcpConfig(toolDefs, hash);
157
+ const configPath = writeMcpConfig(toolDefs, hash, userMcpServers);
151
158
  cachedMcpConfig = { hash, configPath };
152
159
  const toolNames = toolDefs.map((t) => t.name).join(", ");
153
160
  debugMcp(
@@ -255,18 +262,19 @@ export default function (pi: ExtensionAPI) {
255
262
  const bridgePath = resolveAcpBridgePath();
256
263
  if (bridgePath) {
257
264
  const toolDefs = resolveToolDefs(pi, contextTools);
258
- const hash = createHash("sha1").update(JSON.stringify(toolDefs)).digest("hex").slice(0, 12);
265
+ const userMcpServers = getUserMcpServers(options);
266
+ const hash = createHash("sha1").update(JSON.stringify({ toolDefs, userMcpServerNames: userMcpServers.map((server) => server.name) })).digest("hex").slice(0, 12);
259
267
  return streamViaAcp(model, context, {
260
268
  ...options,
261
269
  bridgePath,
262
- mcpServers: buildAcpMcpServers(toolDefs, hash),
270
+ mcpServers: buildAcpMcpServers(toolDefs, hash, userMcpServers),
263
271
  // Forward only HOME/PATH so the bridged `claude` authenticates from the
264
272
  // login/keychain session (R17); never inherited process.env or API keys.
265
273
  bridgeEnv: { HOME: process.env.HOME, PATH: process.env.PATH },
266
274
  });
267
275
  }
268
276
 
269
- const configPath = ensureMcpConfig(pi, contextTools);
277
+ const configPath = ensureMcpConfig(pi, contextTools, getUserMcpServers(options));
270
278
  return streamViaCli(model, context, {
271
279
  ...options,
272
280
  mcpConfigPath: configPath,
@@ -1,38 +1,24 @@
1
1
  {
2
2
  "name": "@fusion/pi-claude-cli",
3
- "version": "0.48.0",
4
- "description": "Fusion vendored fork: pi coding-agent extension that routes LLM calls through the Claude Code CLI. Forked from rchern/pi-claude-cli (MIT). See UPSTREAM.md.",
5
- "license": "MIT",
6
- "private": true,
3
+ "version": "0.49.0",
7
4
  "type": "module",
5
+ "private": true,
8
6
  "main": "index.ts",
9
- "keywords": [
10
- "pi-package"
11
- ],
12
7
  "pi": {
13
8
  "extensions": [
14
9
  "index.ts"
15
10
  ]
16
11
  },
17
- "repository": {
18
- "type": "git",
19
- "url": "https://github.com/Runfusion/Fusion",
20
- "directory": "packages/pi-claude-cli"
21
- },
22
12
  "dependencies": {
23
13
  "@agentclientprotocol/sdk": "0.24.0"
24
14
  },
25
- "peerDependencies": {
26
- "@earendil-works/pi-ai": "*",
27
- "@earendil-works/pi-coding-agent": "*"
28
- },
29
15
  "devDependencies": {
30
16
  "@types/node": "^22.0.0",
31
17
  "typescript": "^5.7.0",
32
18
  "vitest": "^4.1.0"
33
19
  },
34
- "scripts": {
35
- "test": "vitest run --reporter=dot",
36
- "typecheck": "tsc --noEmit"
20
+ "peerDependencies": {
21
+ "@earendil-works/pi-ai": "*",
22
+ "@earendil-works/pi-coding-agent": "*"
37
23
  }
38
- }
24
+ }
@@ -92,6 +92,39 @@ export function toolsFromContext(
92
92
  }));
93
93
  }
94
94
 
95
+ export interface UserMcpServerSpec {
96
+ name: string;
97
+ enabled?: boolean;
98
+ transport?: "stdio" | "sse" | "streamable-http";
99
+ command?: string;
100
+ args?: string[];
101
+ env?: Record<string, string>;
102
+ url?: string;
103
+ headers?: Record<string, string>;
104
+ }
105
+
106
+ function userServerToConfig(server: UserMcpServerSpec): Record<string, unknown> | undefined {
107
+ if (server.enabled === false) return undefined;
108
+ if (server.transport === "sse" || server.transport === "streamable-http") {
109
+ if (!server.url) return undefined;
110
+ return {
111
+ transport: server.transport,
112
+ url: server.url,
113
+ ...(server.headers ? { headers: server.headers } : {}),
114
+ };
115
+ }
116
+ if (!server.command) return undefined;
117
+ return {
118
+ command: server.command,
119
+ ...(server.args ? { args: server.args } : {}),
120
+ ...(server.env ? { env: server.env } : {}),
121
+ };
122
+ }
123
+
124
+ /**
125
+ * FNXC:McpConfig 2026-06-25-22:12:
126
+ * The Claude CLI MCP config combines Fusion's schema-only custom-tools server with operator-enabled user MCP servers. User env/header values are already secret-materialized by the engine, so this module must write them only to the transient MCP config and never log server contents.
127
+ */
95
128
  /**
96
129
  * Write MCP config and tool schemas to temp files.
97
130
  *
@@ -108,6 +141,7 @@ export function toolsFromContext(
108
141
  export function writeMcpConfig(
109
142
  toolDefs: McpToolDef[],
110
143
  cacheKey?: string,
144
+ userMcpServers: UserMcpServerSpec[] = [],
111
145
  ): string {
112
146
  const suffix = cacheKey ? `${process.pid}-${cacheKey}` : `${process.pid}`;
113
147
 
@@ -124,14 +158,17 @@ export function writeMcpConfig(
124
158
  const serverPath = join(__dirname, "mcp-schema-server.cjs");
125
159
 
126
160
  // Build MCP config
127
- const config = {
128
- mcpServers: {
129
- "custom-tools": {
130
- command: "node",
131
- args: [serverPath, schemaFilePath],
132
- },
161
+ const mcpServers: Record<string, unknown> = {
162
+ "custom-tools": {
163
+ command: "node",
164
+ args: [serverPath, schemaFilePath],
133
165
  },
134
166
  };
167
+ for (const server of userMcpServers) {
168
+ const config = userServerToConfig(server);
169
+ if (config) mcpServers[server.name] = config;
170
+ }
171
+ const config = { mcpServers };
135
172
 
136
173
  // Write config to temp file
137
174
  const configFilePath = join(
@@ -151,6 +188,16 @@ export interface AcpMcpServerSpec {
151
188
  env: { name: string; value: string }[];
152
189
  }
153
190
 
191
+ function userServerToAcp(server: UserMcpServerSpec): AcpMcpServerSpec | undefined {
192
+ if (server.enabled === false || (server.transport && server.transport !== "stdio") || !server.command) return undefined;
193
+ return {
194
+ name: server.name,
195
+ command: server.command,
196
+ args: server.args ?? [],
197
+ env: Object.entries(server.env ?? {}).map(([name, value]) => ({ name, value })),
198
+ };
199
+ }
200
+
154
201
  /**
155
202
  * Build the ACP `mcpServers` spec for the same schema-only `custom-tools` server
156
203
  * `writeMcpConfig` produces for `--mcp-config` — but as the inline ACP shape
@@ -161,13 +208,17 @@ export interface AcpMcpServerSpec {
161
208
  export function buildAcpMcpServers(
162
209
  toolDefs: McpToolDef[],
163
210
  cacheKey?: string,
211
+ userMcpServers: UserMcpServerSpec[] = [],
164
212
  ): AcpMcpServerSpec[] {
165
- if (toolDefs.length === 0) return [];
213
+ if (toolDefs.length === 0) {
214
+ return userMcpServers.map(userServerToAcp).filter((server): server is AcpMcpServerSpec => Boolean(server));
215
+ }
166
216
  const suffix = cacheKey ? `${process.pid}-${cacheKey}` : `${process.pid}`;
167
217
  const schemaFilePath = join(tmpdir(), `pi-claude-mcp-schemas-${suffix}.json`);
168
218
  writeFileSync(schemaFilePath, JSON.stringify(toolDefs));
169
219
  const serverPath = join(dirname(fileURLToPath(import.meta.url)), "mcp-schema-server.cjs");
170
220
  return [
171
221
  { name: "custom-tools", command: "node", args: [serverPath, schemaFilePath], env: [] },
222
+ ...userMcpServers.map(userServerToAcp).filter((server): server is AcpMcpServerSpec => Boolean(server)),
172
223
  ];
173
224
  }