chainlesschain 0.163.2 → 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 (185) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-DnGsmsqJ.js → AIOps-DIY6KxV-.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-CrO6fcQ7.js → ActionButton-BXH0muPt.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-DsBdOaP2.js → Analytics-D39w8vmg.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-DmQslKUB.js → AppLayout-CUU1zvLs.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-BvyrT_QQ.js → Artifacts-D8azHO3T.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-prndoLiC.js → Audit-D0tAwXTg.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-DOTFyA55.js → BackgroundAgents-C29mhJll.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-9zOnPp_8.js → Backup-D6Aa1Gro.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-C4PC6sAG.js → BaseInput-B1uoHbPQ.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-BBAF-W9v.js → Chat-Bs4DLOR5.js} +6 -6
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CWhvvloO.js → ChatBubbleRenderer-DUYIBSle.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-BI9iculd.js → Checkbox-CNcBPEa4.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-3DP9BCKb.js → Codegen-CIY89763.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-df-2TnJX.js → Col-CsPYFmgo.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-CHs8gG_A.js → Community-BBocEge4.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-CDfF6q7V.js → Compact-TQ8Ux0Lf.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-CthrDnO7.js → Compliance-DfBsZTft.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-HjIqsWJw.js → Cowork-Cg-I6FVH.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-BKc196fb.js → Cron-DTQzfRTp.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-CJnjdc8W.js → Crosschain-DGxEKGpR.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-BHUy-8Q2.js → DID-DLZ1RDSr.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-QDB7sKeY.js → Dashboard-XneICKNI.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-DStcVK11.js → Dropdown-BRU00J1-.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-BwSUskMJ.js → EmailListRenderer-BzCbJuAy.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DgF_kurT.js → FamilyGuardDashboard-D7BRyNBG.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-k8wvv-wN.js → Federation-D9DeFIhW.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-C11qoq2r.js → FormItemContext-6rAtA9Ko.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-BIIpr9kg.js → GenericCardRenderer-8Hqy80pU.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-BlA1exTe.js → Git-Cmvkj1rt.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-CYa1ZYM4.js → Governance-BRiQUjjw.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-6_kKVIt6.js → Inference-CKN_EzVf.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-CB4AwxYy.js → KnowledgeGraph-BCDHwpwQ.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-xf7nHFAe.js → Logs-DK9ovhaB.js} +2 -2
  35. package/src/assets/web-panel/assets/MarkdownRenderer-D53pHiHy.js +1 -0
  36. package/src/assets/web-panel/assets/{Marketplace-aPg8e4Jt.js → Marketplace-BILPGakp.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-C-TNlVUf.js → McpTools-DTVCOr9-.js} +5 -5
  38. package/src/assets/web-panel/assets/{Memory-DMTPIpGa.js → Memory-Hzc1iow4.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-BxyvveRq.js → MobileBridge-GXfgnGYV.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-DyPCrAyQ.js → MobileProjects-B-3TJWsS.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-BdhqNXp6.js → Mtc-DwSJMWtK.js} +5 -5
  42. package/src/assets/web-panel/assets/{MtcAudit-Cz-HFxzW.js → MtcAudit-D2uxf-DA.js} +5 -5
  43. package/src/assets/web-panel/assets/{Multisig-CIUaFNsx.js → Multisig-DG6kbKK0.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-CWe6-J17.js → NLProgramming-f5p49EDU.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-vYAKeviU.js → Notes-FUgHyzSD.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-DQL9-2d7.js → NotificationSettings-DCHGee7e.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-DnXj1jBn.js → OrderTableRenderer-Dm6LlIoa.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-B3spU8AN.js → Organization-BawA7qAg.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-DgEwo7vm.js → Overflow-D6a5wZU1.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-hujMRH8X.js → P2P-K8WavwnA.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-C_qhdg9h.js → PdhVaultBrowser-4JAJYaqx.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-vp7LMcSf.js → Permissions-BDWvi8PD.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-Dxr5Hgnq.js → PersonalDataHub-DF_K4E9i.js} +3 -3
  54. package/src/assets/web-panel/assets/{Pipeline-DEPZqqH4.js → Pipeline-BYeZlesI.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-DTpDiKPe.js → Privacy-BIHlgnIc.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-jDJsRWmF.js → ProjectInit-Cvf-6B5P.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-Dhor5RWH.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-BGs47s1a.js → Providers-CxC7JuYv.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-CjIw-wIb.js → QrScannerModal-VLf3gAfL.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-DX6jcqoi.js → QuickAsk-B5vGjRiF.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-DopXkhar.js → Recommend--UW4iYs-.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-BLvqJE9c.js → RemoteSession-DMSPcfKR.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-DhRj2Me7.js → Reputation-kQXlEHmj.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-DQ53vuPq.js → Row-CxGu3pit.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-BslvwiBD.js → RssFeed-Bi5lo8MZ.js} +2 -2
  67. package/src/assets/web-panel/assets/{Search-DJKBDNKZ.js → Search-Cq_H5RTh.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-COhpxHER.js → Security-YFbmkaQS.js} +3 -3
  69. package/src/assets/web-panel/assets/{Services-dbulD6cI.js → Services-DLOGdaLm.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-ciIVNfhC.js → Skeleton-CteIxb3D.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-AiRTkTCk.js → Skills-CccopaIZ.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-DDMcWYBc.js → Sla-AzfEQKX1.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-BPxWbpXO.js → SpeechSettings-ekGo5l77.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-BoEOXCyg.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-UowY8Ixe.js → Templates-CX1Tgeka.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-DauSLQXN.js → Tenant-Zc59jF4i.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-DBj7Jneq.js → Terminal-CXOD7y83.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-UMrPwoZC.js → TimelineRenderer-B1aBHPBo.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-4ea96-bn.js → Tokens-zALlOq_U.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger--ISCqt4b.js → Trigger-CQfJMXaq.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-D4GVimRJ.js → Trust-BU0RcM-w.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-Ci-nXRQc.js → UkeySign-IFZ3HsbH.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-Cjk7mKPw.js → VideoEditing-BzslgW0v.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-BgOLOO3Z.js → Wallet-BZAcQNS6.js} +2 -2
  86. package/src/assets/web-panel/assets/{WebAuthn-CCX0K29i.js → WebAuthn-CBK1DMi0.js} +4 -4
  87. package/src/assets/web-panel/assets/{WorkflowEditor-Ch3zgIsE.js → WorkflowEditor-BlMTPzO-.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-DKOU_2Vb.js → chat-B51-8QVn.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-6OVo4u3C.js → colors-504RTByU.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-BH78Hlsq.js → compact-item-C-GP6IQM.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-CFRpSbbC.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-DNQhgcVi.js → hasIn-DN7V-_FW.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-dDkoL4Pe.js → index--n-ZciV3.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CaYqY35Z.js → index-7jIqHbzw.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BYrnm5Ob.js → index-B2-x9bS8.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-sm7W8AXy.js → index-BFIFJ5Dr.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DKN2noIF.js → index-B_vGU-Js.js} +1 -1
  99. package/src/assets/web-panel/assets/{index--rq90rL9.js → index-Bkxhaeta.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CFPJ8yzF.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-caye7AOE.js → index-C0k_Nqg9.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BxRy5LPR.js → index-C3TSohzc.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BepBTpa8.js → index-C4DV_5uA.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-D84id2Y4.js → index-C8UltbXK.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-Y9MJv28e.js → index-C9_48OzU.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Bb6kDrUx.js → index-CKTfZyfU.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CrcLHN2F.js → index-CP2A226L.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CkNEMANR.js → index-CUhQpiYv.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Cu3L4r5l.js → index-CX78k-qf.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DaDgdJYj.js → index-CYopNjcJ.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Du0rnksC.js → index-Cao5DZy7.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BaVE6E8y.js → index-CfiEM64n.js} +3 -3
  114. package/src/assets/web-panel/assets/{index-BujsOZfc.js → index-ConjaJro.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-hPY0fFrd.js → index-CqcLo5WV.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BDSR7ecX.js → index-CySTJKeq.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BHa4WyTZ.js → index-D1phyca8.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-nbfHl1oV.js → index-D9LyiN-L.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CkqHgG-b.js → index-DA2f1UV3.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Eag8e_mA.js → index-DAOpQvl_.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-cdf7fd7d.js → index-DE-hmI2l.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-bKm3TUDp.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-7TC3S8SN.js → index-DaA__-q1.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DvHGtNnF.js → index-FcV8J_Qz.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-B_Z-YoxX.js → index-P2mfY27Z.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-AuBhLqOm.js → index-et5JIPHO.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-D3RtTT4K.js → index-f4Bo4KXm.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CNuCHHQT.js → index-kAqQXfP6.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BkN3iTTp.js → index-kt_5rfcZ.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BnnXQot_.js → index-so8eIIxF.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-HNGGVF6o.js → index-yYTQZypF.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-BZ9w6jPL.js → initDefaultProps-CPYEIdpV.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-BnwUiOho.js → motion-Cjim9pxs.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-ByUKJnNm.js → move-DuU-cgz3.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-V7yK1KEl.js → mtc-parser-DJHNAkta.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-BEXBBt4j.js → omit-DSQBgdBj.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-qDm_46Gi.js → pickAttrs-CTmT_j5m.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-BIbhEo_0.js → placementArrow-Lfm6v-r4.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-NbPbDgA_.js → responsiveObserve-CgrcPcDi.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-BnUWglZ0.js → slide-CuE3110i.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-BX8_wZI5.js → statusUtils-DiK5nbpf.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-BV4OycQX.js → styleChecker-DPEJdQaZ.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-Od_H5llY.js → useFlexGapSupport-CnnodGmp.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-BWI-PyiX.js → useFs-DWF84Yav.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-BqMuhG3g.js → usePersonalDataHub-a5b5Dw2f.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-DNd23z6f.js → vnode-DAluzXOq.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-Cjaxnm7l.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 +217 -30
  156. package/src/data/changelog.json +14 -1
  157. package/src/harness/mcp-client.js +242 -42
  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 +51 -6
  166. package/src/lib/cowork-task-runner.js +1 -0
  167. package/src/lib/mcp-headers-helper.js +76 -8
  168. package/src/lib/mcp-sandbox-policy.js +155 -0
  169. package/src/lib/mcp-stdio-execution-authority.js +163 -0
  170. package/src/lib/mcp-stdio-workspace-authority.js +252 -0
  171. package/src/lib/plugin-runtime/sandbox-policy.js +42 -2
  172. package/src/lib/process-execution-broker/index.js +179 -104
  173. package/src/lib/process-execution-broker/platform-sandbox.js +942 -168
  174. package/src/lib/process-tree-termination.js +17 -1
  175. package/src/lib/skill-mcp.js +65 -4
  176. package/src/lib/web-fetch.js +4 -4
  177. package/src/runtime/agent-runtime.js +61 -8
  178. package/src/runtime/mcp-config.js +235 -28
  179. package/src/workers/background-agent-worker.js +492 -71
  180. package/src/assets/web-panel/assets/MarkdownRenderer-Bf3DEqP6.js +0 -1
  181. package/src/assets/web-panel/assets/Projects-08xUDZGt.js +0 -1
  182. package/src/assets/web-panel/assets/Tasks-CEYFJwmr.js +0 -1
  183. package/src/assets/web-panel/assets/devWarning-DEMblAIm.js +0 -1
  184. package/src/assets/web-panel/assets/index-BTvq-36D.js +0 -1
  185. package/src/assets/web-panel/assets/index-hUpvk6Jl.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,6 +147,8 @@ 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 : [],
@@ -99,6 +156,8 @@ export function parseMcpServers(raw) {
99
156
  ...(typeof cfg.runtimeKind === "string"
100
157
  ? { runtimeKind: cfg.runtimeKind }
101
158
  : {}),
159
+ ...(cwd ? { cwd } : {}),
160
+ ...(sandboxPolicy ? { sandboxPolicy } : {}),
102
161
  url: cfg.url,
103
162
  transport: cfg.transport,
104
163
  headers:
@@ -163,6 +222,7 @@ export async function loadManagedMcp(settings, deps = {}) {
163
222
  return deps.into || null;
164
223
  }
165
224
  const servers = parseMcpServers({ mcpServers: block });
225
+ const nameReservations = mcpServerNameReservations(deps);
166
226
  for (const config of Object.values(servers)) {
167
227
  config.configScope = "managed";
168
228
  config.configSource = deps.managedFile || "managed-settings";
@@ -171,13 +231,19 @@ export async function loadManagedMcp(settings, deps = {}) {
171
231
  servers,
172
232
  "managed-settings",
173
233
  (_name, config) => config.configSource,
174
- { writeErr: deps.writeErr },
234
+ {
235
+ writeErr: deps.writeErr,
236
+ nameReservations,
237
+ },
175
238
  );
176
239
  if (Object.keys(servers).length === 0) return deps.into || null;
177
240
  (deps.writeErr || (() => {}))(
178
241
  ` mcp: ${Object.keys(servers).length} managed server(s) from ${deps.managedFile || "managed settings"}\n`,
179
242
  );
180
- return setupMcpFromConfig(servers, deps);
243
+ return setupMcpFromConfig(servers, {
244
+ ...deps,
245
+ mcpServerNameReservations: nameReservations,
246
+ });
181
247
  }
182
248
 
183
249
  function managedServerNames(value) {
@@ -275,6 +341,8 @@ export async function setupMcpFromConfig(servers, deps = {}) {
275
341
  (() =>
276
342
  new MCPClient({ eventRuntimeStore: deps.eventRuntimeStore || null }));
277
343
  servers = filterMcpServersByPolicy(servers, deps.mcpPolicy, writeErr);
344
+ const nameReservations = mcpServerNameReservations(deps);
345
+ const previouslyReservedNames = new Set(nameReservations);
278
346
 
279
347
  // `deps.into` lets a second batch (e.g. registered servers) accumulate into
280
348
  // the SAME client + channel objects as a first batch (e.g. --mcp-config), so
@@ -288,6 +356,12 @@ export async function setupMcpFromConfig(servers, deps = {}) {
288
356
  resources: [],
289
357
  prompts: [],
290
358
  };
359
+ if (!(result._mcpServerNameReservations instanceof Set)) {
360
+ Object.defineProperty(result, "_mcpServerNameReservations", {
361
+ value: nameReservations,
362
+ configurable: true,
363
+ });
364
+ }
291
365
  // Back-fill the resource/prompt accumulators when an older `deps.into` object
292
366
  // (created before this field existed) is passed in.
293
367
  if (!Array.isArray(result.resources)) result.resources = [];
@@ -329,7 +403,14 @@ export async function setupMcpFromConfig(servers, deps = {}) {
329
403
  for (const [name, cfg] of Object.entries(servers)) {
330
404
  // Skip a name already connected — an earlier batch (ad-hoc --mcp-config)
331
405
  // wins over a later one (registered) on a clash.
332
- 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);
333
414
  // Inject a stored OAuth bearer token for remote servers (`cc mcp login`),
334
415
  // unless the config already supplies an Authorization header. Best-effort:
335
416
  // no token / a refresh failure just connects unauthenticated.
@@ -652,6 +733,7 @@ export async function loadMcpConfig(filePath, deps = {}) {
652
733
  */
653
734
  export async function loadRegisteredMcp(rawDb, deps = {}) {
654
735
  if (!rawDb) return deps.into || null;
736
+ const nameReservations = mcpServerNameReservations(deps);
655
737
  let rows;
656
738
  try {
657
739
  let make = deps.makeServerConfig;
@@ -660,19 +742,79 @@ export async function loadRegisteredMcp(rawDb, deps = {}) {
660
742
  make = (db) => new MCPServerConfig(db);
661
743
  }
662
744
  const cfg = make(rawDb);
663
- 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
+ };
664
762
  if (deps.scope) visibility.scope = deps.scope;
665
- 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
+ }
666
782
  } catch {
667
783
  return deps.into || null; // registry unavailable — non-fatal
668
784
  }
669
785
  const servers = {};
670
786
  for (const r of rows || []) {
671
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
+ }
672
809
  servers[r.name] = {
673
810
  command: r.command,
674
811
  args: r.args,
675
812
  env: r.env,
813
+ ...(typeof r.runtimeKind === "string"
814
+ ? { runtimeKind: r.runtimeKind }
815
+ : {}),
816
+ ...(cwd ? { cwd } : {}),
817
+ ...(sandboxPolicy ? { sandboxPolicy } : {}),
676
818
  url: r.url,
677
819
  transport: r.transport,
678
820
  headers: r.headers,
@@ -688,9 +830,12 @@ export async function loadRegisteredMcp(rawDb, deps = {}) {
688
830
  "registered-config",
689
831
  (name, config) =>
690
832
  `${config.configScope || "user"}:${config.configSource || "user-database"}:${name}`,
691
- { writeErr: deps.writeErr },
833
+ { writeErr: deps.writeErr, nameReservations },
692
834
  );
693
- return setupMcpFromConfig(servers, deps);
835
+ return setupMcpFromConfig(servers, {
836
+ ...deps,
837
+ mcpServerNameReservations: nameReservations,
838
+ });
694
839
  }
695
840
 
696
841
  /**
@@ -718,6 +863,9 @@ export async function loadIdeMcp(opts = {}, deps = {}) {
718
863
  );
719
864
  return deps.into;
720
865
  }
866
+ if (mcpServerNameReservations(deps).has("ide")) {
867
+ return deps.into || null;
868
+ }
721
869
  const cfg = toCfg(lock);
722
870
  if (!cfg) return deps.into || null;
723
871
  const out = await setupMcpFromConfig({ ide: cfg }, deps);
@@ -766,6 +914,9 @@ export async function loadPdhMcp(opts = {}, deps = {}) {
766
914
  );
767
915
  return deps.into;
768
916
  }
917
+ if (mcpServerNameReservations(deps).has("pdh")) {
918
+ return deps.into || null;
919
+ }
769
920
  const cfg = toCfg(lock);
770
921
  if (!cfg) return deps.into || null;
771
922
  const out = await setupMcpFromConfig({ pdh: cfg }, deps);
@@ -808,6 +959,9 @@ export async function loadJetbrainsMcp(opts = {}, deps = {}) {
808
959
  );
809
960
  return deps.into;
810
961
  }
962
+ if (mcpServerNameReservations(deps).has("idea")) {
963
+ return deps.into || null;
964
+ }
811
965
  const cfg = toCfg(found);
812
966
  if (!cfg) return deps.into || null;
813
967
  const out = await setupMcpFromConfig({ idea: cfg }, deps);
@@ -868,15 +1022,17 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
868
1022
  const trust =
869
1023
  deps.projectMcpTrust ||
870
1024
  (await import("../lib/project-mcp-trust.js").catch(() => null));
871
- if (!trust) {
872
- writeErr(
873
- " mcp: SKIPPING project .mcp.json — project trust service is unavailable.\n",
874
- );
875
- return deps.into || null;
876
- }
877
-
1025
+ const nameReservations = mcpServerNameReservations(deps);
878
1026
  const servers = {};
879
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
+ };
880
1036
  for (const file of files) {
881
1037
  if (!fileExists(file)) continue;
882
1038
  let content;
@@ -888,6 +1044,14 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
888
1044
  writeErr(` mcp: ignoring malformed ${file} (${err.message})\n`);
889
1045
  continue;
890
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
+ }
891
1055
  try {
892
1056
  const check = trust.checkProjectMcpTrust(file, content);
893
1057
  if (check.status === "changed") {
@@ -897,6 +1061,7 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
897
1061
  }
898
1062
  writeErr(` mcp: ${file} re-trusted (CC_PROJECT_MCP_TRUST).\n`);
899
1063
  } else {
1064
+ blockProjectNames(rawServerNames);
900
1065
  writeErr(
901
1066
  ` mcp: SKIPPING ${file} — its content changed since it was last trusted. ` +
902
1067
  `Review the diff, then re-trust with CC_PROJECT_MCP_TRUST=1 or \`cc mcp trust-project\`.\n`,
@@ -909,13 +1074,25 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
909
1074
  }
910
1075
  }
911
1076
  } catch (err) {
1077
+ blockProjectNames(rawServerNames);
912
1078
  writeErr(
913
1079
  ` mcp: SKIPPING ${file} — project trust state is unavailable ` +
914
1080
  `(${err?.message || "unknown error"}).\n`,
915
1081
  );
916
1082
  continue;
917
1083
  }
918
- 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)));
919
1096
  if (Object.keys(parsed).length > 0) {
920
1097
  for (const [name, config] of Object.entries(parsed)) {
921
1098
  config.configScope = "project";
@@ -927,24 +1104,39 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
927
1104
  needsExecutionAuthority &&
928
1105
  typeof trust.issueProjectMcpWorkspaceAuthority !== "function"
929
1106
  ) {
1107
+ blockProjectNames([name]);
930
1108
  delete parsed[name];
931
1109
  continue;
932
1110
  }
933
1111
  if (needsExecutionAuthority) {
934
- config.projectMcpWorkspaceAuthority =
935
- trust.issueProjectMcpWorkspaceAuthority({
936
- file,
937
- content,
938
- workspaceRoot: path.dirname(file),
939
- serverName: name,
940
- config,
941
- });
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
+ }
942
1129
  }
1130
+ blockedProjectNames.delete(name);
943
1131
  }
944
1132
  Object.assign(servers, parsed); // later file (cwd) overrides earlier (root)
945
1133
  seenFiles.push(file);
946
1134
  }
947
1135
  }
1136
+ reserveMcpServerNames(nameReservations, blockedProjectNames);
1137
+ for (const name of Object.keys(servers)) {
1138
+ if (nameReservations.has(name)) delete servers[name];
1139
+ }
948
1140
  if (Object.keys(servers).length === 0) return deps.into || null;
949
1141
  writeErr(
950
1142
  ` mcp: ${Object.keys(servers).length} server(s) from project .mcp.json ` +
@@ -954,9 +1146,12 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
954
1146
  servers,
955
1147
  "project-config",
956
1148
  (name, config) => `${config.configSource}:${name}`,
957
- { writeErr },
1149
+ { writeErr, nameReservations },
958
1150
  );
959
- return setupMcpFromConfig(servers, deps);
1151
+ return setupMcpFromConfig(servers, {
1152
+ ...deps,
1153
+ mcpServerNameReservations: nameReservations,
1154
+ });
960
1155
  }
961
1156
 
962
1157
  /**
@@ -994,6 +1189,10 @@ export async function loadPluginMcp(opts = {}, deps = {}) {
994
1189
  return [name, { ...rest, ...headersHelperField(config.headersHelper) }];
995
1190
  }),
996
1191
  );
1192
+ const nameReservations = mcpServerNameReservations(deps);
1193
+ for (const name of Object.keys(servers)) {
1194
+ if (nameReservations.has(name)) delete servers[name];
1195
+ }
997
1196
  const names = Object.keys(servers || {});
998
1197
  if (names.length === 0) return deps.into || null;
999
1198
  writeErr(
@@ -1004,9 +1203,12 @@ export async function loadPluginMcp(opts = {}, deps = {}) {
1004
1203
  "trusted-plugin",
1005
1204
  (name, config) =>
1006
1205
  `${config.pluginId || "plugin"}@${config.pluginVersion || "unknown"}:${config.pluginSource || "unknown"}:${name}`,
1007
- { writeErr },
1206
+ { writeErr, nameReservations },
1008
1207
  );
1009
- return setupMcpFromConfig(servers, deps);
1208
+ return setupMcpFromConfig(servers, {
1209
+ ...deps,
1210
+ mcpServerNameReservations: nameReservations,
1211
+ });
1010
1212
  }
1011
1213
 
1012
1214
  /**
@@ -1042,6 +1244,10 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
1042
1244
  (runtimeEnv.CC_EVENT_RUNTIME_DURABLE === "1"
1043
1245
  ? new EventRuntimeStore()
1044
1246
  : null);
1247
+ const serverNameReservations =
1248
+ deps.mcpServerNameReservations instanceof Set
1249
+ ? deps.mcpServerNameReservations
1250
+ : new Set();
1045
1251
  // Thread the agent session id down to setupMcpFromConfig so spawned stdio MCP
1046
1252
  // servers get CC_SESSION_ID / CLAUDE_CODE_SESSION_ID (Claude-Code parity).
1047
1253
  let mcpPolicy = deps.mcpPolicy || null;
@@ -1063,6 +1269,7 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
1063
1269
  ...(args.sessionId != null ? { sessionId: args.sessionId } : {}),
1064
1270
  ...(eventRuntimeStore ? { eventRuntimeStore } : {}),
1065
1271
  mcpPolicy,
1272
+ mcpServerNameReservations: serverNameReservations,
1066
1273
  };
1067
1274
  let result = await doManaged(managedLoaded.settings, {
1068
1275
  ...fwd,