shadow-claw 1.27.0 → 1.28.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 (240) hide show
  1. package/.well-known/ai-catalog.json +11 -0
  2. package/.well-known/mcp/index.html +19 -0
  3. package/.well-known/mcp/server-card.json +52 -0
  4. package/.well-known/mcp/servers.json +15 -0
  5. package/.well-known/mcp.json +52 -0
  6. package/.well-known/oauth-protected-resource +10 -0
  7. package/.well-known/oauth-protected-resource.json +10 -0
  8. package/bin/assert-version-bump.mjs +61 -3
  9. package/bin/assert-version-bump.test.mjs +77 -1
  10. package/bin/build/build.mjs +116 -49
  11. package/bin/build/build.test.mjs +103 -0
  12. package/bin/cli.mjs +299 -237
  13. package/bin/cli.test.mjs +27 -0
  14. package/bin/commands/mcp.mjs +132 -2
  15. package/bin/commands/mcp.test.mjs +166 -0
  16. package/bin/commands/skills-index.mjs +139 -20
  17. package/bin/commands/skills-index.test.mjs +82 -0
  18. package/bin/utils/control-client.mjs +17 -0
  19. package/bin/utils/control-client.test.mjs +46 -0
  20. package/bin/version.mjs +208 -0
  21. package/bin/version.test.mjs +138 -0
  22. package/dist/electron/main.cjs +195 -185
  23. package/dist/lib/components/index.js +21 -21
  24. package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
  25. package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
  26. package/dist/lib/components/settings/shadow-claw-git.js +1 -1
  27. package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
  28. package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
  29. package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
  30. package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
  31. package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
  32. package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
  33. package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
  34. package/dist/lib/components/shadow-claw/shadow-claw.d.ts +1 -0
  35. package/dist/lib/components/shadow-claw/utils/setupAppLifecycle.d.ts +23 -0
  36. package/dist/lib/components/shadow-claw-channel-config.js +1 -1
  37. package/dist/lib/components/shadow-claw-channels.js +1 -1
  38. package/dist/lib/components/shadow-claw-chat.js +1 -1
  39. package/dist/lib/components/shadow-claw-control-plane.js +1 -1
  40. package/dist/lib/components/shadow-claw-conversations.js +1 -1
  41. package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
  42. package/dist/lib/components/shadow-claw-files.js +1 -1
  43. package/dist/lib/components/shadow-claw-git.js +1 -1
  44. package/dist/lib/components/shadow-claw-llm.js +1 -1
  45. package/dist/lib/components/shadow-claw-networking.js +1 -1
  46. package/dist/lib/components/shadow-claw-notifications.js +1 -1
  47. package/dist/lib/components/shadow-claw-pages.js +1 -1
  48. package/dist/lib/components/shadow-claw-peerjs.js +1 -1
  49. package/dist/lib/components/shadow-claw-settings.js +1 -1
  50. package/dist/lib/components/shadow-claw-storage.js +1 -1
  51. package/dist/lib/components/shadow-claw-task-server.js +1 -1
  52. package/dist/lib/components/shadow-claw-tasks.js +1 -1
  53. package/dist/lib/components/shadow-claw-terminal.js +1 -1
  54. package/dist/lib/components/shadow-claw-tools.js +1 -1
  55. package/dist/lib/components/shadow-claw-webvm.js +1 -1
  56. package/dist/lib/components/shadow-claw.js +1 -1
  57. package/dist/lib/{configurePeerJs-oODzltaC.js → configurePeerJs-D8Ph0-A9.js} +2 -2
  58. package/dist/lib/{configurePeerJs-oODzltaC.js.map → configurePeerJs-D8Ph0-A9.js.map} +1 -1
  59. package/dist/lib/core/control-plane-client.d.ts +2 -0
  60. package/dist/lib/core/orchestrator/orchestrator.d.ts +10 -0
  61. package/dist/lib/core/orchestrator/utils/operations/channel.d.ts +2 -2
  62. package/dist/lib/core/utils/initControlPlane.d.ts +6 -0
  63. package/dist/lib/index.js +21 -21
  64. package/dist/lib/{initControlPlane-C2zURVIS.js → initControlPlane-BIrWmpzc.js} +76 -9
  65. package/dist/lib/initControlPlane-BIrWmpzc.js.map +1 -0
  66. package/dist/lib/{markdown-C6EHl9zs.js → markdown-DEUoM1c6.js} +2 -2
  67. package/dist/lib/{markdown-C6EHl9zs.js.map → markdown-DEUoM1c6.js.map} +1 -1
  68. package/dist/lib/{orchestrator-KRjx0eba.js → orchestrator-BtVj9bBB.js} +11 -10
  69. package/dist/lib/{orchestrator-KRjx0eba.js.map → orchestrator-BtVj9bBB.js.map} +1 -1
  70. package/dist/lib/{orchestrator-CACLa_Ro.js → orchestrator-CFCW-l1O.js} +52 -4
  71. package/dist/lib/orchestrator-CFCW-l1O.js.map +1 -0
  72. package/dist/lib/{peerjs-DFWOBcXf.js → peerjs-BoBkx9DJ.js} +23 -3
  73. package/dist/lib/peerjs-BoBkx9DJ.js.map +1 -0
  74. package/dist/lib/{push-client-_tiWQsCT.js → push-client-D6hbzDNV.js} +10 -4
  75. package/dist/lib/push-client-D6hbzDNV.js.map +1 -0
  76. package/dist/lib/{shadow-claw-6UHdiy4a.js → shadow-claw-Cuf2O5bZ.js} +71 -4
  77. package/dist/lib/shadow-claw-Cuf2O5bZ.js.map +1 -0
  78. package/dist/lib/{shadow-claw-channel-config-DmfwJc6G.js → shadow-claw-channel-config-BDPKt6Bd.js} +3 -3
  79. package/dist/lib/{shadow-claw-channel-config-DmfwJc6G.js.map → shadow-claw-channel-config-BDPKt6Bd.js.map} +1 -1
  80. package/dist/lib/{shadow-claw-channels-1N6Jl-By.js → shadow-claw-channels-BsP5JABM.js} +2 -2
  81. package/dist/lib/{shadow-claw-channels-1N6Jl-By.js.map → shadow-claw-channels-BsP5JABM.js.map} +1 -1
  82. package/dist/lib/{shadow-claw-chat-BMoqQJRK.js → shadow-claw-chat-Cam2lX4k.js} +4 -4
  83. package/dist/lib/{shadow-claw-chat-BMoqQJRK.js.map → shadow-claw-chat-Cam2lX4k.js.map} +1 -1
  84. package/dist/lib/{shadow-claw-control-plane-UG0o7pCz.js → shadow-claw-control-plane-DB2qcCFs.js} +20 -10
  85. package/dist/lib/shadow-claw-control-plane-DB2qcCFs.js.map +1 -0
  86. package/dist/lib/{shadow-claw-conversations-BwXep3iu.js → shadow-claw-conversations-C9Vf4XGx.js} +2 -2
  87. package/dist/lib/{shadow-claw-conversations-BwXep3iu.js.map → shadow-claw-conversations-C9Vf4XGx.js.map} +1 -1
  88. package/dist/lib/{shadow-claw-file-viewer-DUxzVxDT.js → shadow-claw-file-viewer-B4HYiI0v.js} +3 -3
  89. package/dist/lib/{shadow-claw-file-viewer-DUxzVxDT.js.map → shadow-claw-file-viewer-B4HYiI0v.js.map} +1 -1
  90. package/dist/lib/{shadow-claw-files-DIREEnT2.js → shadow-claw-files-DVROUESO.js} +2 -2
  91. package/dist/lib/{shadow-claw-files-DIREEnT2.js.map → shadow-claw-files-DVROUESO.js.map} +1 -1
  92. package/dist/lib/{shadow-claw-git-Bg1SWgsF.js → shadow-claw-git-BqrO7cHJ.js} +3 -3
  93. package/dist/lib/{shadow-claw-git-Bg1SWgsF.js.map → shadow-claw-git-BqrO7cHJ.js.map} +1 -1
  94. package/dist/lib/{shadow-claw-llm-CazBrVpM.js → shadow-claw-llm-BexUQdYo.js} +2 -2
  95. package/dist/lib/{shadow-claw-llm-CazBrVpM.js.map → shadow-claw-llm-BexUQdYo.js.map} +1 -1
  96. package/dist/lib/{shadow-claw-networking-Df85tCbO.js → shadow-claw-networking-CfXRGpUD.js} +2 -2
  97. package/dist/lib/{shadow-claw-networking-Df85tCbO.js.map → shadow-claw-networking-CfXRGpUD.js.map} +1 -1
  98. package/dist/lib/{shadow-claw-notifications-v62FryTc.js → shadow-claw-notifications-C9KPMgx_.js} +2 -2
  99. package/dist/lib/{shadow-claw-notifications-v62FryTc.js.map → shadow-claw-notifications-C9KPMgx_.js.map} +1 -1
  100. package/dist/lib/{shadow-claw-pages-BgPyIEZO.js → shadow-claw-pages-CGzGXmrI.js} +3 -3
  101. package/dist/lib/{shadow-claw-pages-BgPyIEZO.js.map → shadow-claw-pages-CGzGXmrI.js.map} +1 -1
  102. package/dist/lib/{shadow-claw-peerjs-xkBXILed.js → shadow-claw-peerjs-B0ZB7yhB.js} +3 -3
  103. package/dist/lib/{shadow-claw-peerjs-xkBXILed.js.map → shadow-claw-peerjs-B0ZB7yhB.js.map} +1 -1
  104. package/dist/lib/{shadow-claw-settings-CN89xRVU.js → shadow-claw-settings-DBfMZdDS.js} +2 -2
  105. package/dist/lib/{shadow-claw-settings-CN89xRVU.js.map → shadow-claw-settings-DBfMZdDS.js.map} +1 -1
  106. package/dist/lib/{shadow-claw-storage-VnhcObCe.js → shadow-claw-storage-CM-w6mgG.js} +2 -2
  107. package/dist/lib/{shadow-claw-storage-VnhcObCe.js.map → shadow-claw-storage-CM-w6mgG.js.map} +1 -1
  108. package/dist/lib/{shadow-claw-task-server-jgEC2hHB.js → shadow-claw-task-server-DV4b1g2-.js} +4 -2
  109. package/dist/lib/{shadow-claw-task-server-jgEC2hHB.js.map → shadow-claw-task-server-DV4b1g2-.js.map} +1 -1
  110. package/dist/lib/{shadow-claw-tasks-i_evIufy.js → shadow-claw-tasks-K-foOHSE.js} +3 -3
  111. package/dist/lib/{shadow-claw-tasks-i_evIufy.js.map → shadow-claw-tasks-K-foOHSE.js.map} +1 -1
  112. package/dist/lib/{shadow-claw-terminal-CwScROlu.js → shadow-claw-terminal-CpAknKyA.js} +2 -2
  113. package/dist/lib/{shadow-claw-terminal-CwScROlu.js.map → shadow-claw-terminal-CpAknKyA.js.map} +1 -1
  114. package/dist/lib/{shadow-claw-tools-DD3fyXP4.js → shadow-claw-tools-D98XZ0Ep.js} +3 -3
  115. package/dist/lib/{shadow-claw-tools-DD3fyXP4.js.map → shadow-claw-tools-D98XZ0Ep.js.map} +1 -1
  116. package/dist/lib/{shadow-claw-webvm-DbJq4I3-.js → shadow-claw-webvm-DLOb8dMI.js} +2 -2
  117. package/dist/lib/{shadow-claw-webvm-DbJq4I3-.js.map → shadow-claw-webvm-DLOb8dMI.js.map} +1 -1
  118. package/dist/lib/subsystems/channels/imessage.d.ts +1 -0
  119. package/dist/lib/subsystems/channels/peerjs.d.ts +1 -0
  120. package/dist/lib/subsystems/channels/telegram.d.ts +1 -0
  121. package/dist/lib/subsystems/channels/types.d.ts +2 -0
  122. package/dist/lib/subsystems/notifications/push-client.d.ts +1 -1
  123. package/dist/lib/{syncWebMcpRegistration-DNLnQ-jz.js → syncWebMcpRegistration-NspKefOI.js} +2 -2
  124. package/dist/lib/{syncWebMcpRegistration-DNLnQ-jz.js.map → syncWebMcpRegistration-NspKefOI.js.map} +1 -1
  125. package/dist/public/.well-known/ai-catalog.json +11 -0
  126. package/dist/public/.well-known/mcp/index.html +19 -0
  127. package/dist/public/.well-known/mcp/server-card.json +52 -0
  128. package/dist/public/.well-known/mcp/servers.json +15 -0
  129. package/dist/public/.well-known/mcp.json +52 -0
  130. package/dist/public/.well-known/oauth-protected-resource +10 -0
  131. package/dist/public/.well-known/oauth-protected-resource.json +10 -0
  132. package/dist/public/404.html +28 -1
  133. package/dist/public/AGENTS.md +1 -1
  134. package/dist/public/agent.worker.js +1 -1
  135. package/dist/public/{configurePeerJs-BqgeBjP7.js → configurePeerJs-BhBokQlC.js} +1 -1
  136. package/dist/public/docs/example/article/index.html +3 -3
  137. package/dist/public/docs/publishing/index.html +3 -3
  138. package/dist/public/docs/skill-creator/index.html +3 -3
  139. package/dist/public/docs/subsystems/cli.md +11 -8
  140. package/dist/public/docs/subsystems/mcp-server.md +1 -0
  141. package/dist/public/docs/subsystems/notifications.md +10 -0
  142. package/dist/public/{e2e-bridge-Ceqr5kGc.js → e2e-bridge-DcBoeFvd.js} +1 -1
  143. package/dist/public/{file-viewer-C-6Jc_tb.js → file-viewer-CKtVC9Ix.js} +1 -1
  144. package/dist/public/index.css +1 -1
  145. package/dist/public/index.html +3 -3
  146. package/dist/public/index.js +1 -1
  147. package/dist/public/initControlPlane-Bi8ouFEb.js +1 -0
  148. package/dist/public/llms.txt +36 -1
  149. package/dist/public/main/index.html +3 -3
  150. package/dist/public/main/memory/index.html +3 -3
  151. package/dist/public/{markdown-C3M4OW_A.js → markdown-C-hCVJtc.js} +1 -1
  152. package/dist/public/orchestrator-8qNGfw8r.js +15 -0
  153. package/dist/public/{orchestrator-DHjdLtqa.js → orchestrator-BT3Ks5ip.js} +2 -2
  154. package/dist/public/peerjs-DfhwEiiq.js +1 -0
  155. package/dist/public/push-client-BVLrE9pK.js +1 -0
  156. package/dist/public/service-worker/fetch-proxy.js +1 -1
  157. package/dist/public/service-worker.js +1 -1
  158. package/dist/public/{shadow-claw-EAt2ml5Y.js → shadow-claw-DCjxNDCX.js} +3 -3
  159. package/dist/public/{shadow-claw-channels-XsfuWFF8.js → shadow-claw-channels-CITDrqMl.js} +1 -1
  160. package/dist/public/{shadow-claw-chat-CbSaOZ4q.js → shadow-claw-chat-BQrSgSKF.js} +1 -1
  161. package/dist/public/{shadow-claw-control-plane-DHvN3Ukg.js → shadow-claw-control-plane-Cp001OY0.js} +2 -2
  162. package/dist/public/{shadow-claw-conversations-BWs5VVfs.js → shadow-claw-conversations-EhX4RvIj.js} +1 -1
  163. package/dist/public/{shadow-claw-file-viewer-BWsoW5QS.js → shadow-claw-file-viewer-DiQXIjZD.js} +1 -1
  164. package/dist/public/{shadow-claw-files-CG7MqWiV.js → shadow-claw-files-lkTnSJsn.js} +1 -1
  165. package/dist/public/{shadow-claw-git-DBRPZNav.js → shadow-claw-git-BlcA_z8x.js} +2 -2
  166. package/dist/public/{shadow-claw-llm-DMvLgKXo.js → shadow-claw-llm-CW16X9Rg.js} +1 -1
  167. package/dist/public/{shadow-claw-networking-Dd8Rw31D.js → shadow-claw-networking-ySsMBY_i.js} +1 -1
  168. package/dist/public/{shadow-claw-notifications-Dbevj-lq.js → shadow-claw-notifications-CyV2zCQ8.js} +1 -1
  169. package/dist/public/{shadow-claw-pages-3_lQAv0t.js → shadow-claw-pages-Cx7cF9ah.js} +1 -1
  170. package/dist/public/{shadow-claw-settings-t8TIlgrM.js → shadow-claw-settings-zm4PHHGi.js} +2 -2
  171. package/dist/public/{shadow-claw-storage-CfEXoSIE.js → shadow-claw-storage-dy9JAEGd.js} +1 -1
  172. package/dist/public/{shadow-claw-task-server-DxQSsgRZ.js → shadow-claw-task-server-Bleww48s.js} +2 -2
  173. package/dist/public/{shadow-claw-tasks-DNpicQwz.js → shadow-claw-tasks-CTI5oaLN.js} +1 -1
  174. package/dist/public/{shadow-claw-terminal-DpY6zU_r.js → shadow-claw-terminal-mZ3i4HaQ.js} +1 -1
  175. package/dist/public/{shadow-claw-tools-WSwWohnk.js → shadow-claw-tools-B_nuk8Zl.js} +1 -1
  176. package/dist/public/{shadow-claw-webvm-CP6oFjg5.js → shadow-claw-webvm-Vl_jH5YL.js} +1 -1
  177. package/dist/public/{syncWebMcpRegistration-DOn9gLnD.js → syncWebMcpRegistration-n2vAMJ4w.js} +1 -1
  178. package/dist/server.js +197 -187
  179. package/package.json +2 -1
  180. package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.test.ts +6 -0
  181. package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.ts +19 -9
  182. package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.test.ts +14 -0
  183. package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.ts +12 -0
  184. package/src/components/shadow-claw/shadow-claw.ts +6 -0
  185. package/src/components/shadow-claw/utils/bindEventListeners.test.ts +57 -0
  186. package/src/components/shadow-claw/utils/bindEventListeners.ts +14 -0
  187. package/src/components/shadow-claw/utils/setupAppLifecycle.test.ts +201 -0
  188. package/src/components/shadow-claw/utils/setupAppLifecycle.ts +101 -0
  189. package/src/core/control-plane-client.test.ts +82 -1
  190. package/src/core/control-plane-client.ts +35 -1
  191. package/src/core/orchestrator/orchestrator.test.ts +49 -0
  192. package/src/core/orchestrator/orchestrator.ts +43 -0
  193. package/src/core/orchestrator/utils/operations/channel.test.ts +17 -0
  194. package/src/core/orchestrator/utils/operations/channel.ts +11 -5
  195. package/src/core/orchestrator/utils/operations/task.test.ts +26 -0
  196. package/src/core/orchestrator/utils/operations/task.ts +8 -1
  197. package/src/core/utils/initControlPlane.test.ts +138 -0
  198. package/src/core/utils/initControlPlane.ts +82 -0
  199. package/src/core/utils/initializeApp.test.ts +27 -1
  200. package/src/core/utils/initializeApp.ts +6 -13
  201. package/src/server/mcp/mcp-server.test.ts +6 -0
  202. package/src/server/mcp/mcp-server.ts +2 -1
  203. package/src/server/mcp/tools/built-in-tools.ts +88 -1
  204. package/src/server/mcp/tools/client-tool-relay.ts +6 -0
  205. package/src/server/mcp/tools/mcp-tools.test.ts +128 -0
  206. package/src/server/openapi/openapi-coverage.test.ts +2 -1
  207. package/src/server/openapi/openapi-spec.ts +2 -1
  208. package/src/server/openapi/paths/mcp.ts +104 -0
  209. package/src/server/openapi/paths/push.ts +3 -0
  210. package/src/server/routes/mcp.test.ts +92 -0
  211. package/src/server/routes/mcp.ts +138 -2
  212. package/src/server/utils/packageVersion.test.ts +10 -0
  213. package/src/server/utils/packageVersion.ts +32 -0
  214. package/src/service-worker/fetch-proxy-rules.test.ts +73 -0
  215. package/src/service-worker/fetch-proxy-rules.ts +44 -0
  216. package/src/service-worker/fetch-proxy.ts +1 -1
  217. package/src/subsystems/channels/imessage.test.ts +36 -0
  218. package/src/subsystems/channels/imessage.ts +11 -0
  219. package/src/subsystems/channels/peerjs.test.ts +56 -0
  220. package/src/subsystems/channels/peerjs.ts +29 -0
  221. package/src/subsystems/channels/telegram.test.ts +38 -0
  222. package/src/subsystems/channels/telegram.ts +13 -0
  223. package/src/subsystems/channels/types.ts +2 -0
  224. package/src/subsystems/notifications/push-client.test.ts +70 -0
  225. package/src/subsystems/notifications/push-client.ts +28 -3
  226. package/src/subsystems/notifications/push-routes.test.ts +82 -0
  227. package/src/subsystems/notifications/push-routes.ts +70 -16
  228. package/src/subsystems/notifications/push-store.test.ts +59 -0
  229. package/src/subsystems/notifications/push-store.ts +113 -19
  230. package/src/testing/jest-setup.ts +15 -0
  231. package/dist/lib/initControlPlane-C2zURVIS.js.map +0 -1
  232. package/dist/lib/orchestrator-CACLa_Ro.js.map +0 -1
  233. package/dist/lib/peerjs-DFWOBcXf.js.map +0 -1
  234. package/dist/lib/push-client-_tiWQsCT.js.map +0 -1
  235. package/dist/lib/shadow-claw-6UHdiy4a.js.map +0 -1
  236. package/dist/lib/shadow-claw-control-plane-UG0o7pCz.js.map +0 -1
  237. package/dist/public/initControlPlane-BN9cWyO0.js +0 -1
  238. package/dist/public/orchestrator-CMbCTjBf.js +0 -15
  239. package/dist/public/peerjs-DUCKH-m9.js +0 -1
  240. package/dist/public/push-client-D0lkwrK0.js +0 -1
