@clawops/cli 2.1.1 → 2.1.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.
- package/README.md +23 -1
- package/dist/{apply-HJ5GAKHW.js → apply-JARPVA5Y.js} +8 -8
- package/dist/{automation-MKCJ46I6.js → automation-NBYQ6MFZ.js} +1 -1
- package/dist/{bootstrap-NN647RCY.js → bootstrap-3PBVY7MA.js} +2 -2
- package/dist/{chunk-X56CQ6GB.js → chunk-4MHDW2NB.js} +1 -1
- package/dist/{chunk-3Z5TDXCJ.js → chunk-55UMO37O.js} +1 -1
- package/dist/chunk-755X5OGS.js +213 -0
- package/dist/{chunk-R3DTA35B.js → chunk-7T4CIT7C.js} +6 -6
- package/dist/{chunk-QDNFADJI.js → chunk-AVERNLUY.js} +6 -6
- package/dist/{chunk-GFUK6KDR.js → chunk-CPCO6UJK.js} +9 -9
- package/dist/{chunk-64PONSA5.js → chunk-GFIR2IIJ.js} +3 -1
- package/dist/{chunk-YEBFVLOE.js → chunk-PTCVFLZ3.js} +4 -4
- package/dist/{chunk-ELU3XQEA.js → chunk-RDUKRIRC.js} +1 -1
- package/dist/{chunk-OFTAXLOY.js → chunk-TYHTISI5.js} +239 -159
- package/dist/cli.js +127 -274
- package/dist/{context-7VI3R6EK.js → context-WOKSKAIA.js} +5 -5
- package/dist/{flows-RI7FGHAM.js → flows-HGJIA6EL.js} +7 -7
- package/dist/{generate-JNJ63ZYZ.js → generate-NE54BATS.js} +6 -6
- package/dist/{harden-3KKCR7BL.js → harden-RUOUA5BV.js} +2 -2
- package/dist/init-HOPXDNWY.js +13 -0
- package/dist/{mcp-wire-B57DUNOD.js → mcp-wire-FIO5DFBY.js} +11 -11
- package/dist/{package-SAUDFQLG.js → package-MF5LPITL.js} +1 -1
- package/dist/{server-RHON6QMN.js → server-OXWHBTXK.js} +11 -11
- package/dist/{stack-config-LUTS2XAD.js → stack-config-ICQ5YHUL.js} +2 -2
- package/dist/{state-AOAYLYY5.js → state-AKZP2S4T.js} +2 -2
- package/dist/{store-OVB3DAJR.js → store-YOLQYXMB.js} +1 -1
- package/dist/{tailscale-cutover-6YP2QKFM.js → tailscale-cutover-EKAQSDXP.js} +2 -2
- package/package.json +1 -1
- package/spec/mcp-tools.yaml +69 -28
- package/dist/{chunk-BELTQGHT.js → chunk-CHNSL3TC.js} +3 -3
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
applyPlan
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7T4CIT7C.js";
|
|
5
|
+
import {
|
|
6
|
+
generatePlan
|
|
7
|
+
} from "./chunk-PTCVFLZ3.js";
|
|
5
8
|
import {
|
|
6
9
|
extractBaseOutputs
|
|
7
10
|
} from "./chunk-3QJBNAHW.js";
|
|
@@ -10,24 +13,21 @@ import {
|
|
|
10
13
|
readRemoteConfig,
|
|
11
14
|
restartGateway
|
|
12
15
|
} from "./chunk-2I7KCMXZ.js";
|
|
13
|
-
import {
|
|
14
|
-
generatePlan
|
|
15
|
-
} from "./chunk-YEBFVLOE.js";
|
|
16
16
|
import {
|
|
17
17
|
validatePlan
|
|
18
18
|
} from "./chunk-XFN3YDZE.js";
|
|
19
|
+
import {
|
|
20
|
+
buildContext
|
|
21
|
+
} from "./chunk-AVERNLUY.js";
|
|
19
22
|
import {
|
|
20
23
|
acquireSession,
|
|
21
24
|
drainPool
|
|
22
25
|
} from "./chunk-2Z7J3ERQ.js";
|
|
23
|
-
import {
|
|
24
|
-
buildContext
|
|
25
|
-
} from "./chunk-QDNFADJI.js";
|
|
26
26
|
import {
|
|
27
27
|
formatUptime,
|
|
28
28
|
gatherSnapshot,
|
|
29
29
|
runDiagnostics
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-CPCO6UJK.js";
|
|
31
31
|
import {
|
|
32
32
|
GATEWAY_LOGS_PROBE,
|
|
33
33
|
chooseLogSource,
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
import {
|
|
49
49
|
getConfig,
|
|
50
50
|
getConfigDir
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-GFIR2IIJ.js";
|
|
52
52
|
import {
|
|
53
53
|
StateError,
|
|
54
54
|
UsageError
|
|
@@ -141,8 +141,9 @@ function withAudit(toolName, handler) {
|
|
|
141
141
|
// src/mcp/tools/_generated.ts
|
|
142
142
|
import { z } from "zod";
|
|
143
143
|
var clawops_statusSchema = z.object({
|
|
144
|
-
stackName: z.string().optional()
|
|
144
|
+
stackName: z.string().optional().describe("Stack name. Defaults to active stack from config.")
|
|
145
145
|
});
|
|
146
|
+
var clawops_statusDescription = "Get what is deployed for a clawops-managed stack: public IP, gateway URL,\nSSH user, or that nothing is deployed yet. Reads stack outputs; does not\ncontact the host.\n\nUse when: the user asks what exists for a stack, or where to reach it.\n\nDo NOT use when: the user asks whether the gateway is actually WORKING \u2014\nthat needs the host, so use clawops_doctor. Also not for live logs (use\nclawops_logs_tail) or config values (use clawops_config_get).";
|
|
146
147
|
var clawops_statusAnnotations = {
|
|
147
148
|
title: "Get Stack Status",
|
|
148
149
|
readOnlyHint: true,
|
|
@@ -152,9 +153,10 @@ var clawops_statusAnnotations = {
|
|
|
152
153
|
toolsets: ["cli", "read"]
|
|
153
154
|
};
|
|
154
155
|
var clawops_doctorSchema = z.object({
|
|
155
|
-
stackName: z.string().optional(),
|
|
156
|
-
failuresOnly: z.boolean().optional().default(false)
|
|
156
|
+
stackName: z.string().optional().describe("Stack to include remote checks for. Without it, only the local machine is\nchecked \u2014 no SSH connection is made.\n"),
|
|
157
|
+
failuresOnly: z.boolean().optional().default(false).describe("Return only failing and warning checks. Passing checks are counted, not listed.")
|
|
157
158
|
});
|
|
159
|
+
var clawops_doctorDescription = "Run clawops's diagnostics and return the report: Node and Pulumi runtime, config,\nSSH key and known_hosts, cloud credentials per configured provider, and the\nsupported OpenClaw range. With stackName, also contacts the host for container\nstate, the deployed OpenClaw version, a real gateway health probe, whether the\nport is published to the internet, disk usage on the state directory, log\nrotation, and hardening drift.\n\nUse when: something is not working and you do not yet know what; before any\ndeploy, upgrade or migration; or to find out which OpenClaw version a gateway is\nactually running.\n\nDo NOT use when: you already know the problem and want to fix it. This tool only\nreports \u2014 it changes nothing, and never runs `openclaw doctor --fix`. No tool\nrepairs a gateway: `clawops gateway update` is CLI-only, so tell the user to run\nit themselves, after `clawops backup create`.\n\nEvery check carries a status: fail (something is wrong that clawops can name),\nwarn (worth knowing, not broken), info (did not apply). `ok` is false only when\nsomething failed \u2014 a fresh machine with no stacks is full of warnings and healthy.";
|
|
158
160
|
var clawops_doctorAnnotations = {
|
|
159
161
|
title: "Run Diagnostics",
|
|
160
162
|
readOnlyHint: true,
|
|
@@ -164,10 +166,11 @@ var clawops_doctorAnnotations = {
|
|
|
164
166
|
toolsets: ["cli", "read"]
|
|
165
167
|
};
|
|
166
168
|
var clawops_logs_tailSchema = z.object({
|
|
167
|
-
stackName: z.string().optional(),
|
|
168
|
-
tailLines: z.number().int().optional().default(100),
|
|
169
|
-
sinceMin: z.number().int().optional()
|
|
169
|
+
stackName: z.string().optional().describe("Which stack's gateway to read. Omitted = the default stack in ~/.clawops/config.json"),
|
|
170
|
+
tailLines: z.number().int().optional().default(100).describe("How many of the most recent lines to return. Keep it small; output is trimmed to 8KB regardless"),
|
|
171
|
+
sinceMin: z.number().int().optional().describe("Lines since N minutes ago")
|
|
170
172
|
});
|
|
173
|
+
var clawops_logs_tailDescription = "Tail recent gateway logs from a clawops-managed instance.\n\nUse when: the user wants to investigate recent activity or errors, or\nasks \"what's been happening\" on the gateway.\n\nDo NOT use when: the user wants real-time streaming logs (those are not\nwell-suited to tool calls; suggest the user run `clawops logs -f` directly\nin their terminal). Do NOT use for instance-level system logs: no tool runs\narbitrary remote commands, so tell the user to run `clawops ssh --command\n'journalctl ...'` themselves.";
|
|
171
174
|
var clawops_logs_tailAnnotations = {
|
|
172
175
|
title: "Tail Gateway Logs",
|
|
173
176
|
readOnlyHint: true,
|
|
@@ -177,9 +180,10 @@ var clawops_logs_tailAnnotations = {
|
|
|
177
180
|
toolsets: ["cli", "read"]
|
|
178
181
|
};
|
|
179
182
|
var clawops_monitorSchema = z.object({
|
|
180
|
-
stackName: z.string().optional(),
|
|
181
|
-
tailLines: z.number().int().optional().default(5)
|
|
183
|
+
stackName: z.string().optional().describe("Stack name. Defaults to active stack."),
|
|
184
|
+
tailLines: z.number().int().optional().default(5).describe("Log lines to include in snapshot.")
|
|
182
185
|
});
|
|
186
|
+
var clawops_monitorDescription = "Take a live snapshot of a running clawops stack: gateway health, container\nstatus, resource usage (CPU, memory, disk), and recent log lines.\n\nUse when: the user wants to know if the gateway is running, how much\nmemory or CPU it is using, what recent log activity looks like, or\nwants a quick health overview richer than clawops_status.\n\nDo NOT use when: the user wants real-time streaming logs (use\nclawops_logs_tail or suggest `clawops logs -f`). Do NOT use for\nconfiguration queries (use clawops_config_get).";
|
|
183
187
|
var clawops_monitorAnnotations = {
|
|
184
188
|
title: "Monitor Stack Health",
|
|
185
189
|
readOnlyHint: true,
|
|
@@ -189,6 +193,7 @@ var clawops_monitorAnnotations = {
|
|
|
189
193
|
toolsets: ["cli", "read"]
|
|
190
194
|
};
|
|
191
195
|
var clawops_stacks_listSchema = z.object({});
|
|
196
|
+
var clawops_stacks_listDescription = 'List all clawops-managed stacks across all configured providers.\n\nUse when: the user wants an overview of their deployments, asks "what\nstacks do I have", or wants to compare stacks before an operation.\n\nDo NOT use when: the user named a specific stack \u2014 use clawops_status\ndirectly with that name.';
|
|
192
197
|
var clawops_stacks_listAnnotations = {
|
|
193
198
|
title: "List Stacks",
|
|
194
199
|
readOnlyHint: true,
|
|
@@ -198,9 +203,10 @@ var clawops_stacks_listAnnotations = {
|
|
|
198
203
|
toolsets: ["admin", "read"]
|
|
199
204
|
};
|
|
200
205
|
var clawops_config_getSchema = z.object({
|
|
201
|
-
stackName: z.string().optional(),
|
|
202
|
-
key: z.string().optional()
|
|
206
|
+
stackName: z.string().optional().describe("Which stack's gateway config to read. Omitted = the default stack in ~/.clawops/config.json"),
|
|
207
|
+
key: z.string().optional().describe("Dot-path config key, e.g., gateway.auth.mode. Omit to dump the full config.")
|
|
203
208
|
});
|
|
209
|
+
var clawops_config_getDescription = "Read a configuration value from the remote OpenClaw gateway.\n\nUse when: the user wants to inspect current OpenClaw config (e.g., which\nmodel provider is active, which channels are enabled).\n\nDo NOT use when: the user wants to change the config \u2014 use\nclawops_config_set instead.";
|
|
204
210
|
var clawops_config_getAnnotations = {
|
|
205
211
|
title: "Get OpenClaw Config Value",
|
|
206
212
|
readOnlyHint: true,
|
|
@@ -210,8 +216,9 @@ var clawops_config_getAnnotations = {
|
|
|
210
216
|
toolsets: ["cli", "read"]
|
|
211
217
|
};
|
|
212
218
|
var clawops_agents_listSchema = z.object({
|
|
213
|
-
stackName: z.string().optional()
|
|
219
|
+
stackName: z.string().optional().describe("Which stack's agents to list. Omitted = the default stack in ~/.clawops/config.json")
|
|
214
220
|
});
|
|
221
|
+
var clawops_agents_listDescription = "List agents currently registered on the remote OpenClaw gateway.\n\nUse when: the user wants to see which agents are running, debug agent\nrouting, or count active workspaces.\n\nDo NOT use when: the user wants one agent's logs \u2014 no tool exposes those; tell\nthe user to run `clawops agents logs <name>`.";
|
|
215
222
|
var clawops_agents_listAnnotations = {
|
|
216
223
|
title: "List OpenClaw Agents",
|
|
217
224
|
readOnlyHint: true,
|
|
@@ -221,16 +228,17 @@ var clawops_agents_listAnnotations = {
|
|
|
221
228
|
toolsets: ["cli", "read"]
|
|
222
229
|
};
|
|
223
230
|
var clawops_upSchema = z.object({
|
|
224
|
-
stackName: z.string().optional(),
|
|
225
|
-
provider: z.enum(["aws", "gcp", "azure", "local"]).optional(),
|
|
226
|
-
region: z.string().optional(),
|
|
227
|
-
instanceType: z.string().optional().default("small"),
|
|
228
|
-
sshCidr: z.string().optional(),
|
|
229
|
-
gatewayCidr: z.string().optional(),
|
|
230
|
-
publishGateway: z.enum(["loopback", "all"]).optional(),
|
|
231
|
-
openclawVersion: z.string().optional(),
|
|
232
|
-
dryRun: z.boolean().optional().default(false)
|
|
231
|
+
stackName: z.string().optional().describe("Name for the stack to provision, and the name every later command refers to it by. Omitted = the default stack in ~/.clawops/config.json"),
|
|
232
|
+
provider: z.enum(["aws", "gcp", "azure", "local"]).optional().describe("Defaults to provider configured for this stack"),
|
|
233
|
+
region: z.string().optional().describe("Cloud region to deploy into, in the provider's own spelling (us-east-1, us-central1, eastus). Omitted = the region recorded for the stack"),
|
|
234
|
+
instanceType: z.string().optional().default("small").describe("A clawops size (micro|small|medium|large|gpu) or a provider-native machine type.\nNot an enum: Azure offers SKU families per subscription, and an account offered\nnone of the five sizes clawops names would otherwise have no way to deploy.\n"),
|
|
235
|
+
sshCidr: z.string().optional().describe("CIDR(s) allowed to reach SSH, comma-separated, or 'auto' for the caller's own\naddress. Omitted means none, and nothing will be able to connect \u2014 including\nevery clawops day-two command.\n"),
|
|
236
|
+
gatewayCidr: z.string().optional().describe("CIDR(s) allowed to reach the gateway port. Requires publishGateway=all."),
|
|
237
|
+
publishGateway: z.enum(["loopback", "all"]).optional().describe("Which interface the gateway binds. 'all' serves plaintext HTTP."),
|
|
238
|
+
openclawVersion: z.string().optional().describe("semver or 'stable'/'dev'"),
|
|
239
|
+
dryRun: z.boolean().optional().default(false).describe("Show what would be created and change nothing. Use this first when the user has not yet approved a spend")
|
|
233
240
|
});
|
|
241
|
+
var clawops_upDescription = 'Provision and deploy a clawops stack. Idempotent \u2014 re-running with no spec\nchange produces no diff. Long-running (median 3min, p99 8min) so emits\nprogress notifications per R12.\n\nUse when: the user explicitly asks to deploy, provision, create, or "spin\nup" a stack. Always after the user has reviewed a plan\n(clawops_plan first when in doubt).\n\nDo NOT use when: the user has not yet generated a plan and is in\nexploratory/discovery mode \u2014 use clawops_plan first. Do NOT use for an\nexisting stack you only need to update; refresh first.';
|
|
234
242
|
var clawops_upAnnotations = {
|
|
235
243
|
title: "Provision and Deploy Stack",
|
|
236
244
|
readOnlyHint: false,
|
|
@@ -240,9 +248,10 @@ var clawops_upAnnotations = {
|
|
|
240
248
|
toolsets: ["cli"]
|
|
241
249
|
};
|
|
242
250
|
var clawops_destroySchema = z.object({
|
|
243
|
-
stackName: z.string(),
|
|
244
|
-
yes: z.boolean().optional().default(false)
|
|
251
|
+
stackName: z.string().describe("The stack to destroy. Required, and worth repeating back to the user before calling: this deletes every resource it provisioned"),
|
|
252
|
+
yes: z.boolean().optional().default(false).describe("Skip elicitation; CI/scripted use only")
|
|
245
253
|
});
|
|
254
|
+
var clawops_destroyDescription = "Destroy a clawops stack. Removes ALL provisioned resources. Triggers\nelicitation confirmation showing the resource diff before execution\n(R19). Cannot be undone.\n\nUse when: the user explicitly asks to destroy, tear down, delete, or\nremove a stack. Always confirm the stack name.\n\nDo NOT use when: the user wants to stop the gateway temporarily \u2014 that is not\na destroy, and no tool stops a gateway; clawops_gateway_restart is the only\ngateway tool. Do NOT use when in doubt about which stack; list first with\nclawops_stacks_list.";
|
|
246
255
|
var clawops_destroyAnnotations = {
|
|
247
256
|
title: "Destroy Stack (DESTRUCTIVE)",
|
|
248
257
|
readOnlyHint: false,
|
|
@@ -252,9 +261,10 @@ var clawops_destroyAnnotations = {
|
|
|
252
261
|
toolsets: ["cli"]
|
|
253
262
|
};
|
|
254
263
|
var clawops_applySchema = z.object({
|
|
255
|
-
planPath: z.string(),
|
|
256
|
-
yes: z.boolean().optional().default(false)
|
|
264
|
+
planPath: z.string().describe("Absolute path to plan JSON (R7)"),
|
|
265
|
+
yes: z.boolean().optional().default(false).describe("Skip the confirmation and apply immediately. Only when the user has already approved this specific plan")
|
|
257
266
|
});
|
|
267
|
+
var clawops_applyDescription = "Apply a previously-generated Maker plan (deploy-plan.schema.json).\nDeterministic \u2014 the plan describes exactly what will be created.\n\nUse when: the user has a plan file path and wants to apply it. This is\nthe agent-friendly path for any deploy/destroy operation.\n\nDo NOT use when: there's no plan file \u2014 generate one first with\nclawops_plan.";
|
|
258
268
|
var clawops_applyAnnotations = {
|
|
259
269
|
title: "Apply Maker Plan",
|
|
260
270
|
readOnlyHint: false,
|
|
@@ -264,17 +274,18 @@ var clawops_applyAnnotations = {
|
|
|
264
274
|
toolsets: ["cli"]
|
|
265
275
|
};
|
|
266
276
|
var clawops_planSchema = z.object({
|
|
267
|
-
stackName: z.string().optional(),
|
|
268
|
-
provider: z.enum(["aws", "gcp", "azure", "local"]).optional(),
|
|
269
|
-
region: z.string().optional(),
|
|
270
|
-
instanceType: z.string().optional(),
|
|
271
|
-
openclawVersion: z.string().optional(),
|
|
272
|
-
sshCidr: z.string().optional(),
|
|
273
|
-
gatewayCidr: z.string().optional(),
|
|
274
|
-
publishGateway: z.enum(["loopback", "all"]).optional(),
|
|
275
|
-
privateOnly: z.boolean().optional(),
|
|
276
|
-
outPath: z.string().optional()
|
|
277
|
+
stackName: z.string().optional().describe("Which stack the plan is for. Omitted = the default stack in ~/.clawops/config.json"),
|
|
278
|
+
provider: z.enum(["aws", "gcp", "azure", "local"]).optional().describe("Cloud to plan against. Omitted = the provider recorded for the stack. 'local' has no plan/apply path and is refused"),
|
|
279
|
+
region: z.string().optional().describe("Cloud region, in the provider's own spelling (us-east-1, us-central1, eastus). Omitted = the region recorded for the stack"),
|
|
280
|
+
instanceType: z.string().optional().describe("A clawops alias (micro|small|medium|large|gpu) or a machine type the cloud names itself, e.g. t3.small"),
|
|
281
|
+
openclawVersion: z.string().optional().describe("semver, or 'stable'/'dev'"),
|
|
282
|
+
sshCidr: z.string().optional().describe("CIDR(s) allowed to reach SSH, comma-separated, or 'auto' for this machine. Omitted = none, and nothing will be able to connect"),
|
|
283
|
+
gatewayCidr: z.string().optional().describe("CIDR(s) allowed to reach the gateway port, or 'auto'. Requires publishGateway=all"),
|
|
284
|
+
publishGateway: z.enum(["loopback", "all"]).optional().describe("Which interface the gateway binds. loopback (default) keeps it off the network"),
|
|
285
|
+
privateOnly: z.boolean().optional().describe("Close public SSH and gateway access; reach the stack over its tailnet. Requires a verified tailnet address (clawops_harden with tailscale), and refuses unless that address answers SSH now"),
|
|
286
|
+
outPath: z.string().optional().describe("Absolute path to write plan; if omitted, plan returned inline")
|
|
277
287
|
});
|
|
288
|
+
var clawops_planDescription = "Generate a Maker deploy plan (does NOT apply). Plan is JSON conforming to\ndeploy-plan.schema.json \u2014 review before applying.\n\nUse when: the user wants to see what would be created before committing,\nor you (the agent) need a reviewable artifact for the user to approve.\n\nDo NOT use when: the user has explicitly asked to deploy and you already\nhave their approval \u2014 go directly to clawops_up.";
|
|
278
289
|
var clawops_planAnnotations = {
|
|
279
290
|
title: "Generate Deploy Plan",
|
|
280
291
|
readOnlyHint: true,
|
|
@@ -284,11 +295,12 @@ var clawops_planAnnotations = {
|
|
|
284
295
|
toolsets: ["cli", "read"]
|
|
285
296
|
};
|
|
286
297
|
var clawops_config_setSchema = z.object({
|
|
287
|
-
stackName: z.string().optional(),
|
|
288
|
-
key: z.string(),
|
|
289
|
-
value: z.string(),
|
|
290
|
-
restart: z.boolean().optional().default(false)
|
|
298
|
+
stackName: z.string().optional().describe("Which stack's gateway config to write. Omitted = the default stack in ~/.clawops/config.json"),
|
|
299
|
+
key: z.string().describe("Dotted path into the gateway config, e.g. models.provider or channels.slack.enabled"),
|
|
300
|
+
value: z.string().describe("Stringified; JSON for complex values"),
|
|
301
|
+
restart: z.boolean().optional().default(false).describe("Restart the gateway so the change takes effect. Without it the value is written and the running gateway keeps the old one")
|
|
291
302
|
});
|
|
303
|
+
var clawops_config_setDescription = "Set a configuration value on the remote OpenClaw gateway. Optionally\nrestarts the gateway after.\n\nUse when: the user wants to change OpenClaw configuration (model\nprovider, channel auth, gateway port).\n\nDo NOT use when: the user is reading config \u2014 use clawops_config_get.\nDo NOT bulk-edit; one key at a time so changes are auditable (R21).";
|
|
292
304
|
var clawops_config_setAnnotations = {
|
|
293
305
|
title: "Set OpenClaw Config Value",
|
|
294
306
|
readOnlyHint: false,
|
|
@@ -298,10 +310,11 @@ var clawops_config_setAnnotations = {
|
|
|
298
310
|
toolsets: ["cli"]
|
|
299
311
|
};
|
|
300
312
|
var clawops_config_unsetSchema = z.object({
|
|
301
|
-
stackName: z.string().optional(),
|
|
302
|
-
key: z.string(),
|
|
303
|
-
restart: z.boolean().optional().default(false)
|
|
313
|
+
stackName: z.string().optional().describe("Which stack's gateway config to write. Omitted = the default stack in ~/.clawops/config.json"),
|
|
314
|
+
key: z.string().describe("Dot-path config key to remove"),
|
|
315
|
+
restart: z.boolean().optional().default(false).describe("Restart the gateway so the removal takes effect. Without it the key is removed and the running gateway keeps the old value")
|
|
304
316
|
});
|
|
317
|
+
var clawops_config_unsetDescription = "Remove a configuration key from the remote OpenClaw gateway config, reverting\nit to the OpenClaw default.\n\nUse when: the user wants to delete a config key entirely (e.g., remove a\nchannel, clear an override).\n\nDo NOT use when: the user wants to set the key to a new value \u2014 use\nclawops_config_set instead.";
|
|
305
318
|
var clawops_config_unsetAnnotations = {
|
|
306
319
|
title: "Unset OpenClaw Config Key",
|
|
307
320
|
readOnlyHint: false,
|
|
@@ -311,8 +324,9 @@ var clawops_config_unsetAnnotations = {
|
|
|
311
324
|
toolsets: ["cli"]
|
|
312
325
|
};
|
|
313
326
|
var clawops_config_validateSchema = z.object({
|
|
314
|
-
stackName: z.string().optional()
|
|
327
|
+
stackName: z.string().optional().describe("Which stack's deployed config to validate. Omitted = the default stack in ~/.clawops/config.json")
|
|
315
328
|
});
|
|
329
|
+
var clawops_config_validateDescription = "Validate the remote OpenClaw gateway config against the known schema. Checks\nfor structural errors (wrong types, unknown top-level keys) that would cause\nOpenClaw to fail on startup.\n\nUse when: the user wants to verify config before restarting the gateway, or\nafter editing openclaw.json manually.\n\nDo NOT use when: the user wants to change config \u2014 use clawops_config_set.";
|
|
316
330
|
var clawops_config_validateAnnotations = {
|
|
317
331
|
title: "Validate OpenClaw Config",
|
|
318
332
|
readOnlyHint: true,
|
|
@@ -322,8 +336,9 @@ var clawops_config_validateAnnotations = {
|
|
|
322
336
|
toolsets: ["cli", "read"]
|
|
323
337
|
};
|
|
324
338
|
var clawops_gateway_restartSchema = z.object({
|
|
325
|
-
stackName: z.string().optional()
|
|
339
|
+
stackName: z.string().optional().describe("Which stack's gateway to restart. Omitted = the default stack in ~/.clawops/config.json")
|
|
326
340
|
});
|
|
341
|
+
var clawops_gateway_restartDescription = "Restart the OpenClaw gateway daemon on the remote instance.\n\nUse when: a gateway-wide config change requires reload, or the gateway is\nreported as unresponsive.\n\nNote: OpenClaw 2.0 removed per-agent restart; `gateway restart` is the only\nrestart it offers, and it affects every agent on the host. Brief downtime (~10s).";
|
|
327
342
|
var clawops_gateway_restartAnnotations = {
|
|
328
343
|
title: "Restart Gateway Daemon",
|
|
329
344
|
readOnlyHint: false,
|
|
@@ -332,14 +347,34 @@ var clawops_gateway_restartAnnotations = {
|
|
|
332
347
|
openWorldHint: true,
|
|
333
348
|
toolsets: ["cli"]
|
|
334
349
|
};
|
|
350
|
+
var clawops_initSchema = z.object({
|
|
351
|
+
provider: z.enum(["aws", "gcp", "azure", "local"]).describe("Which cloud this stack deploys to, or 'local' for a machine you already have"),
|
|
352
|
+
stackName: z.string().optional().describe('Name for the stack, used by every later call. Omitted = "default"'),
|
|
353
|
+
stateUrl: z.string().optional().describe("Where Pulumi state lives, e.g. s3://bucket/clawops, gs://bucket/clawops, azblob://container. Omitted = clawops names one from the cloud account it can see, which needs credentials"),
|
|
354
|
+
region: z.string().optional().describe("Cloud region in the provider's own spelling. Omitted = us-east-1 (aws), us-central1 (gcp), eastus (azure)"),
|
|
355
|
+
host: z.string().optional().describe("[local only] Hostname or IP of the machine to manage. Required when provider is local"),
|
|
356
|
+
sshUser: z.string().optional().describe("[local only] SSH login user. Omitted = root"),
|
|
357
|
+
sshPort: z.number().int().optional().describe("[local only] SSH port. Omitted = 22"),
|
|
358
|
+
force: z.boolean().optional().describe("Overwrite a stack that already exists. Refused without it, because replacing a state backend orphans the state it points at")
|
|
359
|
+
});
|
|
360
|
+
var clawops_initDescription = "Register a stack and write ~/.clawops/config.json: the provider, the state backend, the\nregion, and an SSH key pair generated if one is not already there. Nothing is provisioned\nand nothing is charged; this only creates local configuration.\n\nUse when: any other clawops tool reports that there is no config, or the user wants to add\na second stack alongside the ones they have. This is the first call on a machine that has\nnever run clawops \u2014 a fresh container, a new laptop, a sandbox.\n\nAdding a stack is additive and safe: existing stacks are kept. Overwriting one needs\nforce: true, because changing a state backend orphans the Pulumi state it points at \u2014 the\ninfrastructure stays up and clawops can no longer see or destroy it.\n\nFor aws, gcp and azure, stateUrl can be omitted and clawops names a bucket from the\naccount it can see; that needs cloud credentials in the environment, so in a sandbox pass\nstateUrl explicitly. The local provider needs host instead, and no cloud account at all.\n\nDo NOT use when: the user wants to deploy \u2014 that is clawops_up, after this. Credentials\nare never passed here: clawops reads them from the environment (R6).";
|
|
361
|
+
var clawops_initAnnotations = {
|
|
362
|
+
title: "Initialise clawops Config",
|
|
363
|
+
readOnlyHint: false,
|
|
364
|
+
destructiveHint: false,
|
|
365
|
+
idempotentHint: false,
|
|
366
|
+
openWorldHint: false,
|
|
367
|
+
toolsets: ["cli"]
|
|
368
|
+
};
|
|
335
369
|
var clawops_hardenSchema = z.object({
|
|
336
|
-
stackName: z.string().optional(),
|
|
337
|
-
options: z.string().optional(),
|
|
338
|
-
dryRun: z.boolean().optional().default(false),
|
|
339
|
-
tailscale: z.boolean().optional().default(false),
|
|
340
|
-
tailscaleRevert: z.boolean().optional().default(false),
|
|
341
|
-
yes: z.boolean().optional().default(false)
|
|
370
|
+
stackName: z.string().optional().describe("Which stack to harden. Omitted = the default stack in ~/.clawops/config.json"),
|
|
371
|
+
options: z.string().optional().describe("Comma-separated module IDs; default is every defaultOn module for the provider"),
|
|
372
|
+
dryRun: z.boolean().optional().default(false).describe("Report the current state, change nothing"),
|
|
373
|
+
tailscale: z.boolean().optional().default(false).describe("Join the tailnet, verify this machine reaches the host there, then use that address"),
|
|
374
|
+
tailscaleRevert: z.boolean().optional().default(false).describe("Leave the tailnet and go back to the public address"),
|
|
375
|
+
yes: z.boolean().optional().default(false).describe("Skip elicitation; CI/scripted use only")
|
|
342
376
|
});
|
|
377
|
+
var clawops_hardenDescription = "Apply security hardening to a deployed stack: SSH, UFW, fail2ban,\nunattended-upgrades, the Docker socket, and per-cloud checks. Optionally join\nthe stack to a Tailscale network and reach it there instead of over the public\ninternet.\n\nUse when: the user asks to harden, secure, or lock down a stack; asks what the\nhardening report says (with dryRun: true, which changes nothing); or asks to put\na stack on their tailnet.\n\ntailscale: true installs Tailscale, joins the tailnet as clawops-<stack>, and\nthen moves clawops onto that address \u2014 but only after opening an SSH session to\nit, against host keys pinned over the connection already trusted. If that fails,\nnothing is recorded and the public address stays in use. The auth key comes from\n`clawops secret set TAILSCALE_AUTH_KEY` and is never passed through this tool\n(R6).\n\ntailscaleRevert: true takes the host back off the tailnet, over its public\naddress. On a private-only stack it refuses and names the plan/apply commands\nthat reopen SSH first \u2014 relay them rather than trying to work around it.\n\nTo close the public ports afterwards, plan with privateOnly: true and apply that\nplan; this tool does not change firewall rules.\n\nDo NOT use when: the user wants to know whether a stack is healthy \u2014 that is\nclawops_doctor. Do NOT pass tailscale and tailscaleRevert together.";
|
|
343
378
|
var clawops_hardenAnnotations = {
|
|
344
379
|
title: "Harden Stack",
|
|
345
380
|
readOnlyHint: false,
|
|
@@ -349,11 +384,12 @@ var clawops_hardenAnnotations = {
|
|
|
349
384
|
toolsets: ["cli"]
|
|
350
385
|
};
|
|
351
386
|
var clawops_workflow_deploy_appSchema = z.object({
|
|
352
|
-
provider: z.enum(["aws", "gcp", "azure", "local"]),
|
|
353
|
-
region: z.string().optional(),
|
|
354
|
-
stackName: z.string().optional().default("default"),
|
|
355
|
-
instanceType: z.enum(["micro", "small", "medium", "large", "gpu"]).optional().default("small")
|
|
387
|
+
provider: z.enum(["aws", "gcp", "azure", "local"]).describe("Cloud to deploy to. Omitted = the default provider in ~/.clawops/config.json"),
|
|
388
|
+
region: z.string().optional().describe("Cloud region, in the provider's own spelling (us-east-1, us-central1, eastus). Omitted = the provider's default"),
|
|
389
|
+
stackName: z.string().optional().default("default").describe("Name for the new stack. Omitted = the default stack name in ~/.clawops/config.json"),
|
|
390
|
+
instanceType: z.enum(["micro", "small", "medium", "large", "gpu"]).optional().default("small").describe("Machine size: a clawops alias (micro|small|medium|large|gpu) or a type the cloud names itself, e.g. t3.small")
|
|
356
391
|
});
|
|
392
|
+
var clawops_workflow_deploy_appDescription = 'Single-tool workflow that takes a user from "I want to deploy OpenClaw\nto <provider>" to a verified, healthy gateway. Internally: plan \u2192 user\nconfirms (elicitation) \u2192 up \u2192 wait for healthy \u2192 return URL.\n\nUse when: the user expresses end-to-end deployment intent ("deploy to\nAWS", "spin up an OpenClaw on GCP for me").\n\nDo NOT use when: the user is mid-deployment and only needs one step\n(e.g., they already have a plan; use clawops_apply). Do NOT use for\ndestroying or updating \u2014 separate workflows.';
|
|
357
393
|
var clawops_workflow_deploy_appAnnotations = {
|
|
358
394
|
title: "Deploy OpenClaw (End-to-End Workflow)",
|
|
359
395
|
readOnlyHint: false,
|
|
@@ -363,8 +399,17 @@ var clawops_workflow_deploy_appAnnotations = {
|
|
|
363
399
|
toolsets: ["workflow"]
|
|
364
400
|
};
|
|
365
401
|
var clawops_workflow_recoverSchema = z.object({
|
|
366
|
-
stackName: z.string().optional()
|
|
402
|
+
stackName: z.string().optional().describe("Which stack to diagnose. Omitted = the default stack in ~/.clawops/config.json")
|
|
367
403
|
});
|
|
404
|
+
var clawops_workflow_recoverDescription = `Diagnostic workflow for an unhealthy stack. Internally: status check \u2192
|
|
405
|
+
gateway logs \u2192 agent logs \u2192 systemd service status \u2192 produces a structured
|
|
406
|
+
diagnostic report with suggested remediation.
|
|
407
|
+
|
|
408
|
+
Use when: the user reports any "not working" symptom and you don't know
|
|
409
|
+
where to start. Best entry point for troubleshooting.
|
|
410
|
+
|
|
411
|
+
Do NOT use when: the user has already identified the problem and asks for
|
|
412
|
+
a specific fix.`;
|
|
368
413
|
var clawops_workflow_recoverAnnotations = {
|
|
369
414
|
title: "Recover/Diagnose Stack",
|
|
370
415
|
readOnlyHint: true,
|
|
@@ -374,8 +419,9 @@ var clawops_workflow_recoverAnnotations = {
|
|
|
374
419
|
toolsets: ["workflow", "read"]
|
|
375
420
|
};
|
|
376
421
|
var clawops_task_statusSchema = z.object({
|
|
377
|
-
taskId: z.string()
|
|
422
|
+
taskId: z.string().describe("The taskId returned by a long-running tool such as clawops_up, clawops_apply or clawops_destroy")
|
|
378
423
|
});
|
|
424
|
+
var clawops_task_statusDescription = "Poll the status of a long-running clawops task (returned by clawops_up,\nclawops_destroy, clawops_apply, etc.). Per R12 streaming model.\n\nUse when: the user is waiting on a long-running deploy/destroy and wants\nprogress, OR you need to check whether a previously-started operation\nfinished.\n\nDo NOT use when: there is no active taskId \u2014 start the operation first.";
|
|
379
425
|
var clawops_task_statusAnnotations = {
|
|
380
426
|
title: "Get Task Status",
|
|
381
427
|
readOnlyHint: true,
|
|
@@ -400,6 +446,7 @@ var TOOLSETS = {
|
|
|
400
446
|
"clawops_config_unset",
|
|
401
447
|
"clawops_config_validate",
|
|
402
448
|
"clawops_gateway_restart",
|
|
449
|
+
"clawops_init",
|
|
403
450
|
"clawops_harden",
|
|
404
451
|
"clawops_task_status"
|
|
405
452
|
],
|
|
@@ -575,6 +622,29 @@ async function handleStacksList(_input, _server) {
|
|
|
575
622
|
return { content: [{ type: "text", text: JSON.stringify({ stacks }, null, 2) }] };
|
|
576
623
|
}
|
|
577
624
|
|
|
625
|
+
// src/mcp/tools/_confirm.ts
|
|
626
|
+
async function confirmDestructive(server, opts) {
|
|
627
|
+
const capabilities = server.server.getClientCapabilities();
|
|
628
|
+
if (!capabilities?.elicitation) {
|
|
629
|
+
return {
|
|
630
|
+
confirmed: false,
|
|
631
|
+
reason: `This client cannot show a confirmation prompt, and ${opts.what} is not something clawops will do unconfirmed. Ask the user to confirm, then call this tool again with \`yes: true\`. (The client did not declare the MCP elicitation capability.)`
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
const elicit = await server.server.elicitInput({
|
|
635
|
+
message: opts.message,
|
|
636
|
+
requestedSchema: {
|
|
637
|
+
type: "object",
|
|
638
|
+
properties: { confirmed: { type: "boolean", title: opts.title } },
|
|
639
|
+
required: ["confirmed"]
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
if (elicit.action !== "accept" || !elicit.content?.["confirmed"]) {
|
|
643
|
+
return { confirmed: false, reason: `Cancelled \u2014 ${opts.what} did not run. Nothing was changed.` };
|
|
644
|
+
}
|
|
645
|
+
return { confirmed: true };
|
|
646
|
+
}
|
|
647
|
+
|
|
578
648
|
// src/mcp/tools/cli/config.ts
|
|
579
649
|
async function handleConfigGet(input, _server) {
|
|
580
650
|
const ac = new AbortController();
|
|
@@ -596,16 +666,13 @@ async function handleConfigGet(input, _server) {
|
|
|
596
666
|
}
|
|
597
667
|
}
|
|
598
668
|
async function handleConfigSet(input, server) {
|
|
599
|
-
const
|
|
669
|
+
const confirmation = await confirmDestructive(server, {
|
|
600
670
|
message: `Set ${input.key} = ${input.value} on stack "${input.stackName ?? "default"}"?`,
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
properties: { confirmed: { type: "boolean", title: "Confirm config change" } },
|
|
604
|
-
required: ["confirmed"]
|
|
605
|
-
}
|
|
671
|
+
title: "Confirm config change",
|
|
672
|
+
what: "changing gateway configuration"
|
|
606
673
|
});
|
|
607
|
-
if (
|
|
608
|
-
return okText(
|
|
674
|
+
if (!confirmation.confirmed) {
|
|
675
|
+
return okText(confirmation.reason);
|
|
609
676
|
}
|
|
610
677
|
const ac = new AbortController();
|
|
611
678
|
const ctx = buildContext({ stack: input.stackName });
|
|
@@ -645,16 +712,13 @@ async function handleConfigSet(input, server) {
|
|
|
645
712
|
}
|
|
646
713
|
}
|
|
647
714
|
async function handleConfigUnset(input, server) {
|
|
648
|
-
const
|
|
715
|
+
const confirmation = await confirmDestructive(server, {
|
|
649
716
|
message: `Remove config key "${input.key}" on stack "${input.stackName ?? "default"}"?`,
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
properties: { confirmed: { type: "boolean", title: "Confirm key removal" } },
|
|
653
|
-
required: ["confirmed"]
|
|
654
|
-
}
|
|
717
|
+
title: "Confirm key removal",
|
|
718
|
+
what: "changing gateway configuration"
|
|
655
719
|
});
|
|
656
|
-
if (
|
|
657
|
-
return okText(
|
|
720
|
+
if (!confirmation.confirmed) {
|
|
721
|
+
return okText(confirmation.reason);
|
|
658
722
|
}
|
|
659
723
|
const ac = new AbortController();
|
|
660
724
|
const ctx = buildContext({ stack: input.stackName });
|
|
@@ -759,16 +823,13 @@ async function handleAgentsList(input, _server) {
|
|
|
759
823
|
|
|
760
824
|
// src/mcp/tools/cli/gateway.ts
|
|
761
825
|
async function handleGatewayRestart(input, server) {
|
|
762
|
-
const
|
|
826
|
+
const confirmation = await confirmDestructive(server, {
|
|
763
827
|
message: `Restart the OpenClaw gateway on stack "${input.stackName ?? "default"}"? This will briefly interrupt connections.`,
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
properties: { confirmed: { type: "boolean", title: "Confirm restart" } },
|
|
767
|
-
required: ["confirmed"]
|
|
768
|
-
}
|
|
828
|
+
title: "Confirm restart",
|
|
829
|
+
what: "restarting the gateway"
|
|
769
830
|
});
|
|
770
|
-
if (
|
|
771
|
-
return okText(
|
|
831
|
+
if (!confirmation.confirmed) {
|
|
832
|
+
return okText(confirmation.reason);
|
|
772
833
|
}
|
|
773
834
|
const ctx = buildContext({ stack: input.stackName });
|
|
774
835
|
const conn = await resolveConn(ctx);
|
|
@@ -828,16 +889,13 @@ function makeProgressEmitter(server, progressToken) {
|
|
|
828
889
|
// src/mcp/tools/cli/up.ts
|
|
829
890
|
async function handleUp(input, server) {
|
|
830
891
|
if (!input.dryRun) {
|
|
831
|
-
const
|
|
892
|
+
const confirmation = await confirmDestructive(server, {
|
|
832
893
|
message: `Deploy stack "${input.stackName ?? "default"}" (provider: ${input.provider ?? "from config"}, instance: ${input.instanceType})? This will provision cloud resources.`,
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
properties: { confirmed: { type: "boolean", title: "Confirm deployment" } },
|
|
836
|
-
required: ["confirmed"]
|
|
837
|
-
}
|
|
894
|
+
title: "Confirm deployment",
|
|
895
|
+
what: "provisioning cloud resources"
|
|
838
896
|
});
|
|
839
|
-
if (
|
|
840
|
-
return okText(
|
|
897
|
+
if (!confirmation.confirmed) {
|
|
898
|
+
return okText(confirmation.reason);
|
|
841
899
|
}
|
|
842
900
|
}
|
|
843
901
|
const ctx = buildContext({ stack: input.stackName, provider: input.provider });
|
|
@@ -850,7 +908,7 @@ async function handleUp(input, server) {
|
|
|
850
908
|
);
|
|
851
909
|
}
|
|
852
910
|
const { localOpts } = stackConfig;
|
|
853
|
-
const { localBootstrap } = await import("./bootstrap-
|
|
911
|
+
const { localBootstrap } = await import("./bootstrap-3PBVY7MA.js");
|
|
854
912
|
const ac = new AbortController();
|
|
855
913
|
const state = await localBootstrap({
|
|
856
914
|
host: localOpts.host,
|
|
@@ -873,8 +931,8 @@ async function handleUp(input, server) {
|
|
|
873
931
|
const progressToken = void 0;
|
|
874
932
|
const emit = makeProgressEmitter(server, progressToken);
|
|
875
933
|
startTask(taskId, `clawops_up stack=${ctx.stackName}`);
|
|
876
|
-
const { generatePlan: generatePlan2 } = await import("./generate-
|
|
877
|
-
const { applyPlan: applyPlan2 } = await import("./apply-
|
|
934
|
+
const { generatePlan: generatePlan2 } = await import("./generate-NE54BATS.js");
|
|
935
|
+
const { applyPlan: applyPlan2 } = await import("./apply-JARPVA5Y.js");
|
|
878
936
|
const { resolveNetworkFlags } = await import("./network-args-PYJRJBYO.js");
|
|
879
937
|
const { detectEgressIp } = await import("./firewall-5VKZ4WBH.js");
|
|
880
938
|
const network = await resolveNetworkFlags(
|
|
@@ -926,16 +984,13 @@ async function handleUp(input, server) {
|
|
|
926
984
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
927
985
|
async function handleDestroy(input, server) {
|
|
928
986
|
if (!input.yes) {
|
|
929
|
-
const
|
|
987
|
+
const confirmation = await confirmDestructive(server, {
|
|
930
988
|
message: `DESTROY stack "${input.stackName}"? This permanently deletes all provisioned resources and cannot be undone.`,
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
properties: { confirmed: { type: "boolean", title: "Confirm destruction (irreversible)" } },
|
|
934
|
-
required: ["confirmed"]
|
|
935
|
-
}
|
|
989
|
+
title: "Confirm destruction (irreversible)",
|
|
990
|
+
what: "destroying a stack"
|
|
936
991
|
});
|
|
937
|
-
if (
|
|
938
|
-
return okText(
|
|
992
|
+
if (!confirmation.confirmed) {
|
|
993
|
+
return okText(confirmation.reason);
|
|
939
994
|
}
|
|
940
995
|
}
|
|
941
996
|
const ctx = buildContext({ stack: input.stackName });
|
|
@@ -992,7 +1047,7 @@ async function handlePlan(input, _server) {
|
|
|
992
1047
|
let network = resolved;
|
|
993
1048
|
if (input.privateOnly) {
|
|
994
1049
|
const { privateOnlyNetwork, assertTailnetReachable } = await import("./private-only-DIA26I2E.js");
|
|
995
|
-
const { probeSsh } = await import("./tailscale-cutover-
|
|
1050
|
+
const { probeSsh } = await import("./tailscale-cutover-EKAQSDXP.js");
|
|
996
1051
|
network = privateOnlyNetwork(flags, resolved, ctx.config.stacks[stackName]?.tailscale, stackName);
|
|
997
1052
|
await assertTailnetReachable(ctx, (conn) => probeSsh(conn));
|
|
998
1053
|
}
|
|
@@ -1029,30 +1084,31 @@ async function handleHarden(input, server) {
|
|
|
1029
1084
|
"tailscale and tailscaleRevert do the opposite of each other; pass one, not both."
|
|
1030
1085
|
);
|
|
1031
1086
|
}
|
|
1032
|
-
const { getConfig: getConfig2 } = await import("./store-
|
|
1087
|
+
const { getConfig: getConfig2 } = await import("./store-YOLQYXMB.js");
|
|
1033
1088
|
const config = getConfig2();
|
|
1034
|
-
if (!config)
|
|
1089
|
+
if (!config) {
|
|
1090
|
+
return errText(
|
|
1091
|
+
"No clawops config on this machine. Call clawops_init first to register a stack; until then every clawops tool will say this."
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1035
1094
|
const ctx = buildContext({ stack: input.stackName });
|
|
1036
1095
|
if (!input.dryRun && !input.yes) {
|
|
1037
1096
|
const what = input.tailscaleRevert ? `Take "${ctx.stackName}" off its tailnet and go back to its public address?` : input.tailscale ? `Harden "${ctx.stackName}" and join it to your tailnet? clawops will use the tailnet address afterwards.` : `Apply hardening modules to "${ctx.stackName}"? This changes the running host.`;
|
|
1038
|
-
const
|
|
1097
|
+
const confirmation = await confirmDestructive(server, {
|
|
1039
1098
|
message: what,
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
properties: { confirmed: { type: "boolean", title: "Confirm" } },
|
|
1043
|
-
required: ["confirmed"]
|
|
1044
|
-
}
|
|
1099
|
+
title: "Confirm",
|
|
1100
|
+
what: "changing a running host"
|
|
1045
1101
|
});
|
|
1046
|
-
if (
|
|
1047
|
-
return okText(
|
|
1102
|
+
if (!confirmation.confirmed) {
|
|
1103
|
+
return okText(confirmation.reason);
|
|
1048
1104
|
}
|
|
1049
1105
|
}
|
|
1050
|
-
const { revertTailnet, cutOverToTailnet, connectionFor } = await import("./flows-
|
|
1106
|
+
const { revertTailnet, cutOverToTailnet, connectionFor } = await import("./flows-HGJIA6EL.js");
|
|
1051
1107
|
if (input.tailscaleRevert) {
|
|
1052
1108
|
const outcome = await revertTailnet(ctx, config);
|
|
1053
1109
|
return outcome.ok ? okText(outcome.message) : errText(outcome.reason);
|
|
1054
1110
|
}
|
|
1055
|
-
const { MODULE_CATALOG, resolveModules, runHardening, formatHardenSummary, makeTailscaleModule } = await import("./harden-
|
|
1111
|
+
const { MODULE_CATALOG, resolveModules, runHardening, formatHardenSummary, makeTailscaleModule } = await import("./harden-RUOUA5BV.js");
|
|
1056
1112
|
const forStack = makeTailscaleModule(ctx.stackName);
|
|
1057
1113
|
const resolved = resolveModules(MODULE_CATALOG, input.options, ctx.adapter.name).map(
|
|
1058
1114
|
(m) => m.id === "tailscale" ? forStack : m
|
|
@@ -1094,6 +1150,32 @@ async function handleHarden(input, server) {
|
|
|
1094
1150
|
return failed.length > 0 ? errText(content) : okText(content);
|
|
1095
1151
|
}
|
|
1096
1152
|
|
|
1153
|
+
// src/mcp/tools/cli/init.ts
|
|
1154
|
+
async function handleInit(input, _server) {
|
|
1155
|
+
const { initStack } = await import("./init-HOPXDNWY.js");
|
|
1156
|
+
const result = await initStack({
|
|
1157
|
+
provider: input.provider,
|
|
1158
|
+
stackName: input.stackName,
|
|
1159
|
+
stateUrl: input.stateUrl,
|
|
1160
|
+
region: input.region,
|
|
1161
|
+
force: input.force,
|
|
1162
|
+
host: input.host,
|
|
1163
|
+
sshUser: input.sshUser,
|
|
1164
|
+
sshPort: input.sshPort
|
|
1165
|
+
});
|
|
1166
|
+
if (!result.ok) return errText(result.reason);
|
|
1167
|
+
const lines = [
|
|
1168
|
+
`Stack "${result.stackName}" registered for ${result.provider}.`,
|
|
1169
|
+
`Config: ${result.configPath}`,
|
|
1170
|
+
`State backend: ${result.stateUrl}`,
|
|
1171
|
+
...result.region ? [`Region: ${result.region}`] : [],
|
|
1172
|
+
`SSH key: ${result.keyPath}${result.keyGenerated ? " (generated now)" : " (already existed)"}`,
|
|
1173
|
+
"",
|
|
1174
|
+
"Nothing has been provisioned and nothing is being charged. Deploying from here needs cloud credentials in the environment clawops runs in; clawops_doctor reports which are missing."
|
|
1175
|
+
];
|
|
1176
|
+
return okText(lines.join("\n"));
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1097
1179
|
// src/mcp/tools/cli/apply.ts
|
|
1098
1180
|
import { readFileSync } from "fs";
|
|
1099
1181
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
@@ -1115,18 +1197,15 @@ ${validation.errors.join("\n")}`);
|
|
|
1115
1197
|
}
|
|
1116
1198
|
if (!input.yes) {
|
|
1117
1199
|
const diffLine = plan.diff ? `${plan.diff.create.length} to create, ${plan.diff.update.length} to update, ${plan.diff.delete.length} to delete` : "diff unavailable";
|
|
1118
|
-
const
|
|
1200
|
+
const confirmation = await confirmDestructive(server, {
|
|
1119
1201
|
message: `Apply plan for stack "${plan.spec.stackName}" (${plan.spec.provider})?
|
|
1120
1202
|
Changes: ${diffLine}.
|
|
1121
1203
|
This will provision cloud resources and may incur costs.`,
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
properties: { confirmed: { type: "boolean", title: "Confirm plan apply" } },
|
|
1125
|
-
required: ["confirmed"]
|
|
1126
|
-
}
|
|
1204
|
+
title: "Confirm plan apply",
|
|
1205
|
+
what: "applying a plan"
|
|
1127
1206
|
});
|
|
1128
|
-
if (
|
|
1129
|
-
return okText(
|
|
1207
|
+
if (!confirmation.confirmed) {
|
|
1208
|
+
return okText(confirmation.reason);
|
|
1130
1209
|
}
|
|
1131
1210
|
}
|
|
1132
1211
|
const taskId = randomUUID4();
|
|
@@ -1255,17 +1334,14 @@ Falling back to direct deployment.`);
|
|
|
1255
1334
|
);
|
|
1256
1335
|
}
|
|
1257
1336
|
const diffLine = plan.diff ? `${plan.diff.create.length} to create, ${plan.diff.update.length} to update, ${plan.diff.delete.length} to delete` : "? changes";
|
|
1258
|
-
const
|
|
1337
|
+
const confirmation = await confirmDestructive(server, {
|
|
1259
1338
|
message: `Deploy OpenClaw on ${provider} (stack: "${input.stackName}", instance: ${input.instanceType}${input.region ? `, region: ${input.region}` : ""})?
|
|
1260
1339
|
Changes: ${diffLine}. This will provision cloud resources and may incur costs.`,
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
properties: { confirmed: { type: "boolean", title: "Confirm end-to-end deployment" } },
|
|
1264
|
-
required: ["confirmed"]
|
|
1265
|
-
}
|
|
1340
|
+
title: "Confirm end-to-end deployment",
|
|
1341
|
+
what: "provisioning cloud resources"
|
|
1266
1342
|
});
|
|
1267
|
-
if (
|
|
1268
|
-
return okText(
|
|
1343
|
+
if (!confirmation.confirmed) {
|
|
1344
|
+
return okText(confirmation.reason);
|
|
1269
1345
|
}
|
|
1270
1346
|
parts.push("### Step 2: Apply");
|
|
1271
1347
|
const emit = makeProgressEmitter(server, void 0);
|
|
@@ -1329,29 +1405,30 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
1329
1405
|
}
|
|
1330
1406
|
|
|
1331
1407
|
// src/mcp/tools/registry.ts
|
|
1332
|
-
function makeEntry(schema, annotations, handler) {
|
|
1333
|
-
return { schema, annotations, handler };
|
|
1408
|
+
function makeEntry(schema, annotations, handler, description) {
|
|
1409
|
+
return { schema, annotations, handler, description };
|
|
1334
1410
|
}
|
|
1335
1411
|
var TOOL_REGISTRY = {
|
|
1336
|
-
clawops_status: makeEntry(clawops_statusSchema, clawops_statusAnnotations, handleStatus),
|
|
1337
|
-
clawops_doctor: makeEntry(clawops_doctorSchema, clawops_doctorAnnotations, handleDoctor),
|
|
1338
|
-
clawops_logs_tail: makeEntry(clawops_logs_tailSchema, clawops_logs_tailAnnotations, handleLogsTail),
|
|
1339
|
-
clawops_monitor: makeEntry(clawops_monitorSchema, clawops_monitorAnnotations, handleMonitor),
|
|
1340
|
-
clawops_stacks_list: makeEntry(clawops_stacks_listSchema, clawops_stacks_listAnnotations, handleStacksList),
|
|
1341
|
-
clawops_config_get: makeEntry(clawops_config_getSchema, clawops_config_getAnnotations, handleConfigGet),
|
|
1342
|
-
clawops_agents_list: makeEntry(clawops_agents_listSchema, clawops_agents_listAnnotations, handleAgentsList),
|
|
1343
|
-
clawops_up: makeEntry(clawops_upSchema, clawops_upAnnotations, handleUp),
|
|
1344
|
-
clawops_destroy: makeEntry(clawops_destroySchema, clawops_destroyAnnotations, handleDestroy),
|
|
1345
|
-
clawops_apply: makeEntry(clawops_applySchema, clawops_applyAnnotations, handleApply),
|
|
1346
|
-
clawops_plan: makeEntry(clawops_planSchema, clawops_planAnnotations, handlePlan),
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1412
|
+
clawops_status: makeEntry(clawops_statusSchema, clawops_statusAnnotations, handleStatus, clawops_statusDescription),
|
|
1413
|
+
clawops_doctor: makeEntry(clawops_doctorSchema, clawops_doctorAnnotations, handleDoctor, clawops_doctorDescription),
|
|
1414
|
+
clawops_logs_tail: makeEntry(clawops_logs_tailSchema, clawops_logs_tailAnnotations, handleLogsTail, clawops_logs_tailDescription),
|
|
1415
|
+
clawops_monitor: makeEntry(clawops_monitorSchema, clawops_monitorAnnotations, handleMonitor, clawops_monitorDescription),
|
|
1416
|
+
clawops_stacks_list: makeEntry(clawops_stacks_listSchema, clawops_stacks_listAnnotations, handleStacksList, clawops_stacks_listDescription),
|
|
1417
|
+
clawops_config_get: makeEntry(clawops_config_getSchema, clawops_config_getAnnotations, handleConfigGet, clawops_config_getDescription),
|
|
1418
|
+
clawops_agents_list: makeEntry(clawops_agents_listSchema, clawops_agents_listAnnotations, handleAgentsList, clawops_agents_listDescription),
|
|
1419
|
+
clawops_up: makeEntry(clawops_upSchema, clawops_upAnnotations, handleUp, clawops_upDescription),
|
|
1420
|
+
clawops_destroy: makeEntry(clawops_destroySchema, clawops_destroyAnnotations, handleDestroy, clawops_destroyDescription),
|
|
1421
|
+
clawops_apply: makeEntry(clawops_applySchema, clawops_applyAnnotations, handleApply, clawops_applyDescription),
|
|
1422
|
+
clawops_plan: makeEntry(clawops_planSchema, clawops_planAnnotations, handlePlan, clawops_planDescription),
|
|
1423
|
+
clawops_init: makeEntry(clawops_initSchema, clawops_initAnnotations, handleInit, clawops_initDescription),
|
|
1424
|
+
clawops_harden: makeEntry(clawops_hardenSchema, clawops_hardenAnnotations, handleHarden, clawops_hardenDescription),
|
|
1425
|
+
clawops_config_set: makeEntry(clawops_config_setSchema, clawops_config_setAnnotations, handleConfigSet, clawops_config_setDescription),
|
|
1426
|
+
clawops_config_unset: makeEntry(clawops_config_unsetSchema, clawops_config_unsetAnnotations, handleConfigUnset, clawops_config_unsetDescription),
|
|
1427
|
+
clawops_config_validate: makeEntry(clawops_config_validateSchema, clawops_config_validateAnnotations, handleConfigValidate, clawops_config_validateDescription),
|
|
1428
|
+
clawops_gateway_restart: makeEntry(clawops_gateway_restartSchema, clawops_gateway_restartAnnotations, handleGatewayRestart, clawops_gateway_restartDescription),
|
|
1429
|
+
clawops_workflow_deploy_app: makeEntry(clawops_workflow_deploy_appSchema, clawops_workflow_deploy_appAnnotations, handleWorkflowDeployApp, clawops_workflow_deploy_appDescription),
|
|
1430
|
+
clawops_workflow_recover: makeEntry(clawops_workflow_recoverSchema, clawops_workflow_recoverAnnotations, handleWorkflowRecover, clawops_workflow_recoverDescription),
|
|
1431
|
+
clawops_task_status: makeEntry(clawops_task_statusSchema, clawops_task_statusAnnotations, handleTaskStatus, clawops_task_statusDescription)
|
|
1355
1432
|
};
|
|
1356
1433
|
var TOOL_NAMES = Object.keys(TOOL_REGISTRY);
|
|
1357
1434
|
function resolveEnabledTools(opts) {
|
|
@@ -1380,13 +1457,16 @@ function registerTools(server, opts) {
|
|
|
1380
1457
|
for (const toolName of enabled) {
|
|
1381
1458
|
const entry = TOOL_REGISTRY[toolName];
|
|
1382
1459
|
if (!entry) continue;
|
|
1383
|
-
const { schema, annotations, handler } = entry;
|
|
1460
|
+
const { schema, annotations, handler, description } = entry;
|
|
1384
1461
|
const { title, readOnlyHint, destructiveHint, idempotentHint, openWorldHint } = annotations;
|
|
1385
1462
|
const audited = withAudit(toolName, (input) => handler(input, server));
|
|
1386
1463
|
server.registerTool(
|
|
1387
1464
|
toolName,
|
|
1388
1465
|
{
|
|
1389
1466
|
title,
|
|
1467
|
+
// What a model reads when it picks a tool. Written per R3 to say when to use this one
|
|
1468
|
+
// and when to reach for another; omitted here, every client saw a nameless capability.
|
|
1469
|
+
description,
|
|
1390
1470
|
inputSchema: schema,
|
|
1391
1471
|
annotations: { title, readOnlyHint, destructiveHint, idempotentHint, openWorldHint }
|
|
1392
1472
|
},
|
|
@@ -1646,7 +1726,7 @@ function bearerFrom(header) {
|
|
|
1646
1726
|
return match?.[1]?.trim();
|
|
1647
1727
|
}
|
|
1648
1728
|
async function serveMcp(opts) {
|
|
1649
|
-
const { version } = await import("./package-
|
|
1729
|
+
const { version } = await import("./package-MF5LPITL.js");
|
|
1650
1730
|
const makeServer = () => {
|
|
1651
1731
|
const server = new McpServer({ name: "clawops", version });
|
|
1652
1732
|
registerTools(server, opts);
|