shadow-claw 1.28.0 → 1.29.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.
- package/.well-known/mcp/server-card.json +1 -1
- package/.well-known/mcp.json +1 -1
- package/README.md +96 -278
- package/bin/cli.mjs +4 -0
- package/bin/commands/mcp.mjs +409 -125
- package/bin/commands/mcp.test.mjs +151 -18
- package/bin/utils/control-client.mjs +338 -103
- package/bin/utils/control-client.test.mjs +14 -0
- package/dist/electron/main.cjs +179 -179
- package/dist/lib/components/index.js +21 -21
- package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
- package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
- package/dist/lib/components/settings/shadow-claw-git.js +1 -1
- package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
- package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
- package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
- package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
- package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
- package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
- package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
- package/dist/lib/components/shadow-claw-channel-config.js +1 -1
- package/dist/lib/components/shadow-claw-channels.js +1 -1
- package/dist/lib/components/shadow-claw-chat.js +1 -1
- package/dist/lib/components/shadow-claw-control-plane.js +1 -1
- package/dist/lib/components/shadow-claw-conversations.js +1 -1
- package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
- package/dist/lib/components/shadow-claw-files.js +1 -1
- package/dist/lib/components/shadow-claw-git.js +1 -1
- package/dist/lib/components/shadow-claw-llm.js +1 -1
- package/dist/lib/components/shadow-claw-networking.js +1 -1
- package/dist/lib/components/shadow-claw-notifications.js +1 -1
- package/dist/lib/components/shadow-claw-pages.js +1 -1
- package/dist/lib/components/shadow-claw-peerjs.js +1 -1
- package/dist/lib/components/shadow-claw-settings.js +1 -1
- package/dist/lib/components/shadow-claw-storage.js +1 -1
- package/dist/lib/components/shadow-claw-task-server.js +1 -1
- package/dist/lib/components/shadow-claw-tasks.js +1 -1
- package/dist/lib/components/shadow-claw-terminal.js +1 -1
- package/dist/lib/components/shadow-claw-tools.js +1 -1
- package/dist/lib/components/shadow-claw-webvm.js +1 -1
- package/dist/lib/components/shadow-claw.js +1 -1
- package/dist/lib/{configurePeerJs-D8Ph0-A9.js → configurePeerJs-DG4hliKp.js} +2 -2
- package/dist/lib/{configurePeerJs-D8Ph0-A9.js.map → configurePeerJs-DG4hliKp.js.map} +1 -1
- package/dist/lib/index.js +21 -21
- package/dist/lib/{initControlPlane-BIrWmpzc.js → initControlPlane-DnpAzphg.js} +8 -8
- package/dist/lib/{initControlPlane-BIrWmpzc.js.map → initControlPlane-DnpAzphg.js.map} +1 -1
- package/dist/lib/{markdown-DEUoM1c6.js → markdown-DgdSt2GD.js} +2 -2
- package/dist/lib/{markdown-DEUoM1c6.js.map → markdown-DgdSt2GD.js.map} +1 -1
- package/dist/lib/{orchestrator-CFCW-l1O.js → orchestrator-CjEau_RG.js} +5 -5
- package/dist/lib/{orchestrator-CFCW-l1O.js.map → orchestrator-CjEau_RG.js.map} +1 -1
- package/dist/lib/{orchestrator-BtVj9bBB.js → orchestrator-ClXbJ4Mb.js} +2 -2
- package/dist/lib/{orchestrator-BtVj9bBB.js.map → orchestrator-ClXbJ4Mb.js.map} +1 -1
- package/dist/lib/{peerjs-BoBkx9DJ.js → peerjs-BdfpltIe.js} +3 -3
- package/dist/lib/{peerjs-BoBkx9DJ.js.map → peerjs-BdfpltIe.js.map} +1 -1
- package/dist/lib/{push-client-D6hbzDNV.js → push-client-DjwKknNg.js} +9 -3
- package/dist/lib/push-client-DjwKknNg.js.map +1 -0
- package/dist/lib/{shadow-claw-Cuf2O5bZ.js → shadow-claw-DcPGKenn.js} +4 -4
- package/dist/lib/{shadow-claw-Cuf2O5bZ.js.map → shadow-claw-DcPGKenn.js.map} +1 -1
- package/dist/lib/{shadow-claw-channel-config-BDPKt6Bd.js → shadow-claw-channel-config-DEL-aZ7N.js} +3 -3
- package/dist/lib/{shadow-claw-channel-config-BDPKt6Bd.js.map → shadow-claw-channel-config-DEL-aZ7N.js.map} +1 -1
- package/dist/lib/{shadow-claw-channels-BsP5JABM.js → shadow-claw-channels-BgaJiPdE.js} +2 -2
- package/dist/lib/{shadow-claw-channels-BsP5JABM.js.map → shadow-claw-channels-BgaJiPdE.js.map} +1 -1
- package/dist/lib/{shadow-claw-chat-Cam2lX4k.js → shadow-claw-chat-mXPQZbwT.js} +4 -4
- package/dist/lib/{shadow-claw-chat-Cam2lX4k.js.map → shadow-claw-chat-mXPQZbwT.js.map} +1 -1
- package/dist/lib/{shadow-claw-control-plane-DB2qcCFs.js → shadow-claw-control-plane-DO6foOLV.js} +6 -6
- package/dist/lib/{shadow-claw-control-plane-DB2qcCFs.js.map → shadow-claw-control-plane-DO6foOLV.js.map} +1 -1
- package/dist/lib/{shadow-claw-conversations-C9Vf4XGx.js → shadow-claw-conversations-BLwHTwdW.js} +2 -2
- package/dist/lib/{shadow-claw-conversations-C9Vf4XGx.js.map → shadow-claw-conversations-BLwHTwdW.js.map} +1 -1
- package/dist/lib/{shadow-claw-file-viewer-B4HYiI0v.js → shadow-claw-file-viewer-BSbZvSl-.js} +3 -3
- package/dist/lib/{shadow-claw-file-viewer-B4HYiI0v.js.map → shadow-claw-file-viewer-BSbZvSl-.js.map} +1 -1
- package/dist/lib/{shadow-claw-files-DVROUESO.js → shadow-claw-files-BLVr9Pua.js} +2 -2
- package/dist/lib/{shadow-claw-files-DVROUESO.js.map → shadow-claw-files-BLVr9Pua.js.map} +1 -1
- package/dist/lib/{shadow-claw-git-BqrO7cHJ.js → shadow-claw-git-CHC1H86J.js} +3 -3
- package/dist/lib/{shadow-claw-git-BqrO7cHJ.js.map → shadow-claw-git-CHC1H86J.js.map} +1 -1
- package/dist/lib/{shadow-claw-llm-BexUQdYo.js → shadow-claw-llm-CKXfxd3D.js} +2 -2
- package/dist/lib/{shadow-claw-llm-BexUQdYo.js.map → shadow-claw-llm-CKXfxd3D.js.map} +1 -1
- package/dist/lib/{shadow-claw-networking-CfXRGpUD.js → shadow-claw-networking-dpYvfchh.js} +2 -2
- package/dist/lib/{shadow-claw-networking-CfXRGpUD.js.map → shadow-claw-networking-dpYvfchh.js.map} +1 -1
- package/dist/lib/{shadow-claw-notifications-C9KPMgx_.js → shadow-claw-notifications-_YeAVPga.js} +2 -2
- package/dist/lib/{shadow-claw-notifications-C9KPMgx_.js.map → shadow-claw-notifications-_YeAVPga.js.map} +1 -1
- package/dist/lib/{shadow-claw-pages-CGzGXmrI.js → shadow-claw-pages-DVzZriZ7.js} +3 -3
- package/dist/lib/{shadow-claw-pages-CGzGXmrI.js.map → shadow-claw-pages-DVzZriZ7.js.map} +1 -1
- package/dist/lib/{shadow-claw-peerjs-B0ZB7yhB.js → shadow-claw-peerjs-BvixjeBz.js} +3 -3
- package/dist/lib/{shadow-claw-peerjs-B0ZB7yhB.js.map → shadow-claw-peerjs-BvixjeBz.js.map} +1 -1
- package/dist/lib/{shadow-claw-settings-DBfMZdDS.js → shadow-claw-settings-DV9-gD4Q.js} +2 -2
- package/dist/lib/{shadow-claw-settings-DBfMZdDS.js.map → shadow-claw-settings-DV9-gD4Q.js.map} +1 -1
- package/dist/lib/{shadow-claw-storage-CM-w6mgG.js → shadow-claw-storage-Bv__kXG6.js} +2 -2
- package/dist/lib/{shadow-claw-storage-CM-w6mgG.js.map → shadow-claw-storage-Bv__kXG6.js.map} +1 -1
- package/dist/lib/{shadow-claw-task-server-DV4b1g2-.js → shadow-claw-task-server-DNOe8PWK.js} +2 -2
- package/dist/lib/{shadow-claw-task-server-DV4b1g2-.js.map → shadow-claw-task-server-DNOe8PWK.js.map} +1 -1
- package/dist/lib/{shadow-claw-tasks-K-foOHSE.js → shadow-claw-tasks-qmcDT4PU.js} +3 -3
- package/dist/lib/{shadow-claw-tasks-K-foOHSE.js.map → shadow-claw-tasks-qmcDT4PU.js.map} +1 -1
- package/dist/lib/{shadow-claw-terminal-CpAknKyA.js → shadow-claw-terminal-0QUWP8of.js} +2 -2
- package/dist/lib/{shadow-claw-terminal-CpAknKyA.js.map → shadow-claw-terminal-0QUWP8of.js.map} +1 -1
- package/dist/lib/{shadow-claw-tools-D98XZ0Ep.js → shadow-claw-tools-Bs_bmI6-.js} +3 -3
- package/dist/lib/{shadow-claw-tools-D98XZ0Ep.js.map → shadow-claw-tools-Bs_bmI6-.js.map} +1 -1
- package/dist/lib/{shadow-claw-webvm-DLOb8dMI.js → shadow-claw-webvm-DYaoL7QY.js} +2 -2
- package/dist/lib/{shadow-claw-webvm-DLOb8dMI.js.map → shadow-claw-webvm-DYaoL7QY.js.map} +1 -1
- package/dist/lib/{syncWebMcpRegistration-NspKefOI.js → syncWebMcpRegistration-BhbqI6R2.js} +2 -2
- package/dist/lib/{syncWebMcpRegistration-NspKefOI.js.map → syncWebMcpRegistration-BhbqI6R2.js.map} +1 -1
- package/dist/public/.well-known/mcp/server-card.json +1 -1
- package/dist/public/.well-known/mcp.json +1 -1
- package/dist/public/AGENTS.md +22 -3
- package/dist/public/README.md +96 -278
- package/dist/public/agent.worker.js +50 -50
- package/dist/public/{base-task-model-CYkpwnvU-DDfHUUIS.js → base-task-model-CYkpwnvU-DrXr4G1R.js} +1 -1
- package/dist/public/{configurePeerJs-BhBokQlC.js → configurePeerJs-B470pdeU.js} +1 -1
- package/dist/public/docs/README.md +31 -31
- package/dist/public/docs/architecture/context-management.md +7 -0
- package/dist/public/docs/architecture/storage.md +10 -1
- package/dist/public/docs/decisions/bundled-typescript-architecture.md +0 -1
- package/dist/public/docs/decisions/native-web-components-and-signals.md +0 -1
- package/dist/public/docs/example/article/index.html +1 -1
- package/dist/public/docs/guides/publishing-to-github-pages.md +334 -0
- package/dist/public/docs/guides/server-development-configuration.md +15 -0
- package/dist/public/docs/publishing/index.html +1 -1
- package/dist/public/docs/skill-creator/index.html +1 -1
- package/dist/public/docs/subsystems/cli.md +10 -2
- package/dist/public/docs/subsystems/control-plane.md +9 -8
- package/dist/public/docs/subsystems/crypto.md +9 -0
- package/dist/public/docs/subsystems/custom-element-security.md +2 -0
- package/dist/public/docs/subsystems/mcp-server.md +31 -16
- package/dist/public/docs/subsystems/notifications.md +8 -5
- package/dist/public/docs/subsystems/providers.md +9 -0
- package/dist/public/docs/subsystems/share-target.md +107 -0
- package/dist/public/docs/subsystems/webmcp.md +43 -0
- package/dist/public/e2e/README.md +4 -2
- package/dist/public/{e2e-bridge-DcBoeFvd.js → e2e-bridge-CSW0S5Yz.js} +1 -1
- package/dist/public/{file-viewer-CKtVC9Ix.js → file-viewer-Cs-riNvy.js} +1 -1
- package/dist/public/{firebase-OSDX3viP.js → firebase-cwAl_ABm.js} +1 -1
- package/dist/public/{git-CkhCJonj.js → git-GD09WATp.js} +25 -25
- package/dist/public/index.html +1 -1
- package/dist/public/index.js +1 -1
- package/dist/public/{initControlPlane-Bi8ouFEb.js → initControlPlane-BqCY0NQy.js} +1 -1
- package/dist/public/initControlPlane-C-IXaKYX.js +1 -0
- package/dist/public/{language-detector-BRKrlra0.js → language-detector-CIeEuQFk.js} +1 -1
- package/dist/public/llms.txt +4 -2
- package/dist/public/main/index.html +1 -1
- package/dist/public/main/memory/index.html +1 -1
- package/dist/public/{markdown-C-hCVJtc.js → markdown-Cw7vCtTg.js} +1 -1
- package/dist/public/{openai-Bpd71Oja.js → openai-BJIb2c5j.js} +3 -3
- package/dist/public/{orchestrator-8qNGfw8r.js → orchestrator-BWkHHO9Y.js} +1 -1
- package/dist/public/{orchestrator-BT3Ks5ip.js → orchestrator-DpkkeD6T.js} +1 -1
- package/dist/public/{peerjs-DfhwEiiq.js → peerjs-tf2EmWjB.js} +1 -1
- package/dist/public/{prompt-api-polyfill-Dl1kbJhR.js → prompt-api-polyfill-CXd75leW.js} +1 -1
- package/dist/public/{push-client-BVLrE9pK.js → push-client-CHjSbrWs.js} +1 -1
- package/dist/public/{rewriter-j6D9LDER.js → rewriter-BEHn9gll.js} +1 -1
- package/dist/public/service-worker.js +1 -1
- package/dist/public/{shadow-claw-DCjxNDCX.js → shadow-claw-BBPV_9X8.js} +2 -2
- package/dist/public/{shadow-claw-channels-CITDrqMl.js → shadow-claw-channels-BJvrKQjg.js} +1 -1
- package/dist/public/{shadow-claw-chat-BQrSgSKF.js → shadow-claw-chat-BG2EaRaw.js} +1 -1
- package/dist/public/{shadow-claw-control-plane-Cp001OY0.js → shadow-claw-control-plane-BBa7WbTg.js} +2 -2
- package/dist/public/{shadow-claw-conversations-EhX4RvIj.js → shadow-claw-conversations-CFaWFmkm.js} +1 -1
- package/dist/public/{shadow-claw-file-viewer-DiQXIjZD.js → shadow-claw-file-viewer-Z-GIKaE9.js} +1 -1
- package/dist/public/{shadow-claw-files-lkTnSJsn.js → shadow-claw-files-BBx4iMsk.js} +1 -1
- package/dist/public/{shadow-claw-git-BlcA_z8x.js → shadow-claw-git-vTOKatwd.js} +2 -2
- package/dist/public/{shadow-claw-llm-CW16X9Rg.js → shadow-claw-llm-Ce1Ax6-x.js} +1 -1
- package/dist/public/{shadow-claw-networking-ySsMBY_i.js → shadow-claw-networking-q4XIzdB5.js} +1 -1
- package/dist/public/{shadow-claw-notifications-CyV2zCQ8.js → shadow-claw-notifications-D2cz0gmm.js} +1 -1
- package/dist/public/{shadow-claw-pages-Cx7cF9ah.js → shadow-claw-pages-3335lmSC.js} +1 -1
- package/dist/public/{shadow-claw-settings-zm4PHHGi.js → shadow-claw-settings-4ptYuJwO.js} +2 -2
- package/dist/public/{shadow-claw-storage-dy9JAEGd.js → shadow-claw-storage-bIrPKFhF.js} +1 -1
- package/dist/public/{shadow-claw-task-server-Bleww48s.js → shadow-claw-task-server-5yqVBxy1.js} +1 -1
- package/dist/public/{shadow-claw-tasks-CTI5oaLN.js → shadow-claw-tasks-DcqYHPLZ.js} +1 -1
- package/dist/public/{shadow-claw-terminal-mZ3i4HaQ.js → shadow-claw-terminal-fARaDONr.js} +1 -1
- package/dist/public/{shadow-claw-tools-B_nuk8Zl.js → shadow-claw-tools-paEAhcJr.js} +1 -1
- package/dist/public/{shadow-claw-webvm-Vl_jH5YL.js → shadow-claw-webvm-CbzH_vyX.js} +1 -1
- package/dist/public/{summarizer-VJNr-7xG.js → summarizer-BT3AuFed.js} +1 -1
- package/dist/public/{syncWebMcpRegistration-n2vAMJ4w.js → syncWebMcpRegistration-CWSYaHex.js} +1 -1
- package/dist/public/{transformers-BhQMWQG5.js → transformers-1VTxqKjT.js} +1 -1
- package/dist/public/{translator-DEQXb7ZL.js → translator-B50RYlFt.js} +1 -1
- package/dist/public/{webllm-CHN5H-Sy.js → webllm-FmyJWWpt.js} +1 -1
- package/dist/public/{writer-CD9oN2pq.js → writer-Bhb4YYRE.js} +1 -1
- package/dist/server.js +205 -203
- package/package.json +1 -1
- package/src/components/settings/shadow-claw-llm/shadow-claw-llm.test.ts +2 -0
- package/src/core/orchestrator/utils/configurePeerJs.test.ts +2 -0
- package/src/server/client-registry.test.ts +9 -0
- package/src/server/client-registry.ts +14 -0
- package/src/server/mcp/mcp-integration.test.ts +68 -16
- package/src/server/mcp/tools/built-in-tools.ts +125 -34
- package/src/server/mcp/tools/client-tool-relay.ts +81 -44
- package/src/server/mcp/tools/mcp-tools.test.ts +103 -13
- package/src/server/mcp/types.ts +3 -0
- package/src/server/openapi/paths/push.ts +48 -0
- package/src/server/server.ts +30 -0
- package/src/subsystems/notifications/push-client.test.ts +17 -0
- package/src/subsystems/notifications/push-client.ts +22 -2
- package/src/subsystems/notifications/push-routes.test.ts +31 -0
- package/src/subsystems/notifications/push-routes.ts +10 -0
- package/src/subsystems/notifications/push-store.test.ts +49 -0
- package/src/subsystems/notifications/push-store.ts +45 -0
- package/src/worker/worker.test.ts +2 -0
- package/dist/lib/push-client-D6hbzDNV.js.map +0 -1
package/bin/commands/mcp.mjs
CHANGED
|
@@ -25,9 +25,24 @@ function getCliVersion() {
|
|
|
25
25
|
return "1.27.1";
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
export const MCP_CLIENT_TOOL_PREFIX = "shadowclaw_client_";
|
|
29
|
+
export const MCP_SERVER_TOOL_PREFIX = "shadowclaw_server_";
|
|
30
|
+
|
|
31
|
+
function getClientRawToolName(name) {
|
|
32
|
+
return typeof name === "string" && name.startsWith(MCP_CLIENT_TOOL_PREFIX)
|
|
33
|
+
? name.slice(MCP_CLIENT_TOOL_PREFIX.length)
|
|
34
|
+
: name;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function toClientExposedToolName(name) {
|
|
38
|
+
return typeof name === "string" && !name.startsWith(MCP_CLIENT_TOOL_PREFIX)
|
|
39
|
+
? `${MCP_CLIENT_TOOL_PREFIX}${name}`
|
|
40
|
+
: name;
|
|
41
|
+
}
|
|
42
|
+
|
|
28
43
|
export const CLI_BUILTIN_TOOLS = [
|
|
29
44
|
{
|
|
30
|
-
name: "
|
|
45
|
+
name: "shadowclaw_server_list_clients",
|
|
31
46
|
description:
|
|
32
47
|
"List connected browser and Electron clients, including device type, ID, and active capabilities.",
|
|
33
48
|
inputSchema: {
|
|
@@ -36,7 +51,7 @@ export const CLI_BUILTIN_TOOLS = [
|
|
|
36
51
|
},
|
|
37
52
|
},
|
|
38
53
|
{
|
|
39
|
-
name: "
|
|
54
|
+
name: "shadowclaw_server_send_message",
|
|
40
55
|
description:
|
|
41
56
|
"Send a message or prompt to a connected ShadowClaw client's active AI orchestrator queue.",
|
|
42
57
|
inputSchema: {
|
|
@@ -61,7 +76,7 @@ export const CLI_BUILTIN_TOOLS = [
|
|
|
61
76
|
},
|
|
62
77
|
},
|
|
63
78
|
{
|
|
64
|
-
name: "
|
|
79
|
+
name: "shadowclaw_server_read_state",
|
|
65
80
|
description:
|
|
66
81
|
"Read the current orchestrator state, active group ID, and capabilities from a connected client.",
|
|
67
82
|
inputSchema: {
|
|
@@ -75,7 +90,7 @@ export const CLI_BUILTIN_TOOLS = [
|
|
|
75
90
|
},
|
|
76
91
|
},
|
|
77
92
|
{
|
|
78
|
-
name: "
|
|
93
|
+
name: "shadowclaw_server_list_tasks",
|
|
79
94
|
description:
|
|
80
95
|
"List scheduled background tasks configured on a connected client.",
|
|
81
96
|
inputSchema: {
|
|
@@ -87,7 +102,7 @@ export const CLI_BUILTIN_TOOLS = [
|
|
|
87
102
|
},
|
|
88
103
|
},
|
|
89
104
|
{
|
|
90
|
-
name: "
|
|
105
|
+
name: "shadowclaw_server_set_active_client",
|
|
91
106
|
description:
|
|
92
107
|
"Set the active default connected client used when no clientId is explicitly provided in tool calls.",
|
|
93
108
|
inputSchema: {
|
|
@@ -103,7 +118,7 @@ export const CLI_BUILTIN_TOOLS = [
|
|
|
103
118
|
},
|
|
104
119
|
},
|
|
105
120
|
{
|
|
106
|
-
name: "
|
|
121
|
+
name: "shadowclaw_server_manage_backup",
|
|
107
122
|
description:
|
|
108
123
|
"Trigger or manage OPFS workspace backups for a connected client (trigger, list, or delete).",
|
|
109
124
|
inputSchema: {
|
|
@@ -121,7 +136,16 @@ export const CLI_BUILTIN_TOOLS = [
|
|
|
121
136
|
},
|
|
122
137
|
},
|
|
123
138
|
{
|
|
124
|
-
name: "
|
|
139
|
+
name: "shadowclaw_server_status",
|
|
140
|
+
description:
|
|
141
|
+
"Query ShadowClaw Node server status, version, and active client count.",
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: "object",
|
|
144
|
+
properties: {},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: "shadowclaw_server_send_notification",
|
|
125
149
|
description:
|
|
126
150
|
"Broadcast an OS-level push notification to subscribed devices via Web Push (VAPID), or send to a specific registered client. Works even when the client browser tab is closed, asleep, or running in the background.",
|
|
127
151
|
inputSchema: {
|
|
@@ -232,17 +256,19 @@ export function createCliMcpEngine(options = {}) {
|
|
|
232
256
|
Array.isArray(res.data.tools)
|
|
233
257
|
) {
|
|
234
258
|
for (const t of res.data.tools) {
|
|
259
|
+
const rawName = getClientRawToolName(t.name);
|
|
235
260
|
if (
|
|
236
|
-
|
|
237
|
-
|
|
261
|
+
rawName === "send_notification" ||
|
|
262
|
+
(rawName.startsWith("shadowclaw_") &&
|
|
263
|
+
!rawName.startsWith("shadowclaw_client_"))
|
|
238
264
|
) {
|
|
239
265
|
continue;
|
|
240
266
|
}
|
|
241
|
-
if (!toolDefMap.has(
|
|
242
|
-
toolDefMap.set(
|
|
243
|
-
toolSupportingClientsMap.set(
|
|
267
|
+
if (!toolDefMap.has(rawName)) {
|
|
268
|
+
toolDefMap.set(rawName, t);
|
|
269
|
+
toolSupportingClientsMap.set(rawName, []);
|
|
244
270
|
}
|
|
245
|
-
toolSupportingClientsMap.get(
|
|
271
|
+
toolSupportingClientsMap.get(rawName).push(c);
|
|
246
272
|
}
|
|
247
273
|
}
|
|
248
274
|
} catch (_) {}
|
|
@@ -251,8 +277,8 @@ export function createCliMcpEngine(options = {}) {
|
|
|
251
277
|
const activeTargetId = await resolveTargetId();
|
|
252
278
|
const relayedTools = [];
|
|
253
279
|
|
|
254
|
-
for (const [
|
|
255
|
-
const supportingClients = toolSupportingClientsMap.get(
|
|
280
|
+
for (const [rawToolName, t] of toolDefMap.entries()) {
|
|
281
|
+
const supportingClients = toolSupportingClientsMap.get(rawToolName) || [];
|
|
256
282
|
const supportingClientIds = supportingClients
|
|
257
283
|
.map((cl) => cl.clientId || cl.id)
|
|
258
284
|
.filter(Boolean);
|
|
@@ -286,10 +312,13 @@ export function createCliMcpEngine(options = {}) {
|
|
|
286
312
|
: ` [Client: ${toolDefaultLabel} (${toolDefaultId.slice(0, 14)}...)]`
|
|
287
313
|
: "";
|
|
288
314
|
|
|
315
|
+
const exposedName = toClientExposedToolName(rawToolName);
|
|
316
|
+
|
|
289
317
|
relayedTools.push({
|
|
290
|
-
name:
|
|
318
|
+
name: exposedName,
|
|
291
319
|
description:
|
|
292
|
-
(t.description ||
|
|
320
|
+
(t.description ||
|
|
321
|
+
`Relayed tool '${rawToolName}' from connected client.`) +
|
|
293
322
|
clientNote,
|
|
294
323
|
inputSchema: {
|
|
295
324
|
...existingSchema,
|
|
@@ -355,6 +384,39 @@ export function createCliMcpEngine(options = {}) {
|
|
|
355
384
|
}
|
|
356
385
|
|
|
357
386
|
case "tools/list": {
|
|
387
|
+
let pushClients = [];
|
|
388
|
+
try {
|
|
389
|
+
if (typeof client.listPushClients === "function") {
|
|
390
|
+
pushClients = await client.listPushClients();
|
|
391
|
+
} else if (typeof client.listPushSubscriptions === "function") {
|
|
392
|
+
const subs = await client.listPushSubscriptions();
|
|
393
|
+
if (Array.isArray(subs)) {
|
|
394
|
+
const map = new Map();
|
|
395
|
+
for (const sub of subs) {
|
|
396
|
+
const cid =
|
|
397
|
+
(sub.client_id || "").trim() ||
|
|
398
|
+
(sub.id ? String(sub.id) : "");
|
|
399
|
+
if (cid && !map.has(cid)) {
|
|
400
|
+
map.set(cid, {
|
|
401
|
+
clientId: cid,
|
|
402
|
+
deviceLabel: sub.device_label || undefined,
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
pushClients = Array.from(map.values());
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
} catch (_) {}
|
|
410
|
+
|
|
411
|
+
const sortedPushClients = Array.isArray(pushClients)
|
|
412
|
+
? [...pushClients].sort((a, b) =>
|
|
413
|
+
(a.clientId || "").localeCompare(b.clientId || ""),
|
|
414
|
+
)
|
|
415
|
+
: [];
|
|
416
|
+
const pushClientIds = sortedPushClients
|
|
417
|
+
.map((c) => c.clientId)
|
|
418
|
+
.filter(Boolean);
|
|
419
|
+
|
|
358
420
|
const relayed = await getRelayedTools();
|
|
359
421
|
const combined = new Map();
|
|
360
422
|
for (const t of CLI_BUILTIN_TOOLS) {
|
|
@@ -366,6 +428,32 @@ export function createCliMcpEngine(options = {}) {
|
|
|
366
428
|
}
|
|
367
429
|
}
|
|
368
430
|
|
|
431
|
+
if (pushClientIds.length > 0) {
|
|
432
|
+
for (const targetName of [
|
|
433
|
+
"shadowclaw_server_send_notification",
|
|
434
|
+
"shadowclaw_send_notification",
|
|
435
|
+
]) {
|
|
436
|
+
const existing = combined.get(targetName);
|
|
437
|
+
if (existing) {
|
|
438
|
+
combined.set(targetName, {
|
|
439
|
+
...existing,
|
|
440
|
+
inputSchema: {
|
|
441
|
+
...existing.inputSchema,
|
|
442
|
+
type: "object",
|
|
443
|
+
properties: {
|
|
444
|
+
...(existing.inputSchema?.properties || {}),
|
|
445
|
+
clientId: {
|
|
446
|
+
type: "string",
|
|
447
|
+
description: `Target client ID, prefix, or device label of a specific client registered for push notifications (optional; if omitted, broadcasts to all subscribed devices). Available on: ${sortedPushClients.map((c) => `${c.clientId} (${c.deviceLabel || "Client"})`).join(", ")}`,
|
|
448
|
+
enum: pushClientIds,
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
369
457
|
const sortedTools = Array.from(combined.values()).sort((a, b) =>
|
|
370
458
|
a.name.localeCompare(b.name),
|
|
371
459
|
);
|
|
@@ -400,22 +488,46 @@ export function createCliMcpEngine(options = {}) {
|
|
|
400
488
|
}
|
|
401
489
|
|
|
402
490
|
// Built-in tools
|
|
403
|
-
if (
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
491
|
+
if (
|
|
492
|
+
toolName === "shadowclaw_server_list_clients" ||
|
|
493
|
+
toolName === "shadowclaw_list_clients"
|
|
494
|
+
) {
|
|
495
|
+
try {
|
|
496
|
+
const clients = await client.listClients();
|
|
497
|
+
return {
|
|
498
|
+
jsonrpc: "2.0",
|
|
499
|
+
id: reqId,
|
|
500
|
+
result: {
|
|
501
|
+
resultType: "complete",
|
|
502
|
+
content: [
|
|
503
|
+
{ type: "text", text: JSON.stringify({ clients }, null, 2) },
|
|
504
|
+
],
|
|
505
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
506
|
+
},
|
|
507
|
+
};
|
|
508
|
+
} catch (err) {
|
|
509
|
+
return {
|
|
510
|
+
jsonrpc: "2.0",
|
|
511
|
+
id: reqId,
|
|
512
|
+
result: {
|
|
513
|
+
resultType: "complete",
|
|
514
|
+
isError: true,
|
|
515
|
+
content: [
|
|
516
|
+
{
|
|
517
|
+
type: "text",
|
|
518
|
+
text: `Error listing clients: ${err.message}`,
|
|
519
|
+
},
|
|
520
|
+
],
|
|
521
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
522
|
+
},
|
|
523
|
+
};
|
|
524
|
+
}
|
|
416
525
|
}
|
|
417
526
|
|
|
418
|
-
if (
|
|
527
|
+
if (
|
|
528
|
+
toolName === "shadowclaw_server_set_active_client" ||
|
|
529
|
+
toolName === "shadowclaw_set_active_client"
|
|
530
|
+
) {
|
|
419
531
|
const targetId = await resolveTargetId(args.clientId);
|
|
420
532
|
if (!targetId) {
|
|
421
533
|
return {
|
|
@@ -457,7 +569,10 @@ export function createCliMcpEngine(options = {}) {
|
|
|
457
569
|
};
|
|
458
570
|
}
|
|
459
571
|
|
|
460
|
-
if (
|
|
572
|
+
if (
|
|
573
|
+
toolName === "shadowclaw_server_send_message" ||
|
|
574
|
+
toolName === "shadowclaw_send_message"
|
|
575
|
+
) {
|
|
461
576
|
const targetId = await resolveTargetId(args.clientId);
|
|
462
577
|
if (!targetId) {
|
|
463
578
|
return {
|
|
@@ -476,119 +591,254 @@ export function createCliMcpEngine(options = {}) {
|
|
|
476
591
|
},
|
|
477
592
|
};
|
|
478
593
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
594
|
+
try {
|
|
595
|
+
const res = await client.sendCommand(targetId, "send-message", {
|
|
596
|
+
text: args.text,
|
|
597
|
+
groupId: args.groupId,
|
|
598
|
+
});
|
|
599
|
+
return {
|
|
600
|
+
jsonrpc: "2.0",
|
|
601
|
+
id: reqId,
|
|
602
|
+
result: {
|
|
603
|
+
resultType: "complete",
|
|
604
|
+
isError: !res.success,
|
|
605
|
+
content: [
|
|
606
|
+
{
|
|
607
|
+
type: "text",
|
|
608
|
+
text: JSON.stringify(res.data || res, null, 2),
|
|
609
|
+
},
|
|
610
|
+
],
|
|
611
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
612
|
+
},
|
|
613
|
+
};
|
|
614
|
+
} catch (err) {
|
|
615
|
+
return {
|
|
616
|
+
jsonrpc: "2.0",
|
|
617
|
+
id: reqId,
|
|
618
|
+
result: {
|
|
619
|
+
resultType: "complete",
|
|
620
|
+
isError: true,
|
|
621
|
+
content: [
|
|
622
|
+
{
|
|
623
|
+
type: "text",
|
|
624
|
+
text: `Error sending message: ${err.message}`,
|
|
625
|
+
},
|
|
626
|
+
],
|
|
627
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
628
|
+
},
|
|
629
|
+
};
|
|
630
|
+
}
|
|
498
631
|
}
|
|
499
632
|
|
|
500
|
-
if (
|
|
633
|
+
if (
|
|
634
|
+
toolName === "shadowclaw_server_read_state" ||
|
|
635
|
+
toolName === "shadowclaw_read_state"
|
|
636
|
+
) {
|
|
501
637
|
const targetId = await resolveTargetId(args.clientId);
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
638
|
+
try {
|
|
639
|
+
const res = await client.sendCommand(targetId, "read-state", {});
|
|
640
|
+
return {
|
|
641
|
+
jsonrpc: "2.0",
|
|
642
|
+
id: reqId,
|
|
643
|
+
result: {
|
|
644
|
+
resultType: "complete",
|
|
645
|
+
isError: !res.success,
|
|
646
|
+
content: [
|
|
647
|
+
{
|
|
648
|
+
type: "text",
|
|
649
|
+
text: JSON.stringify(res.data || res, null, 2),
|
|
650
|
+
},
|
|
651
|
+
],
|
|
652
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
653
|
+
},
|
|
654
|
+
};
|
|
655
|
+
} catch (err) {
|
|
656
|
+
return {
|
|
657
|
+
jsonrpc: "2.0",
|
|
658
|
+
id: reqId,
|
|
659
|
+
result: {
|
|
660
|
+
resultType: "complete",
|
|
661
|
+
isError: true,
|
|
662
|
+
content: [
|
|
663
|
+
{
|
|
664
|
+
type: "text",
|
|
665
|
+
text: `Error reading state: ${err.message}`,
|
|
666
|
+
},
|
|
667
|
+
],
|
|
668
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
669
|
+
},
|
|
670
|
+
};
|
|
671
|
+
}
|
|
518
672
|
}
|
|
519
673
|
|
|
520
|
-
if (
|
|
674
|
+
if (
|
|
675
|
+
toolName === "shadowclaw_server_list_tasks" ||
|
|
676
|
+
toolName === "shadowclaw_list_tasks"
|
|
677
|
+
) {
|
|
521
678
|
const targetId = await resolveTargetId(args.clientId);
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
679
|
+
try {
|
|
680
|
+
const res = await client.sendCommand(targetId, "list-tasks", {
|
|
681
|
+
groupId: args.groupId,
|
|
682
|
+
});
|
|
683
|
+
return {
|
|
684
|
+
jsonrpc: "2.0",
|
|
685
|
+
id: reqId,
|
|
686
|
+
result: {
|
|
687
|
+
resultType: "complete",
|
|
688
|
+
isError: !res.success,
|
|
689
|
+
content: [
|
|
690
|
+
{
|
|
691
|
+
type: "text",
|
|
692
|
+
text: JSON.stringify(res.data || res, null, 2),
|
|
693
|
+
},
|
|
694
|
+
],
|
|
695
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
696
|
+
},
|
|
697
|
+
};
|
|
698
|
+
} catch (err) {
|
|
699
|
+
return {
|
|
700
|
+
jsonrpc: "2.0",
|
|
701
|
+
id: reqId,
|
|
702
|
+
result: {
|
|
703
|
+
resultType: "complete",
|
|
704
|
+
isError: true,
|
|
705
|
+
content: [
|
|
706
|
+
{
|
|
707
|
+
type: "text",
|
|
708
|
+
text: `Error listing tasks: ${err.message}`,
|
|
709
|
+
},
|
|
710
|
+
],
|
|
711
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
712
|
+
},
|
|
713
|
+
};
|
|
714
|
+
}
|
|
540
715
|
}
|
|
541
716
|
|
|
542
|
-
if (
|
|
717
|
+
if (
|
|
718
|
+
toolName === "shadowclaw_server_manage_backup" ||
|
|
719
|
+
toolName === "shadowclaw_manage_backup"
|
|
720
|
+
) {
|
|
543
721
|
const action = args.action || "trigger";
|
|
544
722
|
const targetId = await resolveTargetId(args.clientId);
|
|
545
|
-
|
|
546
|
-
|
|
723
|
+
try {
|
|
724
|
+
if (action === "list") {
|
|
725
|
+
const backups = await client.listBackups(targetId);
|
|
726
|
+
return {
|
|
727
|
+
jsonrpc: "2.0",
|
|
728
|
+
id: reqId,
|
|
729
|
+
result: {
|
|
730
|
+
resultType: "complete",
|
|
731
|
+
content: [
|
|
732
|
+
{
|
|
733
|
+
type: "text",
|
|
734
|
+
text: JSON.stringify({ backups }, null, 2),
|
|
735
|
+
},
|
|
736
|
+
],
|
|
737
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
738
|
+
},
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
if (action === "delete") {
|
|
742
|
+
const res = await client.deleteBackup(args.backupId, targetId);
|
|
743
|
+
return {
|
|
744
|
+
jsonrpc: "2.0",
|
|
745
|
+
id: reqId,
|
|
746
|
+
result: {
|
|
747
|
+
resultType: "complete",
|
|
748
|
+
content: [
|
|
749
|
+
{ type: "text", text: JSON.stringify(res, null, 2) },
|
|
750
|
+
],
|
|
751
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
752
|
+
},
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
const res = await client.sendCommand(targetId, "trigger-backup", {
|
|
756
|
+
groupId: args.groupId,
|
|
757
|
+
});
|
|
758
|
+
return {
|
|
759
|
+
jsonrpc: "2.0",
|
|
760
|
+
id: reqId,
|
|
761
|
+
result: {
|
|
762
|
+
resultType: "complete",
|
|
763
|
+
isError: !res.success,
|
|
764
|
+
content: [
|
|
765
|
+
{
|
|
766
|
+
type: "text",
|
|
767
|
+
text: JSON.stringify(res.data || res, null, 2),
|
|
768
|
+
},
|
|
769
|
+
],
|
|
770
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
771
|
+
},
|
|
772
|
+
};
|
|
773
|
+
} catch (err) {
|
|
547
774
|
return {
|
|
548
775
|
jsonrpc: "2.0",
|
|
549
776
|
id: reqId,
|
|
550
777
|
result: {
|
|
551
778
|
resultType: "complete",
|
|
779
|
+
isError: true,
|
|
552
780
|
content: [
|
|
553
|
-
{
|
|
781
|
+
{
|
|
782
|
+
type: "text",
|
|
783
|
+
text: `Error managing backup: ${err.message}`,
|
|
784
|
+
},
|
|
554
785
|
],
|
|
555
786
|
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
556
787
|
},
|
|
557
788
|
};
|
|
558
789
|
}
|
|
559
|
-
|
|
560
|
-
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
if (
|
|
793
|
+
toolName === "shadowclaw_server_status" ||
|
|
794
|
+
toolName === "shadowclaw_status"
|
|
795
|
+
) {
|
|
796
|
+
try {
|
|
797
|
+
const clients = await client.listClients();
|
|
798
|
+
return {
|
|
799
|
+
jsonrpc: "2.0",
|
|
800
|
+
id: reqId,
|
|
801
|
+
result: {
|
|
802
|
+
resultType: "complete",
|
|
803
|
+
content: [
|
|
804
|
+
{
|
|
805
|
+
type: "text",
|
|
806
|
+
text: JSON.stringify(
|
|
807
|
+
{
|
|
808
|
+
server: "ShadowClaw",
|
|
809
|
+
version: serverInfo.version,
|
|
810
|
+
connectedClients: clients.length,
|
|
811
|
+
status: "healthy",
|
|
812
|
+
},
|
|
813
|
+
null,
|
|
814
|
+
2,
|
|
815
|
+
),
|
|
816
|
+
},
|
|
817
|
+
],
|
|
818
|
+
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
819
|
+
},
|
|
820
|
+
};
|
|
821
|
+
} catch (err) {
|
|
561
822
|
return {
|
|
562
823
|
jsonrpc: "2.0",
|
|
563
824
|
id: reqId,
|
|
564
825
|
result: {
|
|
565
826
|
resultType: "complete",
|
|
566
|
-
|
|
827
|
+
isError: true,
|
|
828
|
+
content: [
|
|
829
|
+
{
|
|
830
|
+
type: "text",
|
|
831
|
+
text: `Error querying server status: ${err.message}`,
|
|
832
|
+
},
|
|
833
|
+
],
|
|
567
834
|
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
568
835
|
},
|
|
569
836
|
};
|
|
570
837
|
}
|
|
571
|
-
const res = await client.sendCommand(targetId, "trigger-backup", {
|
|
572
|
-
groupId: args.groupId,
|
|
573
|
-
});
|
|
574
|
-
return {
|
|
575
|
-
jsonrpc: "2.0",
|
|
576
|
-
id: reqId,
|
|
577
|
-
result: {
|
|
578
|
-
resultType: "complete",
|
|
579
|
-
isError: !res.success,
|
|
580
|
-
content: [
|
|
581
|
-
{
|
|
582
|
-
type: "text",
|
|
583
|
-
text: JSON.stringify(res.data || res, null, 2),
|
|
584
|
-
},
|
|
585
|
-
],
|
|
586
|
-
_meta: { "io.modelcontextprotocol/serverInfo": serverInfo },
|
|
587
|
-
},
|
|
588
|
-
};
|
|
589
838
|
}
|
|
590
839
|
|
|
591
840
|
if (
|
|
841
|
+
toolName === "shadowclaw_server_send_notification" ||
|
|
592
842
|
toolName === "shadowclaw_send_notification" ||
|
|
593
843
|
toolName === "send_notification"
|
|
594
844
|
) {
|
|
@@ -671,9 +921,11 @@ export function createCliMcpEngine(options = {}) {
|
|
|
671
921
|
}
|
|
672
922
|
}
|
|
673
923
|
|
|
924
|
+
const rawToolName = getClientRawToolName(toolName);
|
|
925
|
+
|
|
674
926
|
// Relayed interactive ask_user tool with MRTR response fulfillment if provided
|
|
675
927
|
if (
|
|
676
|
-
toolName === "ask_user" &&
|
|
928
|
+
(rawToolName === "ask_user" || toolName === "ask_user") &&
|
|
677
929
|
inputResponses &&
|
|
678
930
|
inputResponses["response"]
|
|
679
931
|
) {
|
|
@@ -695,7 +947,10 @@ export function createCliMcpEngine(options = {}) {
|
|
|
695
947
|
await getRelayedTools();
|
|
696
948
|
}
|
|
697
949
|
|
|
698
|
-
const supportingClients =
|
|
950
|
+
const supportingClients =
|
|
951
|
+
toolSupportingClientsMap.get(rawToolName) ||
|
|
952
|
+
toolSupportingClientsMap.get(toolName) ||
|
|
953
|
+
[];
|
|
699
954
|
const supportingClientIds = supportingClients
|
|
700
955
|
.map((cl) => cl.clientId || cl.id)
|
|
701
956
|
.filter(Boolean);
|
|
@@ -755,23 +1010,23 @@ export function createCliMcpEngine(options = {}) {
|
|
|
755
1010
|
|
|
756
1011
|
try {
|
|
757
1012
|
console.error(
|
|
758
|
-
`[ShadowClaw MCP] Executing '${
|
|
1013
|
+
`[ShadowClaw MCP] Executing '${rawToolName}' on client: ${targetId}`,
|
|
759
1014
|
);
|
|
760
1015
|
const toolArgs = { ...args };
|
|
761
1016
|
delete toolArgs.clientId;
|
|
762
|
-
const isInteractive =
|
|
1017
|
+
const isInteractive = rawToolName === "ask_user";
|
|
763
1018
|
const res = isInteractive
|
|
764
1019
|
? await client.sendCommand(
|
|
765
1020
|
targetId,
|
|
766
1021
|
"invoke-tool",
|
|
767
1022
|
{
|
|
768
|
-
toolName,
|
|
1023
|
+
toolName: rawToolName,
|
|
769
1024
|
input: toolArgs,
|
|
770
1025
|
},
|
|
771
1026
|
300000,
|
|
772
1027
|
)
|
|
773
1028
|
: await client.sendCommand(targetId, "invoke-tool", {
|
|
774
|
-
toolName,
|
|
1029
|
+
toolName: rawToolName,
|
|
775
1030
|
input: toolArgs,
|
|
776
1031
|
});
|
|
777
1032
|
|
|
@@ -885,8 +1140,22 @@ export async function runMcpCommand(options = {}) {
|
|
|
885
1140
|
let data = "";
|
|
886
1141
|
req.on("data", (chunk) => (data += chunk));
|
|
887
1142
|
req.on("end", async () => {
|
|
1143
|
+
let body;
|
|
1144
|
+
try {
|
|
1145
|
+
body = JSON.parse(data);
|
|
1146
|
+
} catch {
|
|
1147
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1148
|
+
res.end(
|
|
1149
|
+
JSON.stringify({
|
|
1150
|
+
jsonrpc: "2.0",
|
|
1151
|
+
id: null,
|
|
1152
|
+
error: { code: -32700, message: "Parse error" },
|
|
1153
|
+
}),
|
|
1154
|
+
);
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
888
1158
|
try {
|
|
889
|
-
const body = JSON.parse(data);
|
|
890
1159
|
const headers = {
|
|
891
1160
|
"mcp-protocol-version": req.headers["mcp-protocol-version"],
|
|
892
1161
|
"mcp-method": req.headers["mcp-method"],
|
|
@@ -906,12 +1175,15 @@ export async function runMcpCommand(options = {}) {
|
|
|
906
1175
|
});
|
|
907
1176
|
res.end(JSON.stringify(reply));
|
|
908
1177
|
} catch (err) {
|
|
909
|
-
res.writeHead(
|
|
1178
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
910
1179
|
res.end(
|
|
911
1180
|
JSON.stringify({
|
|
912
1181
|
jsonrpc: "2.0",
|
|
913
|
-
id: null,
|
|
914
|
-
error: {
|
|
1182
|
+
id: body?.id ?? null,
|
|
1183
|
+
error: {
|
|
1184
|
+
code: -32603,
|
|
1185
|
+
message: err?.message || "Internal error",
|
|
1186
|
+
},
|
|
915
1187
|
}),
|
|
916
1188
|
);
|
|
917
1189
|
}
|
|
@@ -944,8 +1216,20 @@ export async function runMcpCommand(options = {}) {
|
|
|
944
1216
|
const trimmed = line.trim();
|
|
945
1217
|
if (!trimmed) return;
|
|
946
1218
|
|
|
1219
|
+
let request;
|
|
1220
|
+
try {
|
|
1221
|
+
request = JSON.parse(trimmed);
|
|
1222
|
+
} catch {
|
|
1223
|
+
const errorResponse = {
|
|
1224
|
+
jsonrpc: "2.0",
|
|
1225
|
+
id: null,
|
|
1226
|
+
error: { code: -32700, message: "Parse error" },
|
|
1227
|
+
};
|
|
1228
|
+
process.stdout.write(JSON.stringify(errorResponse) + "\n");
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
947
1232
|
try {
|
|
948
|
-
const request = JSON.parse(trimmed);
|
|
949
1233
|
const response = await engine.handleMessage(request);
|
|
950
1234
|
if (response !== null) {
|
|
951
1235
|
process.stdout.write(JSON.stringify(response) + "\n");
|
|
@@ -953,8 +1237,8 @@ export async function runMcpCommand(options = {}) {
|
|
|
953
1237
|
} catch (err) {
|
|
954
1238
|
const errorResponse = {
|
|
955
1239
|
jsonrpc: "2.0",
|
|
956
|
-
id: null,
|
|
957
|
-
error: { code: -
|
|
1240
|
+
id: request?.id ?? null,
|
|
1241
|
+
error: { code: -32603, message: err?.message || "Internal error" },
|
|
958
1242
|
};
|
|
959
1243
|
process.stdout.write(JSON.stringify(errorResponse) + "\n");
|
|
960
1244
|
}
|