@@ -0,0 +1 @@
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{r as t}from"./config-CrHchneq.js";import{i as n}from"./app-routes-Bs-riIvr.js";import{n as r}from"./txPromise-EBECky1b.js";import{t as i}from"./ulid-BY7rQVLN.js";import{t as a}from"./browser-nBz_r6l4.js";import{t as o}from"./getAllTasks-vpBlgGsc.js";var s=e(a(),1),c=class{_transport;_url;_httpUrl;_token;_clientId;_peerId;_deviceLabel;_capabilities;_version;_heartbeatIntervalMs;_reconnectDelayMs;_maxReconnectDelayMs;_handlers;_WebSocketClass;_EventSourceClass;_fetchFn;_ws=null;_es=null;_heartbeatTimer=null;_reconnectTimer=null;_currentReconnectDelay;_isDestroyed=!1;_state=`disconnected`;constructor(e){if(this._transport=e.transport||`sse`,this._clientId=e.clientId,this._peerId=e.peerId,this._deviceLabel=e.deviceLabel||`ShadowClaw Browser Client`,this._capabilities=e.capabilities||[`webmcp`,`opfs`,`push`],this._version=e.version||`1.27.1`,this._token=e.token,this._heartbeatIntervalMs=e.heartbeatIntervalMs||1e4,this._reconnectDelayMs=e.reconnectDelayMs||1e3,this._maxReconnectDelayMs=e.maxReconnectDelayMs||3e4,this._currentReconnectDelay=this._reconnectDelayMs,this._handlers=new Map,this._WebSocketClass=e.WebSocketClass||(typeof WebSocket<`u`?WebSocket:null),this._EventSourceClass=e.EventSourceClass||(typeof EventSource<`u`?EventSource:null),this._fetchFn=e.fetchFn||(typeof fetch<`u`?fetch.bind(globalThis):(()=>Promise.reject(Error(`fetch not available`)))),e.handlers)for(let[t,n]of Object.entries(e.handlers))this.registerHandler(t,n);let t=typeof location<`u`?location:null,n=t?`${t.protocol}//${t.host}`:`http://127.0.0.1:8888`,r=t?`${t.protocol===`https:`?`wss:`:`ws:`}//${t.host}`:`ws://127.0.0.1:8888`;this._url=e.url||`${r}/ws/control`,this._httpUrl=e.httpUrl||n}get transport(){return this._transport}get version(){return this._version}registerHandler(e,t){this._handlers.set(e,t)}unregisterHandler(e){this._handlers.delete(e)}getState(){return this._state}ensureConnected(e=!1){if(this._isDestroyed=!1,this._reconnectTimer&&=(clearTimeout(this._reconnectTimer),null),this._currentReconnectDelay=this._reconnectDelayMs,this._transport===`websocket`){let t=this._ws&&(this._ws.readyState===1||this._ws.readyState===this._WebSocketClass?.OPEN);(e||!t||this._state!==`connected`)&&(this._cleanupConnection(),this.connect())}else{let t=this._es&&(this._es.readyState===1||this._es.readyState===this._EventSourceClass?.OPEN);(e||!t||this._state!==`connected`)&&(this._cleanupConnection(),this.connect())}}connect(){this._isDestroyed||this._state===`connected`||this._state===`connecting`||(this._transport===`websocket`?this._connectWebSocket():this._connectSse())}_connectWebSocket(){if(!this._WebSocketClass){console.warn(`[ControlPlaneClient] WebSocket not supported in this environment`);return}this._state=`connecting`;let e=new URL(this._url,`ws://127.0.0.1:8888`);this._token&&e.searchParams.set(`token`,this._token);try{let t=new this._WebSocketClass(e.toString());this._ws=t,t.onopen=()=>{this._state=`connected`,this._currentReconnectDelay=this._reconnectDelayMs,this._sendRegister(),this._startHeartbeat()},t.onmessage=e=>{this._handleMessage(e.data)},t.onclose=()=>{this._cleanupConnection(),this._isDestroyed||this._scheduleReconnect()},t.onerror=e=>{console.warn(`[ControlPlaneClient] WebSocket error:`,e)}}catch(e){console.warn(`[ControlPlaneClient] Failed to establish WebSocket connection:`,e),this._cleanupConnection(),this._scheduleReconnect()}}_connectSse(){if(!this._EventSourceClass){(s.default===void 0||!s.default.env?.JEST_WORKER_ID)&&console.warn(`[ControlPlaneClient] EventSource not supported in this environment`);return}this._state=`connecting`;let e=new URL(`/api/control/events`,this._httpUrl);e.searchParams.set(`clientId`,this._clientId),this._token&&e.searchParams.set(`token`,this._token);try{let t=new this._EventSourceClass(e.toString());this._es=t,t.onopen=()=>{this._state=`connected`,this._currentReconnectDelay=this._reconnectDelayMs,this._sendRegister(),this._startHeartbeat()},typeof t.addEventListener==`function`&&t.addEventListener(`command:execute`,e=>{this._handleMessage(e.data)}),t.onmessage=e=>{this._handleMessage(e.data)},t.onerror=e=>{console.warn(`[ControlPlaneClient] SSE connection error:`,e),this._cleanupConnection(),this._isDestroyed||this._scheduleReconnect()}}catch(e){console.warn(`[ControlPlaneClient] Failed to establish SSE connection:`,e),this._cleanupConnection(),this._scheduleReconnect()}}disconnect(){this._isDestroyed=!0;try{this._sendUnregister()}catch{}this._cleanupConnection(),this._reconnectTimer&&=(clearTimeout(this._reconnectTimer),null)}_cleanupConnection(){if(this._state=`disconnected`,this._stopHeartbeat(),this._ws){try{this._ws.close()}catch{}this._ws=null}if(this._es){try{this._es.close()}catch{}this._es=null}}_scheduleReconnect(){this._reconnectTimer||this._isDestroyed||(this._reconnectTimer=setTimeout(()=>{this._reconnectTimer=null,this._isDestroyed||this.connect()},this._currentReconnectDelay),this._currentReconnectDelay=Math.min(this._currentReconnectDelay*1.5,this._maxReconnectDelayMs))}_startHeartbeat(){this._stopHeartbeat(),this._heartbeatTimer=setInterval(()=>{this._sendHeartbeat()},this._heartbeatIntervalMs)}_stopHeartbeat(){this._heartbeatTimer&&=(clearInterval(this._heartbeatTimer),null)}_sendRegister(){let e={clientId:this._clientId,deviceLabel:this._deviceLabel,capabilities:this._capabilities,version:this._version,transport:this._transport,peerId:this._peerId};this._sendMessage({id:i(),type:`client:register`,payload:e})}_sendHeartbeat(){let e={clientId:this._clientId,timestamp:Date.now()};this._sendMessage({id:i(),type:`client:heartbeat`,payload:e})}_sendUnregister(){if(!this._clientId)return;let e={clientId:this._clientId};this._sendMessage({id:i(),type:`client:unregister`,payload:e})}_sendMessage(e){if(this._transport===`websocket`){this._ws&&(this._ws.readyState===1||this._ws.readyState===this._WebSocketClass?.OPEN)&&this._ws.send(JSON.stringify(e));return}let t=new URL(`/api/control/messages`,this._httpUrl),n={"Content-Type":`application/json`};this._token&&(n[`x-control-token`]=this._token,n.Authorization=`Bearer ${this._token}`);let r={method:`POST`,headers:n,body:JSON.stringify(e)},i=t.hostname.toLowerCase(),a=i===`localhost`||i===`127.0.0.1`||i===`::1`||i===`[::1]`,o=/^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.)/.test(i);a?r.targetAddressSpace=`loopback`:o&&(r.targetAddressSpace=`private`),this._fetchFn(t.toString(),r).catch(e=>{console.warn(`[ControlPlaneClient] Failed to send message via HTTP POST:`,e)})}async _handleMessage(e){if(!e||typeof e!=`string`)return;let t;try{t=JSON.parse(e)}catch{return}if(t.type===`command:execute`){let{commandId:e,action:n,args:r}=t.payload,a=this._handlers.get(n);if(!a){this._sendMessage({id:i(),type:`command:result`,replyTo:t.id,payload:{commandId:e,success:!1,error:`Unknown action: ${n}`}});return}try{let n=await a(r);this._sendMessage({id:i(),type:`command:result`,replyTo:t.id,payload:{commandId:e,success:!0,data:n}})}catch(n){this._sendMessage({id:i(),type:`command:result`,replyTo:t.id,payload:{commandId:e,success:!1,error:n.message||String(n)}})}}}};function l(){if(typeof localStorage<`u`)try{let e=localStorage.getItem(t.CONTROL_PLANE_CLIENT_ID);if(e&&e.trim())return e.trim()}catch{}let e=n(),r=e?`${e}-${i().toLowerCase()}`:`client-${i().toLowerCase()}`;if(typeof localStorage<`u`)try{localStorage.setItem(t.CONTROL_PLANE_CLIENT_ID,r)}catch{}return r}async function u(e){if(typeof localStorage<`u`)try{let e=localStorage.getItem(t.CONTROL_PLANE_ENABLED);if(e!==null)return e===`true`||e===`1`}catch{}if(e)try{let{getConfig:n}=await import(`./getConfig-D89uJgo5.js`).then(e=>e.n),r=await n(e,t.CONTROL_PLANE_ENABLED);if(r!=null)return r===`true`||r===`1`}catch{}return!1}function d(e){if(typeof EventSource>`u`&&typeof WebSocket>`u`)return!1;let t=e||(typeof location<`u`?location:null);return!(!t||t.protocol===`file:`||typeof document<`u`&&document.querySelector(`meta[name="shadowclaw-static-only"]`))}function f(e){let n=``;if(typeof localStorage<`u`)try{n=(localStorage.getItem(t.CONTROL_PLANE_URL)||``).trim()}catch{}let r=e||(typeof location<`u`?location:null),i=r&&(r.protocol===`file:`||r.hostname&&(r.hostname.endsWith(`.github.io`)||r.hostname.endsWith(`.pages.dev`))),a=n;a||=i?`http://127.0.0.1:8888`:r&&r.host?`${r.protocol}//${r.host}`:`http://127.0.0.1:8888`,a=a.replace(/\/+$/,``);let o=a.replace(/^https?:/,e=>e===`https:`?`wss:`:`ws:`);return{httpUrl:a,wsUrl:`${o}/ws/control`}}function p(){let e=[];return typeof navigator<`u`&&(navigator.storage&&typeof navigator.storage.getDirectory==`function`&&e.push(`opfs`),`serviceWorker`in navigator&&typeof window<`u`&&`PushManager`in window&&e.push(`push`),(typeof document<`u`&&document.modelContext||navigator&&navigator.modelContext)&&e.push(`webmcp`)),typeof RTCPeerConnection<`u`&&e.push(`peerjs`),e}function m(){if(typeof navigator>`u`)return`ShadowClaw Node`;let e=navigator.userAgent,t=`Desktop`;/iPad/i.test(e)?t=`iPad`:/iPhone/i.test(e)?t=`iPhone`:/Android/i.test(e)?t=`Android`:/Macintosh/i.test(e)?t=`Mac`:/Windows/i.test(e)?t=`Windows`:/Linux/i.test(e)&&(t=`Linux`);let n=`Browser`;return/Chrome/i.test(e)&&!/Edg/i.test(e)?n=`Chrome`:/Safari/i.test(e)&&!/Chrome/i.test(e)?n=`Safari`:/Firefox/i.test(e)?n=`Firefox`:/Edg/i.test(e)&&(n=`Edge`),`${t} ${n}`}function h(){let e=``,t=``;typeof document<`u`&&(e=document.querySelector(`meta[name="version"]`)?.getAttribute(`content`)?.trim()||``,t=document.querySelector(`meta[name="revision"]`)?.getAttribute(`content`)?.trim()||``);let n=t.length>7?t.slice(0,7):t;return e&&n?`${e} (${n})`:e||n||`1.27.1`}let g=null;async function _(e,t={},n={}){let i=l(),a=m(),s=p();switch(e){case`send-message`:{if(!t.text)throw Error(`Missing text parameter`);let{orchestratorStore:e}=await import(`./orchestrator-BT3Ks5ip.js`).then(e=>e.n),r=n.orchestrator||e.orchestrator,i=t.groupId||e.activeGroupId||`br:main`;return r?.browserChat?.submit?(r.browserChat.submit(t.text,i),{queued:!0,groupId:i}):r?.submitMessage?(r.submitMessage(t.text,i),{queued:!0,groupId:i}):e.sendMessage?(e.sendMessage(t.text),{queued:!0,groupId:i}):{queued:!1,error:`Orchestrator not ready`}}case`list-tasks`:{let e=await o(await r());return t?.groupId&&(e=e.filter(e=>e.groupId===t.groupId)),{tasks:e}}case`read-state`:{let{orchestratorStore:e}=await import(`./orchestrator-BT3Ks5ip.js`).then(e=>e.n),t=n.orchestrator||e.orchestrator;return{clientId:i,deviceLabel:a,capabilities:s,version:n.version||h(),activeGroupId:n.orchestrator?.activeGroupId||e.activeGroupId||t?.activeGroupId||`br:main`,state:n.orchestrator?.state||e.state||t?.state||`idle`}}case`list-tools`:{try{let{getWebMcpTools:e}=await import(`./webmcp-DAjmliCx.js`).then(e=>e.a),t=await e();if(t&&t.length>0)return{tools:t.map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema,annotations:e.annotations}))}}catch{}try{let{orchestratorStore:e}=await import(`./orchestrator-BT3Ks5ip.js`).then(e=>e.n),r=n.orchestrator||e.orchestrator||(typeof document<`u`?document.querySelector(`shadow-claw`)?.orchestrator:null),i=t.groupId||r?.activeGroupId||e.activeGroupId||`br:main`,a=e.groups.find(e=>e.groupId===i);if(a?.toolTags&&a.toolTags.length>0){let{TOOL_DEFINITIONS:e}=await import(`./tools-C8x3nmo4.js`).then(e=>e.n),{parseWebMcpInputSchema:t}=await import(`./webmcp-DAjmliCx.js`).then(e=>e.a);return{tools:e.filter(e=>a.toolTags.includes(e.name)).map(e=>({name:e.name,description:e.description,inputSchema:t(e.input_schema)}))}}}catch{}let{TOOL_DEFINITIONS:e}=await import(`./tools-C8x3nmo4.js`).then(e=>e.n),{parseWebMcpInputSchema:r}=await import(`./webmcp-DAjmliCx.js`).then(e=>e.a);return{tools:e.map(e=>({name:e.name,description:e.description,inputSchema:r(e.input_schema)}))}}case`invoke-tool`:{if(!t.toolName)throw Error(`Missing toolName parameter`);try{let{orchestratorStore:e}=await import(`./orchestrator-BT3Ks5ip.js`).then(e=>e.n),{toolsStore:r}=await import(`./tools-DvckJZG2.js`).then(e=>e.n),i=n.orchestrator||e.orchestrator||(typeof document<`u`?document.querySelector(`shadow-claw`)?.orchestrator:null),a=t.groupId||i?.activeGroupId||e.activeGroupId||`br:main`,o=e.groups.find(e=>e.groupId===a);if(o?.toolTags&&o.toolTags.length>0){if(!o.toolTags.includes(t.toolName))throw Error(`Tool '${t.toolName}' is not enabled in the active conversation (${a}).`)}else if(r?.allTools&&r.allTools.some(e=>e.name===t.toolName)&&r?.enabledToolNames&&r.enabledToolNames.size>0){let e=r.enabledToolNames.has(t.toolName),n=r.isDeclarativeToolEnabled(t.toolName);if(!e&&!n)throw Error(`Tool '${t.toolName}' is not enabled on this client.`)}}catch(e){if(e.message&&e.message.includes(`is not enabled`))throw e}let e=typeof document<`u`&&document.modelContext||typeof navigator<`u`&&navigator.modelContext;if(e){let n;if(typeof e.getTools==`function`)try{let r=await e.getTools();if(Array.isArray(r)&&r.length>0){if(n=r.find(e=>e.name===t.toolName),!n)throw Error(`Tool '${t.toolName}' is not enabled or registered on this client.`)}else n=Array.isArray(r)?r.find(e=>e.name===t.toolName):void 0;if(n&&typeof n.execute==`function`)return{result:await n.execute(typeof t.input==`string`?JSON.parse(t.input):t.input||{})}}catch(e){if(e.message&&e.message.includes(`is not enabled`))throw e}let r=typeof t.input==`string`?t.input:JSON.stringify(t.input||{});if(typeof e.executeTool==`function`){if(n)try{return{result:await e.executeTool(n,r)}}catch{}try{return{result:await e.executeTool({name:t.toolName},r)}}catch{}try{return{result:await e.executeTool(t.toolName,r)}}catch{}}if(typeof navigator<`u`&&navigator.modelContextTesting&&typeof navigator.modelContextTesting.executeTool==`function`)try{return{result:await navigator.modelContextTesting.executeTool(t.toolName,r)}}catch{}if(typeof e.callTool==`function`)try{return{result:await e.callTool({name:t.toolName,arguments:typeof t.input==`string`?JSON.parse(t.input):t.input||{}})}}catch{}if(typeof e.invoke==`function`)try{return{result:await e.invoke(t.toolName,typeof t.input==`string`?JSON.parse(t.input):t.input||{})}}catch{}}let{orchestratorStore:r}=await import(`./orchestrator-BT3Ks5ip.js`).then(e=>e.n),i=n.orchestrator||r.orchestrator||(typeof document<`u`?document.querySelector(`shadow-claw`)?.orchestrator:null),a=i?.agentWorker;if(a&&typeof a.postMessage==`function`){let e=Date.now().toString(36)+Math.random().toString(36).slice(2),n=t.toolName===`ask_user`,r=t.timeoutMs||(n?3e5:6e4);return{result:await new Promise((n,o)=>{let s=setTimeout(()=>{a.removeEventListener(`message`,c),o(Error(`Timeout waiting for tool execution`))},r),c=t=>{let r=t.data;r&&r.type===`execute-tool-result`&&r.callId===e&&(clearTimeout(s),a.removeEventListener(`message`,c),r.error?o(Error(r.error)):n(r.result))};a.addEventListener(`message`,c),a.postMessage({type:`execute-tool`,callId:e,payload:{name:t.toolName,input:typeof t.input==`string`?JSON.parse(t.input):t.input||{},groupId:t.groupId||i?.activeGroupId||`br:main`}})})}}throw Error(`Tool ${t.toolName} could not be executed (no context or worker available)`)}case`trigger-backup`:{let{orchestratorStore:e}=await import(`./orchestrator-BT3Ks5ip.js`).then(e=>e.n),a=t.groupId||n.orchestrator?.activeGroupId||e.activeGroupId||`br:main`,o=await r(),{getGroupDir:s}=await import(`./getGroupDir-P1h9wl6S.js`).then(e=>e.n),c=await s(o,a);async function l(e,t=``){let n=[];for await(let[r,i]of e.entries()){let e=t?`${t}/${r}`:r;if(i.kind===`directory`){let t=await l(i,e);n.push(...t)}else n.push(e)}return n}async function u(e){try{let t=e.split(`/`),n=c;for(let e=0;e<t.length-1;e++)n=await n.getDirectoryHandle(t[e]);let r=await(await(await n.getFileHandle(t[t.length-1])).getFile()).arrayBuffer();return new Uint8Array(r)}catch{return null}}let{BackupController:d}=await import(`./backup-controller-CvzDOq4T.js`);return await new d({clientId:i,token:t.token,serverBaseUrl:f().httpUrl,fileEnumerator:()=>l(c),fileReader:e=>u(e)}).initiate()}default:throw Error(`Unknown action '${e}'`)}}function v(e={}){if(g){try{g.disconnect()}catch{}g=null}let n=e.clientId&&e.clientId.trim()||l(),r=p(),i=m(),a=e.version||h(),o=null;if(typeof localStorage<`u`)try{let e=localStorage.getItem(t.CONTROL_PLANE_TRANSPORT);(e===`sse`||e===`websocket`)&&(o=e)}catch{}let s=e.transport||o||`sse`,u;if(typeof localStorage<`u`)try{u=localStorage.getItem(t.PEERJS_MY_PEER_ID)||void 0}catch{}let{httpUrl:v,wsUrl:y}=f(),b=new c({clientId:n,deviceLabel:i,capabilities:r,version:a,peerId:u,transport:s,httpUrl:v,url:y,handlers:{"send-message":t=>_(`send-message`,t,e),"list-tasks":t=>_(`list-tasks`,t,e),"read-state":t=>_(`read-state`,t,e),"invoke-tool":t=>_(`invoke-tool`,t,e),"list-tools":t=>_(`list-tools`,t,e),"trigger-backup":t=>_(`trigger-backup`,t,e)}});return e.autoConnect!==!1&&d()&&b.connect(),g=b,b}function y(){return g}function b(){if(g){try{g.disconnect()}catch{}g=null}}async function x(e={}){let n=e.db;if(!n)try{n=await r()}catch{}if(!await u(n))return b(),null;if(!d())return null;if(typeof localStorage<`u`&&n)try{let{getConfig:e}=await import(`./getConfig-D89uJgo5.js`).then(e=>e.n),[r,i]=await Promise.all([e(n,t.CONTROL_PLANE_URL),e(n,t.CONTROL_PLANE_TRANSPORT)]);r&&localStorage.setItem(t.CONTROL_PLANE_URL,r),i&&localStorage.setItem(t.CONTROL_PLANE_TRANSPORT,i),localStorage.setItem(t.CONTROL_PLANE_ENABLED,`true`)}catch{}let i=y();return i?(i.ensureConnected(e.force),i):v(e)}export{x as ensureControlPlaneConnected,_ as executeClientControlCommand,u as isControlPlaneEnabled,d as shouldConnectControlPlane,b as stopControlPlaneClient};
@@ -1,6 +1,32 @@
1
1
  # [ShadowClaw](https://xt-ml.github.io/shadow-claw/)
