chainlesschain 0.163.1 → 0.163.3

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 (191) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-Cn7quRgL.js → AIOps-DIY6KxV-.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-YqMX3ueH.js → ActionButton-BXH0muPt.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-Bxmy1b7Y.js → Analytics-D39w8vmg.js} +2 -2
  5. package/src/assets/web-panel/assets/{AppLayout-DBOw69jE.js → AppLayout-CUU1zvLs.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-mq1nyzN1.js → Artifacts-D8azHO3T.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-mMiKtZ0D.js → Audit-D0tAwXTg.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-WBUjpYVh.js → BackgroundAgents-C29mhJll.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-c25OoJgs.js → Backup-D6Aa1Gro.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-BbfWhZ4-.js → BaseInput-B1uoHbPQ.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-CVVzsTwU.js → Chat-Bs4DLOR5.js} +5 -5
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CVCjZJ04.js → ChatBubbleRenderer-DUYIBSle.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-C9o2HK-1.js → Checkbox-CNcBPEa4.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-B7X5LfKc.js → Codegen-CIY89763.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-jpPj2Pur.js → Col-CsPYFmgo.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-Dti6bHxN.js → Community-BBocEge4.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-S4ZsLt3W.js → Compact-TQ8Ux0Lf.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-Bge0sQ3O.js → Compliance-DfBsZTft.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-C4XyzVI7.js → Cowork-Cg-I6FVH.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-CPR0v2xy.js → Cron-DTQzfRTp.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-DAX8lDaj.js → Crosschain-DGxEKGpR.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-fBHPa0QH.js → DID-DLZ1RDSr.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-vvaUTafU.js → Dashboard-XneICKNI.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-DyaQM63v.js → Dropdown-BRU00J1-.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-CAF0wiU2.js → EmailListRenderer-BzCbJuAy.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-ia-WzDRs.js → FamilyGuardDashboard-D7BRyNBG.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-Cz3gHoT5.js → Federation-D9DeFIhW.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CJQDJr4Q.js → FormItemContext-6rAtA9Ko.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-B05BZlQp.js → GenericCardRenderer-8Hqy80pU.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-DT0YcQnI.js → Git-Cmvkj1rt.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-Bqbl6m5Q.js → Governance-BRiQUjjw.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-BdebLR0N.js → Inference-CKN_EzVf.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-M36b8YYV.js → KnowledgeGraph-BCDHwpwQ.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-5LN_XL43.js → Logs-DK9ovhaB.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-BCb1Dm8l.js → MarkdownRenderer-D53pHiHy.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-BkIin-QY.js → Marketplace-BILPGakp.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-Bkppx8Uj.js → McpTools-DTVCOr9-.js} +5 -5
  38. package/src/assets/web-panel/assets/{Memory-Qk9wg_Ib.js → Memory-Hzc1iow4.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-BsTDU3Aj.js → MobileBridge-GXfgnGYV.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-CrZW5I28.js → MobileProjects-B-3TJWsS.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-BMkmgtsA.js → Mtc-DwSJMWtK.js} +2 -2
  42. package/src/assets/web-panel/assets/{MtcAudit-6m4CC0Yn.js → MtcAudit-D2uxf-DA.js} +2 -2
  43. package/src/assets/web-panel/assets/{Multisig-BZ8yB7QV.js → Multisig-DG6kbKK0.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-CxitAMIO.js → NLProgramming-f5p49EDU.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-Bv0msnHu.js → Notes-FUgHyzSD.js} +4 -4
  46. package/src/assets/web-panel/assets/{NotificationSettings-DeVMqM3P.js → NotificationSettings-DCHGee7e.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-CXBSWa3R.js → OrderTableRenderer-Dm6LlIoa.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-b_G5Vs1Q.js → Organization-BawA7qAg.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-DW7riOmA.js → Overflow-D6a5wZU1.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-CtpQNYjL.js → P2P-K8WavwnA.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-Ba63yT4l.js → PdhVaultBrowser-4JAJYaqx.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-DnzyeB67.js → Permissions-BDWvi8PD.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-DbPZ7HWw.js → PersonalDataHub-DF_K4E9i.js} +3 -3
  54. package/src/assets/web-panel/assets/{Pipeline-gs_HOThJ.js → Pipeline-BYeZlesI.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-CZlQ1EjE.js → Privacy-BIHlgnIc.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-DQp__Ccb.js → ProjectInit-Cvf-6B5P.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-C7h2sOWZ.js → ProjectSettings-CnwfJrRz.js} +2 -2
  58. package/src/assets/web-panel/assets/Projects-b-jPXzF4.js +1 -0
  59. package/src/assets/web-panel/assets/Providers-CxC7JuYv.js +1 -0
  60. package/src/assets/web-panel/assets/{QrScannerModal-B_8M1-FC.js → QrScannerModal-VLf3gAfL.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-Bpycr8WD.js → QuickAsk-B5vGjRiF.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-Z4TrcNzs.js → Recommend--UW4iYs-.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-BD6TsJlS.js → RemoteSession-DMSPcfKR.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-IKxDXHEu.js → Reputation-kQXlEHmj.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-DbmR20tJ.js → Row-CxGu3pit.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-CLjA5PPf.js → RssFeed-Bi5lo8MZ.js} +2 -2
  67. package/src/assets/web-panel/assets/{Search-Bm3owbIU.js → Search-Cq_H5RTh.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-CY4RyOuq.js → Security-YFbmkaQS.js} +2 -2
  69. package/src/assets/web-panel/assets/{Services-CYO9qrd_.js → Services-DLOGdaLm.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-ClF51Go6.js → Skeleton-CteIxb3D.js} +1 -1
  71. package/src/assets/web-panel/assets/Skills-CccopaIZ.js +1 -0
  72. package/src/assets/web-panel/assets/{Sla-zqpDUxzP.js → Sla-AzfEQKX1.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-DPSi8Qco.js → SpeechSettings-ekGo5l77.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-CqABopsQ.js → SyncSettings-BmZmAgYH.js} +2 -2
  75. package/src/assets/web-panel/assets/Tasks-D7q3Z4uL.js +1 -0
  76. package/src/assets/web-panel/assets/{Templates-Dzl6f0M2.js → Templates-CX1Tgeka.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-XeZkw40a.js → Tenant-Zc59jF4i.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-CYw2YzPm.js → Terminal-CXOD7y83.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-Bc2pko4i.js → TimelineRenderer-B1aBHPBo.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-CfCenOHx.js → Tokens-zALlOq_U.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-DTz-_YqV.js → Trigger-CQfJMXaq.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-CB3tt3Z6.js → Trust-BU0RcM-w.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-y1ykmMvU.js → UkeySign-IFZ3HsbH.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-UlZ_lX0e.js → VideoEditing-BzslgW0v.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-DMBaHTha.js → Wallet-BZAcQNS6.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-Cksm-hBI.js → WebAuthn-CBK1DMi0.js} +4 -4
  87. package/src/assets/web-panel/assets/{WorkflowEditor-BhOa40sX.js → WorkflowEditor-BlMTPzO-.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-DNbeSTDO.js → chat-B51-8QVn.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-9zz8gBmW.js → colors-504RTByU.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-D7aoVv-5.js → compact-item-C-GP6IQM.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-DYg7B8nd.js → createContext-DOkIj7ID.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-kB0nCNwN.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-BNbhkcoI.js → hasIn-DN7V-_FW.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-DeD1wWA8.js → index--n-ZciV3.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-Da0SysnX.js → index-7jIqHbzw.js} +1 -1
  96. package/src/assets/web-panel/assets/{index--TvoQ6UC.js → index-B2-x9bS8.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-m2pXS3W2.js → index-BFIFJ5Dr.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CzDDeZBo.js → index-B_vGU-Js.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-gNKj00Fx.js → index-Bkxhaeta.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-C8LC0nvw.js → index-By6u5IV1.js} +1 -1
  101. package/src/assets/web-panel/assets/index-Bya64sZE.js +1 -0
  102. package/src/assets/web-panel/assets/{index-B8irlIUK.js → index-C0k_Nqg9.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-B9zUawcE.js → index-C3TSohzc.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BPojutcZ.js → index-C4DV_5uA.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-ZPDbEh-L.js → index-C8UltbXK.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-jS6NASar.js → index-C9_48OzU.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-67GdrUx2.js → index-CKTfZyfU.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CYu-F-gp.js → index-CP2A226L.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Cq3l0L7C.js → index-CUhQpiYv.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DtQzs0hH.js → index-CX78k-qf.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Bdxe0nrD.js → index-CYopNjcJ.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-uc8Rz96X.js → index-Cao5DZy7.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DnTM8FWK.js → index-CfiEM64n.js} +3 -3
  114. package/src/assets/web-panel/assets/{index-DHskwmwI.js → index-ConjaJro.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CA72qB1n.js → index-CqcLo5WV.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-Dn-JFqEi.js → index-CySTJKeq.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DUWmZ059.js → index-D1phyca8.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-_-Vt1Wqk.js → index-D9LyiN-L.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DIljkSt9.js → index-DA2f1UV3.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-B9TzVW7i.js → index-DAOpQvl_.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-CRKukX1W.js → index-DE-hmI2l.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DIMVe3HJ.js → index-DEMPUVa3.js} +1 -1
  123. package/src/assets/web-panel/assets/index-D_FWpDZM.js +1 -0
  124. package/src/assets/web-panel/assets/{index-FlBuITVG.js → index-DaA__-q1.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-Cqy-hqD9.js → index-FcV8J_Qz.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CpEIwp4A.js → index-P2mfY27Z.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-nnmo3ipi.js → index-et5JIPHO.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-SmEIFaRm.js → index-f4Bo4KXm.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DMrqEsOS.js → index-kAqQXfP6.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CV06YdPO.js → index-kt_5rfcZ.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CN6-OEgS.js → index-so8eIIxF.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BRd1zkLB.js → index-yYTQZypF.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-D0mTMUGz.js → initDefaultProps-CPYEIdpV.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-DK16p4-o.js → motion-Cjim9pxs.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-DalC20HC.js → move-DuU-cgz3.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-B5RusszF.js → mtc-parser-DJHNAkta.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-C9Mhitht.js → omit-DSQBgdBj.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-51xQLgwM.js → pickAttrs-CTmT_j5m.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-CJzIqp8u.js → placementArrow-Lfm6v-r4.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-HQvC19u4.js → responsiveObserve-CgrcPcDi.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-C6hhabOp.js → slide-CuE3110i.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-Q1r48-oc.js → statusUtils-DiK5nbpf.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-UakVWrHs.js → styleChecker-DPEJdQaZ.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-Dmv94cxx.js → useFlexGapSupport-CnnodGmp.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-DrxOnt_V.js → useFs-DWF84Yav.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-BVf2M-Hg.js → usePersonalDataHub-a5b5Dw2f.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-BzzW9qKH.js → vnode-DAluzXOq.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-C1ZvMgAZ.js → zoom-Dokg7uAZ.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/command-help-index.json +1 -1
  151. package/src/commands/agenda.js +6 -5
  152. package/src/commands/agent.js +237 -75
  153. package/src/commands/agents.js +6 -0
  154. package/src/commands/background-session.js +11 -1
  155. package/src/commands/mcp.js +245 -30
  156. package/src/data/changelog.json +28 -2
  157. package/src/harness/mcp-client.js +256 -43
  158. package/src/harness/worktree-isolator.js +26 -3
  159. package/src/lib/agent-worktree.js +41 -2
  160. package/src/lib/background-agent-supervisor.js +790 -186
  161. package/src/lib/background-command-argv.js +318 -0
  162. package/src/lib/background-launch-profile.js +1 -0
  163. package/src/lib/background-phase-reporter.js +22 -2
  164. package/src/lib/background-worktree-policy.js +109 -0
  165. package/src/lib/cowork-mcp-tools.js +52 -6
  166. package/src/lib/cowork-task-runner.js +1 -0
  167. package/src/lib/cowork-task-templates.js +1 -0
  168. package/src/lib/mcp-headers-helper.js +76 -8
  169. package/src/lib/mcp-sandbox-policy.js +155 -0
  170. package/src/lib/mcp-stdio-executable-identity.js +75 -11
  171. package/src/lib/mcp-stdio-execution-authority.js +168 -0
  172. package/src/lib/mcp-stdio-workspace-authority.js +252 -0
  173. package/src/lib/plugin-runtime/sandbox-policy.js +42 -2
  174. package/src/lib/process-execution-broker/index.js +495 -126
  175. package/src/lib/process-execution-broker/platform-sandbox.js +1424 -189
  176. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  177. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  178. package/src/lib/process-execution-broker/windows-sandbox.cs +5 -4
  179. package/src/lib/process-tree-termination.js +17 -1
  180. package/src/lib/skill-mcp.js +74 -3
  181. package/src/lib/web-fetch.js +4 -4
  182. package/src/runtime/agent-runtime.js +61 -8
  183. package/src/runtime/mcp-config.js +238 -28
  184. package/src/workers/background-agent-worker.js +492 -71
  185. package/src/assets/web-panel/assets/Projects-DdCpNRNt.js +0 -1
  186. package/src/assets/web-panel/assets/Providers-CyvtUkUf.js +0 -1
  187. package/src/assets/web-panel/assets/Skills-CCCEmSf5.js +0 -1
  188. package/src/assets/web-panel/assets/Tasks-4dbAJng4.js +0 -1
  189. package/src/assets/web-panel/assets/devWarning-uadaGF_y.js +0 -1
  190. package/src/assets/web-panel/assets/index-C7zhie9M.js +0 -1
  191. package/src/assets/web-panel/assets/index-Cmbg0Wbr.js +0 -1
@@ -16,6 +16,7 @@
16
16
 
17
17
  import fs from "fs";
18
18
  import path from "path";
19
+ import { isProxy } from "node:util/types";
19
20
  import {
20
21
  MCPClient,
21
22
  inferTransport,
@@ -45,12 +46,65 @@ import {
45
46
  isMcpToolMetadataError,
46
47
  } from "../lib/mcp-tool-metadata.js";
47
48
  import { issueMcpStdioExecutionAuthority } from "../lib/mcp-stdio-execution-authority.js";
49
+ import {
50
+ MCP_SANDBOX_POLICY_INVALID_CODE,
51
+ normalizeMcpSandboxPolicy,
52
+ readMcpStdioCwd,
53
+ } from "../lib/mcp-sandbox-policy.js";
54
+
55
+ function invalidSandboxPolicy(message) {
56
+ const error = new TypeError(message);
57
+ error.code = MCP_SANDBOX_POLICY_INVALID_CODE;
58
+ return error;
59
+ }
60
+
61
+ function sandboxPolicyFromConfig(config, label) {
62
+ if (!config || typeof config !== "object" || isProxy(config)) {
63
+ throw invalidSandboxPolicy(`${label} must be a non-Proxy object`);
64
+ }
65
+ const descriptor = Object.getOwnPropertyDescriptor(config, "sandboxPolicy");
66
+ if (!descriptor) return null;
67
+ if (!("value" in descriptor)) {
68
+ throw invalidSandboxPolicy(
69
+ `${label}.sandboxPolicy must be an own data property`,
70
+ );
71
+ }
72
+ return normalizeMcpSandboxPolicy(descriptor.value, {
73
+ label: `${label}.sandboxPolicy`,
74
+ });
75
+ }
76
+
77
+ function mcpServerNameReservations(deps = {}) {
78
+ if (deps.mcpServerNameReservations instanceof Set) {
79
+ return deps.mcpServerNameReservations;
80
+ }
81
+ if (deps.into?._mcpServerNameReservations instanceof Set) {
82
+ return deps.into._mcpServerNameReservations;
83
+ }
84
+ return new Set();
85
+ }
86
+
87
+ function reserveMcpServerNames(reservations, names) {
88
+ for (const name of names || []) {
89
+ if (typeof name === "string" && name.length > 0) reservations.add(name);
90
+ }
91
+ }
92
+
93
+ function rawMcpServerNames(raw) {
94
+ const block =
95
+ raw && typeof raw === "object" && !Array.isArray(raw)
96
+ ? raw.mcpServers || raw.servers || raw
97
+ : null;
98
+ return block && typeof block === "object" && !Array.isArray(block)
99
+ ? Object.keys(block)
100
+ : [];
101
+ }
48
102
 
49
103
  function authorizeStdioServers(
50
104
  servers,
51
105
  approvalKind,
52
106
  sourceForServer,
53
- { writeErr = () => {}, failFast = false } = {},
107
+ { writeErr = () => {}, failFast = false, nameReservations = null } = {},
54
108
  ) {
55
109
  for (const [name, config] of Object.entries(servers || {})) {
56
110
  if (!config || typeof config !== "object") continue;
@@ -65,6 +119,7 @@ function authorizeStdioServers(
65
119
  } catch (error) {
66
120
  if (failFast) throw error;
67
121
  delete servers[name];
122
+ nameReservations?.add?.(name);
68
123
  writeErr(
69
124
  ` mcp: SKIPPING stdio server "${name}" because its local-code execution authority could not be issued.\n`,
70
125
  );
@@ -92,10 +147,17 @@ export function parseMcpServers(raw) {
92
147
  const out = {};
93
148
  for (const [name, cfg] of Object.entries(block)) {
94
149
  if (!cfg || typeof cfg !== "object") continue;
150
+ const sandboxPolicy = sandboxPolicyFromConfig(cfg, `mcpServers.${name}`);
151
+ const { cwd } = readMcpStdioCwd(cfg, { label: `mcpServers.${name}` });
95
152
  out[name] = {
96
153
  command: cfg.command,
97
154
  args: Array.isArray(cfg.args) ? cfg.args : [],
98
155
  env: cfg.env && typeof cfg.env === "object" ? cfg.env : {},
156
+ ...(typeof cfg.runtimeKind === "string"
157
+ ? { runtimeKind: cfg.runtimeKind }
158
+ : {}),
159
+ ...(cwd ? { cwd } : {}),
160
+ ...(sandboxPolicy ? { sandboxPolicy } : {}),
99
161
  url: cfg.url,
100
162
  transport: cfg.transport,
101
163
  headers:
@@ -160,6 +222,7 @@ export async function loadManagedMcp(settings, deps = {}) {
160
222
  return deps.into || null;
161
223
  }
162
224
  const servers = parseMcpServers({ mcpServers: block });
225
+ const nameReservations = mcpServerNameReservations(deps);
163
226
  for (const config of Object.values(servers)) {
164
227
  config.configScope = "managed";
165
228
  config.configSource = deps.managedFile || "managed-settings";
@@ -168,13 +231,19 @@ export async function loadManagedMcp(settings, deps = {}) {
168
231
  servers,
169
232
  "managed-settings",
170
233
  (_name, config) => config.configSource,
171
- { writeErr: deps.writeErr },
234
+ {
235
+ writeErr: deps.writeErr,
236
+ nameReservations,
237
+ },
172
238
  );
173
239
  if (Object.keys(servers).length === 0) return deps.into || null;
174
240
  (deps.writeErr || (() => {}))(
175
241
  ` mcp: ${Object.keys(servers).length} managed server(s) from ${deps.managedFile || "managed settings"}\n`,
176
242
  );
177
- return setupMcpFromConfig(servers, deps);
243
+ return setupMcpFromConfig(servers, {
244
+ ...deps,
245
+ mcpServerNameReservations: nameReservations,
246
+ });
178
247
  }
179
248
 
180
249
  function managedServerNames(value) {
@@ -272,6 +341,8 @@ export async function setupMcpFromConfig(servers, deps = {}) {
272
341
  (() =>
273
342
  new MCPClient({ eventRuntimeStore: deps.eventRuntimeStore || null }));
274
343
  servers = filterMcpServersByPolicy(servers, deps.mcpPolicy, writeErr);
344
+ const nameReservations = mcpServerNameReservations(deps);
345
+ const previouslyReservedNames = new Set(nameReservations);
275
346
 
276
347
  // `deps.into` lets a second batch (e.g. registered servers) accumulate into
277
348
  // the SAME client + channel objects as a first batch (e.g. --mcp-config), so
@@ -285,6 +356,12 @@ export async function setupMcpFromConfig(servers, deps = {}) {
285
356
  resources: [],
286
357
  prompts: [],
287
358
  };
359
+ if (!(result._mcpServerNameReservations instanceof Set)) {
360
+ Object.defineProperty(result, "_mcpServerNameReservations", {
361
+ value: nameReservations,
362
+ configurable: true,
363
+ });
364
+ }
288
365
  // Back-fill the resource/prompt accumulators when an older `deps.into` object
289
366
  // (created before this field existed) is passed in.
290
367
  if (!Array.isArray(result.resources)) result.resources = [];
@@ -326,7 +403,14 @@ export async function setupMcpFromConfig(servers, deps = {}) {
326
403
  for (const [name, cfg] of Object.entries(servers)) {
327
404
  // Skip a name already connected — an earlier batch (ad-hoc --mcp-config)
328
405
  // wins over a later one (registered) on a clash.
329
- if (mcpClient.servers?.has?.(name)) continue;
406
+ if (mcpClient.servers?.has?.(name)) {
407
+ nameReservations.add(name);
408
+ continue;
409
+ }
410
+ if (previouslyReservedNames.has(name)) continue;
411
+ // Precedence is selected before authorization/connect. A failed higher
412
+ // source must never release its name for a lower source in this run.
413
+ nameReservations.add(name);
330
414
  // Inject a stored OAuth bearer token for remote servers (`cc mcp login`),
331
415
  // unless the config already supplies an Authorization header. Best-effort:
332
416
  // no token / a refresh failure just connects unauthenticated.
@@ -649,6 +733,7 @@ export async function loadMcpConfig(filePath, deps = {}) {
649
733
  */
650
734
  export async function loadRegisteredMcp(rawDb, deps = {}) {
651
735
  if (!rawDb) return deps.into || null;
736
+ const nameReservations = mcpServerNameReservations(deps);
652
737
  let rows;
653
738
  try {
654
739
  let make = deps.makeServerConfig;
@@ -657,19 +742,79 @@ export async function loadRegisteredMcp(rawDb, deps = {}) {
657
742
  make = (db) => new MCPServerConfig(db);
658
743
  }
659
744
  const cfg = make(rawDb);
660
- const visibility = { cwd: deps.cwd || process.cwd() };
745
+ const writeErr = deps.writeErr || (() => {});
746
+ const visibility = {
747
+ cwd: deps.cwd || process.cwd(),
748
+ onInvalidRow: (error, row) => {
749
+ const rawName = row?.display_name || row?.name || "unknown";
750
+ const safeName = String(rawName).replace(/[\r\n]/g, " ");
751
+ if (typeof rawName === "string" && rawName.length > 0) {
752
+ nameReservations.add(rawName);
753
+ }
754
+ const reason = String(
755
+ error?.code || error?.message || "unknown error",
756
+ ).replace(/[\r\n]/g, " ");
757
+ writeErr(
758
+ ` mcp: SKIPPING stored server "${safeName}" because its configuration is invalid (${reason}).\n`,
759
+ );
760
+ },
761
+ };
661
762
  if (deps.scope) visibility.scope = deps.scope;
662
- rows = deps.all ? cfg.list(visibility) : cfg.getAutoConnect(visibility);
763
+ if (typeof cfg.list === "function") {
764
+ const visibleRows = cfg.list(visibility);
765
+ if (deps.all) {
766
+ rows = visibleRows;
767
+ } else {
768
+ reserveMcpServerNames(
769
+ nameReservations,
770
+ visibleRows
771
+ .filter((row) => row?.autoConnect !== true)
772
+ .map((row) => row?.name),
773
+ );
774
+ rows =
775
+ typeof cfg.getAutoConnect === "function"
776
+ ? cfg.getAutoConnect({ ...visibility, onInvalidRow: undefined })
777
+ : visibleRows.filter((row) => row?.autoConnect === true);
778
+ }
779
+ } else {
780
+ rows = deps.all ? [] : cfg.getAutoConnect(visibility);
781
+ }
663
782
  } catch {
664
783
  return deps.into || null; // registry unavailable — non-fatal
665
784
  }
666
785
  const servers = {};
667
786
  for (const r of rows || []) {
668
787
  if (!r || !r.name) continue;
788
+ if (nameReservations.has(r.name)) continue;
789
+ let sandboxPolicy;
790
+ let cwd;
791
+ try {
792
+ sandboxPolicy = sandboxPolicyFromConfig(
793
+ r,
794
+ `registered MCP server ${r.name}`,
795
+ );
796
+ ({ cwd } = readMcpStdioCwd(r, {
797
+ label: `registered MCP server ${r.name}`,
798
+ }));
799
+ } catch (error) {
800
+ nameReservations.add(r.name);
801
+ const reason = String(
802
+ error?.code || error?.message || "unknown error",
803
+ ).replace(/[\r\n]/g, " ");
804
+ (deps.writeErr || (() => {}))(
805
+ ` mcp: SKIPPING registered server "${String(r.name).replace(/[\r\n]/g, " ")}" because its configuration is invalid (${reason}).\n`,
806
+ );
807
+ continue;
808
+ }
669
809
  servers[r.name] = {
670
810
  command: r.command,
671
811
  args: r.args,
672
812
  env: r.env,
813
+ ...(typeof r.runtimeKind === "string"
814
+ ? { runtimeKind: r.runtimeKind }
815
+ : {}),
816
+ ...(cwd ? { cwd } : {}),
817
+ ...(sandboxPolicy ? { sandboxPolicy } : {}),
673
818
  url: r.url,
674
819
  transport: r.transport,
675
820
  headers: r.headers,
@@ -685,9 +830,12 @@ export async function loadRegisteredMcp(rawDb, deps = {}) {
685
830
  "registered-config",
686
831
  (name, config) =>
687
832
  `${config.configScope || "user"}:${config.configSource || "user-database"}:${name}`,
688
- { writeErr: deps.writeErr },
833
+ { writeErr: deps.writeErr, nameReservations },
689
834
  );
690
- return setupMcpFromConfig(servers, deps);
835
+ return setupMcpFromConfig(servers, {
836
+ ...deps,
837
+ mcpServerNameReservations: nameReservations,
838
+ });
691
839
  }
692
840
 
693
841
  /**
@@ -715,6 +863,9 @@ export async function loadIdeMcp(opts = {}, deps = {}) {
715
863
  );
716
864
  return deps.into;
717
865
  }
866
+ if (mcpServerNameReservations(deps).has("ide")) {
867
+ return deps.into || null;
868
+ }
718
869
  const cfg = toCfg(lock);
719
870
  if (!cfg) return deps.into || null;
720
871
  const out = await setupMcpFromConfig({ ide: cfg }, deps);
@@ -763,6 +914,9 @@ export async function loadPdhMcp(opts = {}, deps = {}) {
763
914
  );
764
915
  return deps.into;
765
916
  }
917
+ if (mcpServerNameReservations(deps).has("pdh")) {
918
+ return deps.into || null;
919
+ }
766
920
  const cfg = toCfg(lock);
767
921
  if (!cfg) return deps.into || null;
768
922
  const out = await setupMcpFromConfig({ pdh: cfg }, deps);
@@ -805,6 +959,9 @@ export async function loadJetbrainsMcp(opts = {}, deps = {}) {
805
959
  );
806
960
  return deps.into;
807
961
  }
962
+ if (mcpServerNameReservations(deps).has("idea")) {
963
+ return deps.into || null;
964
+ }
808
965
  const cfg = toCfg(found);
809
966
  if (!cfg) return deps.into || null;
810
967
  const out = await setupMcpFromConfig({ idea: cfg }, deps);
@@ -865,15 +1022,17 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
865
1022
  const trust =
866
1023
  deps.projectMcpTrust ||
867
1024
  (await import("../lib/project-mcp-trust.js").catch(() => null));
868
- if (!trust) {
869
- writeErr(
870
- " mcp: SKIPPING project .mcp.json — project trust service is unavailable.\n",
871
- );
872
- return deps.into || null;
873
- }
874
-
1025
+ const nameReservations = mcpServerNameReservations(deps);
875
1026
  const servers = {};
876
1027
  const seenFiles = [];
1028
+ const blockedProjectNames = new Set();
1029
+ const blockProjectNames = (names) => {
1030
+ for (const name of names || []) {
1031
+ if (typeof name !== "string" || name.length === 0) continue;
1032
+ blockedProjectNames.add(name);
1033
+ delete servers[name];
1034
+ }
1035
+ };
877
1036
  for (const file of files) {
878
1037
  if (!fileExists(file)) continue;
879
1038
  let content;
@@ -885,6 +1044,14 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
885
1044
  writeErr(` mcp: ignoring malformed ${file} (${err.message})\n`);
886
1045
  continue;
887
1046
  }
1047
+ const rawServerNames = rawMcpServerNames(raw);
1048
+ if (!trust) {
1049
+ blockProjectNames(rawServerNames);
1050
+ writeErr(
1051
+ ` mcp: SKIPPING ${file} — project trust service is unavailable.\n`,
1052
+ );
1053
+ continue;
1054
+ }
888
1055
  try {
889
1056
  const check = trust.checkProjectMcpTrust(file, content);
890
1057
  if (check.status === "changed") {
@@ -894,6 +1061,7 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
894
1061
  }
895
1062
  writeErr(` mcp: ${file} re-trusted (CC_PROJECT_MCP_TRUST).\n`);
896
1063
  } else {
1064
+ blockProjectNames(rawServerNames);
897
1065
  writeErr(
898
1066
  ` mcp: SKIPPING ${file} — its content changed since it was last trusted. ` +
899
1067
  `Review the diff, then re-trust with CC_PROJECT_MCP_TRUST=1 or \`cc mcp trust-project\`.\n`,
@@ -906,13 +1074,25 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
906
1074
  }
907
1075
  }
908
1076
  } catch (err) {
1077
+ blockProjectNames(rawServerNames);
909
1078
  writeErr(
910
1079
  ` mcp: SKIPPING ${file} — project trust state is unavailable ` +
911
1080
  `(${err?.message || "unknown error"}).\n`,
912
1081
  );
913
1082
  continue;
914
1083
  }
915
- const parsed = parseMcpServers(raw);
1084
+ let parsed;
1085
+ try {
1086
+ parsed = parseMcpServers(raw);
1087
+ } catch (error) {
1088
+ blockProjectNames(rawServerNames);
1089
+ writeErr(
1090
+ ` mcp: SKIPPING ${file} because its server sandbox policy is invalid (${error?.message || "unknown error"}).\n`,
1091
+ );
1092
+ continue;
1093
+ }
1094
+ const parsedNames = new Set(Object.keys(parsed));
1095
+ blockProjectNames(rawServerNames.filter((name) => !parsedNames.has(name)));
916
1096
  if (Object.keys(parsed).length > 0) {
917
1097
  for (const [name, config] of Object.entries(parsed)) {
918
1098
  config.configScope = "project";
@@ -924,24 +1104,39 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
924
1104
  needsExecutionAuthority &&
925
1105
  typeof trust.issueProjectMcpWorkspaceAuthority !== "function"
926
1106
  ) {
1107
+ blockProjectNames([name]);
927
1108
  delete parsed[name];
928
1109
  continue;
929
1110
  }
930
1111
  if (needsExecutionAuthority) {
931
- config.projectMcpWorkspaceAuthority =
932
- trust.issueProjectMcpWorkspaceAuthority({
933
- file,
934
- content,
935
- workspaceRoot: path.dirname(file),
936
- serverName: name,
937
- config,
938
- });
1112
+ try {
1113
+ config.projectMcpWorkspaceAuthority =
1114
+ trust.issueProjectMcpWorkspaceAuthority({
1115
+ file,
1116
+ content,
1117
+ workspaceRoot: path.dirname(file),
1118
+ serverName: name,
1119
+ config,
1120
+ });
1121
+ } catch (error) {
1122
+ blockProjectNames([name]);
1123
+ delete parsed[name];
1124
+ writeErr(
1125
+ ` mcp: SKIPPING project server "${name}" because its workspace authority could not be issued (${error?.message || "unknown error"}).\n`,
1126
+ );
1127
+ continue;
1128
+ }
939
1129
  }
1130
+ blockedProjectNames.delete(name);
940
1131
  }
941
1132
  Object.assign(servers, parsed); // later file (cwd) overrides earlier (root)
942
1133
  seenFiles.push(file);
943
1134
  }
944
1135
  }
1136
+ reserveMcpServerNames(nameReservations, blockedProjectNames);
1137
+ for (const name of Object.keys(servers)) {
1138
+ if (nameReservations.has(name)) delete servers[name];
1139
+ }
945
1140
  if (Object.keys(servers).length === 0) return deps.into || null;
946
1141
  writeErr(
947
1142
  ` mcp: ${Object.keys(servers).length} server(s) from project .mcp.json ` +
@@ -951,9 +1146,12 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
951
1146
  servers,
952
1147
  "project-config",
953
1148
  (name, config) => `${config.configSource}:${name}`,
954
- { writeErr },
1149
+ { writeErr, nameReservations },
955
1150
  );
956
- return setupMcpFromConfig(servers, deps);
1151
+ return setupMcpFromConfig(servers, {
1152
+ ...deps,
1153
+ mcpServerNameReservations: nameReservations,
1154
+ });
957
1155
  }
958
1156
 
959
1157
  /**
@@ -991,6 +1189,10 @@ export async function loadPluginMcp(opts = {}, deps = {}) {
991
1189
  return [name, { ...rest, ...headersHelperField(config.headersHelper) }];
992
1190
  }),
993
1191
  );
1192
+ const nameReservations = mcpServerNameReservations(deps);
1193
+ for (const name of Object.keys(servers)) {
1194
+ if (nameReservations.has(name)) delete servers[name];
1195
+ }
994
1196
  const names = Object.keys(servers || {});
995
1197
  if (names.length === 0) return deps.into || null;
996
1198
  writeErr(
@@ -1001,9 +1203,12 @@ export async function loadPluginMcp(opts = {}, deps = {}) {
1001
1203
  "trusted-plugin",
1002
1204
  (name, config) =>
1003
1205
  `${config.pluginId || "plugin"}@${config.pluginVersion || "unknown"}:${config.pluginSource || "unknown"}:${name}`,
1004
- { writeErr },
1206
+ { writeErr, nameReservations },
1005
1207
  );
1006
- return setupMcpFromConfig(servers, deps);
1208
+ return setupMcpFromConfig(servers, {
1209
+ ...deps,
1210
+ mcpServerNameReservations: nameReservations,
1211
+ });
1007
1212
  }
1008
1213
 
1009
1214
  /**
@@ -1039,6 +1244,10 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
1039
1244
  (runtimeEnv.CC_EVENT_RUNTIME_DURABLE === "1"
1040
1245
  ? new EventRuntimeStore()
1041
1246
  : null);
1247
+ const serverNameReservations =
1248
+ deps.mcpServerNameReservations instanceof Set
1249
+ ? deps.mcpServerNameReservations
1250
+ : new Set();
1042
1251
  // Thread the agent session id down to setupMcpFromConfig so spawned stdio MCP
1043
1252
  // servers get CC_SESSION_ID / CLAUDE_CODE_SESSION_ID (Claude-Code parity).
1044
1253
  let mcpPolicy = deps.mcpPolicy || null;
@@ -1060,6 +1269,7 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
1060
1269
  ...(args.sessionId != null ? { sessionId: args.sessionId } : {}),
1061
1270
  ...(eventRuntimeStore ? { eventRuntimeStore } : {}),
1062
1271
  mcpPolicy,
1272
+ mcpServerNameReservations: serverNameReservations,
1063
1273
  };
1064
1274
  let result = await doManaged(managedLoaded.settings, {
1065
1275
  ...fwd,