2
2
 
3
- > A browser-native, fully-featured AI assistant whose core orchestration and tool-use loop run client-side in the browser. Deployable as a PWA or native Electron desktop app, backed by a Node.js service layer (local proxying, control plane, MCP), and driven via the `shadow-claw` CLI. AI inference routes to remote APIs, local servers, or in-browser models depending on your configuration.
3
+ > A browser-native AI assistant featuring client-side orchestration of the full agentic loop (reasoning, state machine, dynamic context windowing, and tool execution) running off the main thread in a Web Worker in the browser or Electron. Instantly launchable via `npx shadow-claw dev --open`, driven by a full-featured CLI, and backed by a 24/7 Node.js service layer (control plane, task scheduler, proxying, and MCP).
4
+
5
+ ## Quick Start & CLI
6
+
7
+ Run instantly without cloning the repo:
8
+
9
+ - `npx shadow-claw dev --open` — Start local services and launch the assistant in your browser immediately.
10
+ - `npx shadow-claw init <dir>` — Scaffold a custom template or knowledge hub.
11
+ - `npx shadow-claw server` — Run headless 24/7 backend services (task scheduler, MCP, REST API).
12
+ - `npx shadow-claw send "prompt"` — Dispatch prompts to connected clients directly from your terminal.
13
+ - [CLI Reference](https://xt-ml.github.io/shadow-claw/docs/subsystems/cli.md) — Complete guide to all CLI commands, flags, and control plane options.
14
+
15
+ ## When to Use This
16
+
17
+ ShadowClaw is best suited for:
18
+
19
+ - **Client-side orchestration of the agentic loop:** When you want the entire agent decision loop—state machine, prompt assembly, dynamic context windowing, and tool dispatch—to execute client-side off the main thread in a browser Web Worker or Electron.
20
+ - **Zero-install instant launch & CLI driving:** Starting immediately with `npx shadow-claw dev --open`, scaffolding custom templates with `npx shadow-claw init`, or driving connected browser sessions, tasks, and backups through the `shadow-claw` CLI.
21
+ - **Ultra-safe sandboxed execution:** Running real code, bash, and system operations inside isolated client-side environments—including an in-browser WebVM (v86 Alpine Linux running in WASM inside a Web Worker), `just-bash` POSIX emulation, and sandboxed OPFS/IndexedDB storage.
22
+ - **Control plane & client bridge:** Driving browser and Electron execution surfaces from external tools, scripts, or CLI commands via real-time SSE, WebSockets, or WebRTC.
23
+ - **Headless server & background services:** Running a persistent 24/7 Node backend (`shadow-claw server`) to manage client schedules in SQLite, tick cron schedules, wake dormant clients via Web Push, and serve REST APIs and MCP endpoints.
24
+ - **Model Context Protocol (MCP) integrations:** Interfacing with external coding agents (Claude Desktop, Cursor, Goose) via STDIO or Streamable HTTP.
25
+ - **Static knowledge hubs:** Authoring and deploying static documentation and agent-assisted knowledge repositories.
26
+
27
+ When to look elsewhere:
28
+
29
+ - Workloads requiring an unsandboxed, host-native server agent where the entire LLM prompt/tool execution loop must run directly against the server's bare-metal OS rather than sandboxed client execution surfaces.
4
30
 
5
31
  ## Docs
6
32
 
@@ -16,6 +42,15 @@
16
42
  - [Storage System](https://xt-ml.github.io/shadow-claw/docs/architecture/storage.md)
17
43
  - [Context Management](https://xt-ml.github.io/shadow-claw/docs/architecture/context-management.md)
18
44
  - [Streaming](https://xt-ml.github.io/shadow-claw/docs/architecture/streaming.md)
45
+ - [Control Plane & Client Bridge](https://xt-ml.github.io/shadow-claw/docs/subsystems/control-plane.md)
46
+
47
+ ## MCP & Discovery
48
+
49
+ - [MCP Server Card (SEP-2127)](https://xt-ml.github.io/shadow-claw/.well-known/mcp.json): Standardized remote MCP discovery document
50
+ - [AI Catalog (SEP-2127)](https://xt-ml.github.io/shadow-claw/.well-known/ai-catalog.json): Decentralized AI artifact catalog
51
+ - [MCP Servers Manifest (Discussion #1147)](https://xt-ml.github.io/shadow-claw/.well-known/mcp/servers.json): Server endpoint manifest
52
+ - [Protected Resource Metadata (RFC 9728)](https://xt-ml.github.io/shadow-claw/.well-known/oauth-protected-resource): OAuth PRM discovery
53
+ - [Stateless MCP Server Subsystem](https://xt-ml.github.io/shadow-claw/docs/subsystems/mcp-server.md): Complete architectural documentation for MCP Streamable HTTP & STDIO transports
19
54
 
20
55
  ## Optional
21
56