@hoststack.dev/mcp 0.3.0 → 0.4.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/README.md +2 -1
- package/dist/hoststack-mcp.js +204 -43
- package/dist/hoststack-mcp.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +204 -43
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ If `HOSTSTACK_API_KEY` is set in your shell, it gets baked into the snippet; oth
|
|
|
79
79
|
|
|
80
80
|
## Tool inventory
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
35 tools, grouped by resource:
|
|
83
83
|
|
|
84
84
|
| Category | Read | Write |
|
|
85
85
|
|---|---|---|
|
|
@@ -89,6 +89,7 @@ If `HOSTSTACK_API_KEY` is set in your shell, it gets baked into the snippet; oth
|
|
|
89
89
|
| **databases** | `list_databases`, `get_database` | — (use the dashboard for create/delete/credentials) |
|
|
90
90
|
| **domains** | `list_domains` | `add_domain`, `verify_domain`, `remove_domain` |
|
|
91
91
|
| **env-vars** | `list_env_vars` | `set_env_var`, `delete_env_var`, `bulk_set_env_vars` |
|
|
92
|
+
| **environments** | `list_environments` | `create_environment`, `delete_environment`, `promote_deploy` |
|
|
92
93
|
| **cron** | `list_cron_executions`, `get_cron_execution` | — |
|
|
93
94
|
| **activity-log** | `list_activity_log` | — |
|
|
94
95
|
| **meta** | `get_me` | — |
|
package/dist/hoststack-mcp.js
CHANGED
|
@@ -992,6 +992,146 @@ defineTool({
|
|
|
992
992
|
}
|
|
993
993
|
});
|
|
994
994
|
|
|
995
|
+
// src/tools/environments.ts
|
|
996
|
+
import { z as z8 } from "zod";
|
|
997
|
+
defineTool({
|
|
998
|
+
name: "list_environments",
|
|
999
|
+
category: "environments",
|
|
1000
|
+
description: [
|
|
1001
|
+
"List every environment for a project (production / staging / development / preview).",
|
|
1002
|
+
"",
|
|
1003
|
+
"When to use: the user wants to see what envs exist before creating a service in one or promoting a deploy. Every project has at least Production.",
|
|
1004
|
+
"",
|
|
1005
|
+
"Inputs:",
|
|
1006
|
+
' - project_id: project publicId (e.g. "prj_abc123").',
|
|
1007
|
+
"",
|
|
1008
|
+
"Returns: { items: Environment[] } \u2014 id, publicId, name, type, isDefault, isProtected.",
|
|
1009
|
+
"",
|
|
1010
|
+
'Example: list_environments({ project_id: "prj_abc" }) \u2192 { items: [{ name: "Production", type: "production", isDefault: true }, { name: "Staging", type: "staging" }] }'
|
|
1011
|
+
].join("\n"),
|
|
1012
|
+
input: {
|
|
1013
|
+
project_id: z8.string().describe("Project publicId.")
|
|
1014
|
+
},
|
|
1015
|
+
handler: async (args2, ctx) => {
|
|
1016
|
+
const teamId = await ctx.resolveTeamId();
|
|
1017
|
+
const response = await ctx.hoststack.environments.list(teamId, args2.project_id);
|
|
1018
|
+
const data = shapeList(response, "environments", shape);
|
|
1019
|
+
const summary = data.items.length === 0 ? "No environments yet \u2014 every project should have Production by default." : `Found ${data.items.length} environment${data.items.length === 1 ? "" : "s"}.`;
|
|
1020
|
+
return respond({ summary, data });
|
|
1021
|
+
}
|
|
1022
|
+
});
|
|
1023
|
+
defineTool({
|
|
1024
|
+
name: "create_environment",
|
|
1025
|
+
category: "environments",
|
|
1026
|
+
description: [
|
|
1027
|
+
"Create a new environment in a project (e.g. Staging, QA, Preview).",
|
|
1028
|
+
"",
|
|
1029
|
+
"When to use: the user wants to add an env so they can run a sibling service alongside production for testing or staging before release.",
|
|
1030
|
+
"",
|
|
1031
|
+
"Inputs:",
|
|
1032
|
+
" - project_id: project publicId.",
|
|
1033
|
+
" - name: human-readable name (1\u201364 chars). Shown in the env switcher.",
|
|
1034
|
+
' - type: "production" | "staging" | "development" | "preview". Determines the hostname suffix on services in this env (production stays clean; others get -staging / -dev / -preview).',
|
|
1035
|
+
" - is_protected (optional): require admin role for destructive actions in this env. Default false.",
|
|
1036
|
+
"",
|
|
1037
|
+
"Returns: { environment: Environment }.",
|
|
1038
|
+
"",
|
|
1039
|
+
'Example: create_environment({ project_id: "prj_abc", name: "Staging", type: "staging" }) \u2192 { environment: { id: 7, publicId: "environment_\u2026", name: "Staging", type: "staging" } }'
|
|
1040
|
+
].join("\n"),
|
|
1041
|
+
input: {
|
|
1042
|
+
project_id: z8.string().describe("Project publicId."),
|
|
1043
|
+
name: z8.string().min(1).max(64).describe("Environment name (1\u201364 chars)."),
|
|
1044
|
+
type: z8.enum(["production", "staging", "development", "preview"]).describe("Environment type \u2014 drives the hostname suffix."),
|
|
1045
|
+
is_protected: z8.boolean().optional().describe("Require admin role for destructive actions. Default false.")
|
|
1046
|
+
},
|
|
1047
|
+
handler: async (args2, ctx) => {
|
|
1048
|
+
const teamId = await ctx.resolveTeamId();
|
|
1049
|
+
const input = {
|
|
1050
|
+
name: args2.name,
|
|
1051
|
+
type: args2.type
|
|
1052
|
+
};
|
|
1053
|
+
if (args2.is_protected !== void 0) input.isProtected = args2.is_protected;
|
|
1054
|
+
const response = await ctx.hoststack.environments.create(teamId, args2.project_id, input);
|
|
1055
|
+
const data = { environment: shape(response.environment) };
|
|
1056
|
+
return respond({
|
|
1057
|
+
summary: `Created environment "${args2.name}" (${args2.type}) in project ${args2.project_id}.`,
|
|
1058
|
+
data
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
defineTool({
|
|
1063
|
+
name: "delete_environment",
|
|
1064
|
+
category: "environments",
|
|
1065
|
+
description: [
|
|
1066
|
+
"Delete an environment from a project.",
|
|
1067
|
+
"",
|
|
1068
|
+
"When to use: an env is no longer used (e.g. tearing down a feature branch staging). Blocked when the env still has live services or databases attached \u2014 destroy or move them first. The default env (usually Production) cannot be deleted.",
|
|
1069
|
+
"",
|
|
1070
|
+
"Inputs:",
|
|
1071
|
+
" - project_id: project publicId.",
|
|
1072
|
+
" - environment_id: environment publicId or numeric id.",
|
|
1073
|
+
"",
|
|
1074
|
+
"Returns: { success: true } on success.",
|
|
1075
|
+
"",
|
|
1076
|
+
'Example: delete_environment({ project_id: "prj_abc", environment_id: "environment_xyz" }) \u2192 { success: true }'
|
|
1077
|
+
].join("\n"),
|
|
1078
|
+
input: {
|
|
1079
|
+
project_id: z8.string().describe("Project publicId."),
|
|
1080
|
+
environment_id: z8.union([z8.string(), z8.number()]).describe("Environment publicId or numeric id.")
|
|
1081
|
+
},
|
|
1082
|
+
handler: async (args2, ctx) => {
|
|
1083
|
+
const teamId = await ctx.resolveTeamId();
|
|
1084
|
+
await ctx.hoststack.environments.delete(teamId, args2.project_id, args2.environment_id);
|
|
1085
|
+
return respond({
|
|
1086
|
+
summary: `Deleted environment ${String(args2.environment_id)} from project ${args2.project_id}.`,
|
|
1087
|
+
data: { success: true }
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
});
|
|
1091
|
+
defineTool({
|
|
1092
|
+
name: "promote_deploy",
|
|
1093
|
+
category: "environments",
|
|
1094
|
+
description: [
|
|
1095
|
+
"Promote a built deploy from one environment to another (build-once, run-many).",
|
|
1096
|
+
"",
|
|
1097
|
+
"When to use: the user has tested a deploy in staging and wants to ship that exact image to production without rebuilding. Atomic and image-based \u2014 same docker image runs on the sibling service in the target env.",
|
|
1098
|
+
"",
|
|
1099
|
+
"Inputs:",
|
|
1100
|
+
" - service_id: source service publicId (the one that owns the deploy).",
|
|
1101
|
+
" - deploy_id: source deploy publicId. Must have `dockerImageId` set (i.e. a successful build).",
|
|
1102
|
+
" - target_environment_id: env publicId or numeric id to promote into. Must be in the same project. Cannot be the source service's own env.",
|
|
1103
|
+
"",
|
|
1104
|
+
"Behaviour: if a sibling service with the same name already exists in the target env, the new deploy lands on it. Otherwise the API auto-clones the source service's build/runtime config into the target env first. Env-specific config (env vars, secret files, volumes, IP allowlists, custom domains) is NOT copied \u2014 those are per-env by design.",
|
|
1105
|
+
"",
|
|
1106
|
+
"Returns: { deploy: Deploy } \u2014 the new deploy on the target service.",
|
|
1107
|
+
"",
|
|
1108
|
+
'Example: promote_deploy({ service_id: "svc_staging", deploy_id: "dpl_built", target_environment_id: "environment_prod" }) \u2192 { deploy: { id: 99, status: "pending", trigger: "rollback", dockerImageId: "sha256:\u2026" } }'
|
|
1109
|
+
].join("\n"),
|
|
1110
|
+
input: {
|
|
1111
|
+
service_id: z8.string().describe("Source service publicId."),
|
|
1112
|
+
deploy_id: z8.string().describe("Source deploy publicId (must have a built image)."),
|
|
1113
|
+
target_environment_id: z8.union([z8.string(), z8.number()]).describe("Target environment publicId or numeric id.")
|
|
1114
|
+
},
|
|
1115
|
+
handler: async (args2, ctx) => {
|
|
1116
|
+
const teamId = await ctx.resolveTeamId();
|
|
1117
|
+
const targetEnvId = await ctx.hoststack.resolveId(args2.target_environment_id, {
|
|
1118
|
+
kind: "environment",
|
|
1119
|
+
teamId: await ctx.hoststack.resolveId(teamId, { kind: "team" })
|
|
1120
|
+
});
|
|
1121
|
+
const response = await ctx.hoststack.deploys.promote(
|
|
1122
|
+
teamId,
|
|
1123
|
+
args2.service_id,
|
|
1124
|
+
args2.deploy_id,
|
|
1125
|
+
targetEnvId
|
|
1126
|
+
);
|
|
1127
|
+
const data = { deploy: shape(response.deploy) };
|
|
1128
|
+
return respond({
|
|
1129
|
+
summary: `Promoted deploy ${args2.deploy_id} from service ${args2.service_id} to env ${String(args2.target_environment_id)}.`,
|
|
1130
|
+
data
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
});
|
|
1134
|
+
|
|
995
1135
|
// src/tools/meta.ts
|
|
996
1136
|
defineTool({
|
|
997
1137
|
name: "get_me",
|
|
@@ -1019,7 +1159,7 @@ defineTool({
|
|
|
1019
1159
|
});
|
|
1020
1160
|
|
|
1021
1161
|
// src/tools/projects.ts
|
|
1022
|
-
import { z as
|
|
1162
|
+
import { z as z9 } from "zod";
|
|
1023
1163
|
defineTool({
|
|
1024
1164
|
name: "list_projects",
|
|
1025
1165
|
category: "projects",
|
|
@@ -1059,9 +1199,9 @@ defineTool({
|
|
|
1059
1199
|
'Example: create_project({ name: "billing-api", description: "Stripe webhooks", region: "fsn1" }) \u2192 { project: { id: 12, publicId: "prj_\u2026", \u2026 } }'
|
|
1060
1200
|
].join("\n"),
|
|
1061
1201
|
input: {
|
|
1062
|
-
name:
|
|
1063
|
-
description:
|
|
1064
|
-
region:
|
|
1202
|
+
name: z9.string().min(1).max(60).describe("Project name (1\u201360 chars)."),
|
|
1203
|
+
description: z9.string().max(500).optional().describe("Short description (\u2264500 chars)."),
|
|
1204
|
+
region: z9.enum(["fsn1", "nbg1", "hel1"]).optional().describe("Hetzner region: fsn1 | nbg1 | hel1.")
|
|
1065
1205
|
},
|
|
1066
1206
|
handler: async (args2, ctx) => {
|
|
1067
1207
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1092,9 +1232,9 @@ defineTool({
|
|
|
1092
1232
|
'Example: update_project({ project_id: "prj_abc", name: "billing-prod" }) \u2192 { project: { name: "billing-prod", \u2026 } }'
|
|
1093
1233
|
].join("\n"),
|
|
1094
1234
|
input: {
|
|
1095
|
-
project_id:
|
|
1096
|
-
name:
|
|
1097
|
-
description:
|
|
1235
|
+
project_id: z9.string().describe("Project publicId."),
|
|
1236
|
+
name: z9.string().min(1).max(60).optional().describe("New name (1\u201360 chars)."),
|
|
1237
|
+
description: z9.string().max(500).optional().describe("New description (\u2264500 chars).")
|
|
1098
1238
|
},
|
|
1099
1239
|
handler: async (args2, ctx) => {
|
|
1100
1240
|
if (args2.name === void 0 && args2.description === void 0) {
|
|
@@ -1128,7 +1268,7 @@ defineTool({
|
|
|
1128
1268
|
'Example: get_project({ project_id: "prj_abc" }) \u2192 { project: { id: 12, name: "billing", \u2026 } }'
|
|
1129
1269
|
].join("\n"),
|
|
1130
1270
|
input: {
|
|
1131
|
-
project_id:
|
|
1271
|
+
project_id: z9.string().describe("Project publicId (e.g. prj_abc123).")
|
|
1132
1272
|
},
|
|
1133
1273
|
handler: async (args2, ctx) => {
|
|
1134
1274
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1140,7 +1280,7 @@ defineTool({
|
|
|
1140
1280
|
});
|
|
1141
1281
|
|
|
1142
1282
|
// src/tools/services.ts
|
|
1143
|
-
import { z as
|
|
1283
|
+
import { z as z10 } from "zod";
|
|
1144
1284
|
defineTool({
|
|
1145
1285
|
name: "list_services",
|
|
1146
1286
|
category: "services",
|
|
@@ -1178,7 +1318,7 @@ defineTool({
|
|
|
1178
1318
|
'Example: get_service({ service_id: "svc_abc" }) \u2192 { service: { type: "web", status: "running", \u2026 } }'
|
|
1179
1319
|
].join("\n"),
|
|
1180
1320
|
input: {
|
|
1181
|
-
service_id:
|
|
1321
|
+
service_id: z10.string().describe("Service publicId (e.g. svc_abc123).")
|
|
1182
1322
|
},
|
|
1183
1323
|
handler: async (args2, ctx) => {
|
|
1184
1324
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1204,7 +1344,7 @@ defineTool({
|
|
|
1204
1344
|
'Example: get_service_metrics({ service_id: "svc_abc" }) \u2192 { metrics: { cpu: 0.42, memory: 0.71, \u2026 } }'
|
|
1205
1345
|
].join("\n"),
|
|
1206
1346
|
input: {
|
|
1207
|
-
service_id:
|
|
1347
|
+
service_id: z10.string().describe("Service publicId.")
|
|
1208
1348
|
},
|
|
1209
1349
|
handler: async (args2, ctx) => {
|
|
1210
1350
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1230,8 +1370,8 @@ defineTool({
|
|
|
1230
1370
|
'Example: update_service({ service_id: "svc_abc", name: "api-prod" }) \u2192 { service: { name: "api-prod", \u2026 } }'
|
|
1231
1371
|
].join("\n"),
|
|
1232
1372
|
input: {
|
|
1233
|
-
service_id:
|
|
1234
|
-
name:
|
|
1373
|
+
service_id: z10.string().describe("Service publicId."),
|
|
1374
|
+
name: z10.string().min(1).max(60).describe("New service name (1\u201360 chars).")
|
|
1235
1375
|
},
|
|
1236
1376
|
handler: async (args2, ctx) => {
|
|
1237
1377
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1264,15 +1404,15 @@ defineTool({
|
|
|
1264
1404
|
'Example: update_service_config({ service_id: "svc_abc", start_command: "bun apps/api/src/index.ts" }) \u2192 { service: { startCommand: "bun apps/api/src/index.ts", \u2026 } }'
|
|
1265
1405
|
].join("\n"),
|
|
1266
1406
|
input: {
|
|
1267
|
-
service_id:
|
|
1268
|
-
install_command:
|
|
1269
|
-
build_command:
|
|
1270
|
-
start_command:
|
|
1271
|
-
branch:
|
|
1272
|
-
root_directory:
|
|
1273
|
-
dockerfile_path:
|
|
1274
|
-
auto_deploy:
|
|
1275
|
-
instance_count:
|
|
1407
|
+
service_id: z10.string().describe("Service publicId."),
|
|
1408
|
+
install_command: z10.string().nullable().optional().describe("Install shell command. Null clears."),
|
|
1409
|
+
build_command: z10.string().nullable().optional().describe("Build shell command. Null clears."),
|
|
1410
|
+
start_command: z10.string().nullable().optional().describe("Start shell command. Null clears."),
|
|
1411
|
+
branch: z10.string().optional().describe("Git branch to track."),
|
|
1412
|
+
root_directory: z10.string().optional().describe("Build context root."),
|
|
1413
|
+
dockerfile_path: z10.string().nullable().optional().describe("Path to Dockerfile relative to root. Null clears."),
|
|
1414
|
+
auto_deploy: z10.boolean().optional().describe("Auto-deploy on push."),
|
|
1415
|
+
instance_count: z10.number().int().positive().max(50).optional().describe("Pin min and max instances to this value (1\u201350).")
|
|
1276
1416
|
},
|
|
1277
1417
|
handler: async (args2, ctx) => {
|
|
1278
1418
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1337,7 +1477,7 @@ defineTool({
|
|
|
1337
1477
|
'Example: suspend_service({ service_id: "svc_dev" }) \u2192 { ok: true }'
|
|
1338
1478
|
].join("\n"),
|
|
1339
1479
|
input: {
|
|
1340
|
-
service_id:
|
|
1480
|
+
service_id: z10.string().describe("Service publicId.")
|
|
1341
1481
|
},
|
|
1342
1482
|
handler: async (args2, ctx) => {
|
|
1343
1483
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1361,7 +1501,7 @@ defineTool({
|
|
|
1361
1501
|
'Example: resume_service({ service_id: "svc_dev" }) \u2192 { ok: true }'
|
|
1362
1502
|
].join("\n"),
|
|
1363
1503
|
input: {
|
|
1364
|
-
service_id:
|
|
1504
|
+
service_id: z10.string().describe("Service publicId.")
|
|
1365
1505
|
},
|
|
1366
1506
|
handler: async (args2, ctx) => {
|
|
1367
1507
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1380,18 +1520,29 @@ defineTool({
|
|
|
1380
1520
|
"Inputs:",
|
|
1381
1521
|
" - service_id: publicId of the service.",
|
|
1382
1522
|
" - lines (optional): tail size (default 200, max 1000).",
|
|
1383
|
-
|
|
1523
|
+
' - since/until (optional): ISO-8601 timestamp OR a relative offset like "-5m", "-1h", "-2d".',
|
|
1384
1524
|
' - stream (optional): "stdout" | "stderr". Omit to combine.',
|
|
1525
|
+
" - level (optional): friendly synonym \u2014 info/debug \u2192 stdout, warn/error \u2192 stderr.",
|
|
1526
|
+
" - search (optional): case-insensitive substring grep, \u2264100 chars.",
|
|
1527
|
+
' - count_only (optional): when true, returns { count } only \u2014 much cheaper for "how many error lines in last 5m" polling.',
|
|
1528
|
+
"",
|
|
1529
|
+
"Returns: { logs: LogEntry[] | string } when count_only is false (each entry has { timestamp, level?, stream?, message }), or { count: number } when count_only is true.",
|
|
1385
1530
|
"",
|
|
1386
|
-
|
|
1531
|
+
'Example: get_service_logs({ service_id: "svc_abc", search: "OOM", since: "-15m" }) \u2192 { logs: [...] }.',
|
|
1387
1532
|
"",
|
|
1388
|
-
|
|
1533
|
+
"More examples:",
|
|
1534
|
+
' - Last 50 stderr lines from the past hour: get_service_logs({ service_id: "svc_abc", lines: 50, stream: "stderr", since: "-1h" })',
|
|
1535
|
+
' - Just count error lines without fetching them: get_service_logs({ service_id: "svc_abc", level: "error", since: "-5m", count_only: true }) \u2192 { count: 47 }'
|
|
1389
1536
|
].join("\n"),
|
|
1390
1537
|
input: {
|
|
1391
|
-
service_id:
|
|
1392
|
-
lines:
|
|
1393
|
-
since:
|
|
1394
|
-
|
|
1538
|
+
service_id: z10.string().describe("Service publicId."),
|
|
1539
|
+
lines: z10.number().int().positive().max(1e3).optional().describe("Tail size; default 200, hard cap 1000."),
|
|
1540
|
+
since: z10.string().optional().describe('ISO-8601 timestamp or relative offset (e.g. "-5m", "-1h").'),
|
|
1541
|
+
until: z10.string().optional().describe("ISO-8601 timestamp or relative offset upper bound."),
|
|
1542
|
+
stream: z10.enum(["stdout", "stderr"]).optional().describe("Restrict to one stream."),
|
|
1543
|
+
level: z10.enum(["stdout", "stderr", "info", "warn", "error", "debug"]).optional().describe("Friendly stream alias: info/debug\u2192stdout, warn/error\u2192stderr."),
|
|
1544
|
+
search: z10.string().max(100).optional().describe("Case-insensitive substring filter."),
|
|
1545
|
+
count_only: z10.boolean().optional().describe("When true, return only { count } \u2014 skips the log payload.")
|
|
1395
1546
|
},
|
|
1396
1547
|
handler: async (args2, ctx) => {
|
|
1397
1548
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1399,8 +1550,18 @@ defineTool({
|
|
|
1399
1550
|
lines: args2.lines ?? 200
|
|
1400
1551
|
};
|
|
1401
1552
|
if (args2.since) opts.since = args2.since;
|
|
1553
|
+
if (args2.until) opts.until = args2.until;
|
|
1402
1554
|
if (args2.stream) opts.stream = args2.stream;
|
|
1555
|
+
if (args2.level) opts.level = args2.level;
|
|
1556
|
+
if (args2.search) opts.search = args2.search;
|
|
1557
|
+
if (args2.count_only) opts.countOnly = args2.count_only;
|
|
1403
1558
|
const response = await ctx.hoststack.services.getRuntimeLogs(teamId, args2.service_id, opts);
|
|
1559
|
+
if ("count" in response) {
|
|
1560
|
+
return respond({
|
|
1561
|
+
summary: `${response.count} matching log line${response.count === 1 ? "" : "s"} for service ${args2.service_id}.`,
|
|
1562
|
+
data: { count: response.count }
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1404
1565
|
const count = Array.isArray(response.logs) ? response.logs.length : typeof response.logs === "string" ? response.logs.split("\n").length : 0;
|
|
1405
1566
|
return respond({
|
|
1406
1567
|
summary: `Fetched ${count} log line${count === 1 ? "" : "s"} for service ${args2.service_id}.`,
|
|
@@ -1410,7 +1571,7 @@ defineTool({
|
|
|
1410
1571
|
});
|
|
1411
1572
|
|
|
1412
1573
|
// src/tools/volumes.ts
|
|
1413
|
-
import { z as
|
|
1574
|
+
import { z as z11 } from "zod";
|
|
1414
1575
|
defineTool({
|
|
1415
1576
|
name: "list_volumes",
|
|
1416
1577
|
category: "volumes",
|
|
@@ -1427,7 +1588,7 @@ defineTool({
|
|
|
1427
1588
|
'Example: list_volumes({ service_id: "svc_abc" }) \u2192 { items: [{ name: "data", mountPath: "/var/data", sizeGb: 10, status: "active" }] }'
|
|
1428
1589
|
].join("\n"),
|
|
1429
1590
|
input: {
|
|
1430
|
-
service_id:
|
|
1591
|
+
service_id: z11.string().describe("Service publicId (e.g. svc_abc123).")
|
|
1431
1592
|
},
|
|
1432
1593
|
handler: async (args2, ctx) => {
|
|
1433
1594
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1456,10 +1617,10 @@ defineTool({
|
|
|
1456
1617
|
'Example: create_volume({ service_id: "svc_abc", name: "data", mount_path: "/var/data", size_gb: 10 }) \u2192 { volume: { name: "data", mountPath: "/var/data", sizeGb: 10, status: "active" } }'
|
|
1457
1618
|
].join("\n"),
|
|
1458
1619
|
input: {
|
|
1459
|
-
service_id:
|
|
1460
|
-
name:
|
|
1461
|
-
mount_path:
|
|
1462
|
-
size_gb:
|
|
1620
|
+
service_id: z11.string().describe("Service publicId."),
|
|
1621
|
+
name: z11.string().min(1).max(64).regex(/^[a-z0-9-]+$/).describe("Volume name (lowercase alphanumeric + hyphens)."),
|
|
1622
|
+
mount_path: z11.string().startsWith("/").max(500).describe("In-container mount path (absolute)."),
|
|
1623
|
+
size_gb: z11.number().int().min(1).max(100).optional().describe("Disk size in GB (default 1, max 100).")
|
|
1463
1624
|
},
|
|
1464
1625
|
handler: async (args2, ctx) => {
|
|
1465
1626
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1495,10 +1656,10 @@ defineTool({
|
|
|
1495
1656
|
'Example: update_volume({ service_id: "svc_abc", volume_id: "vol_xyz", size_gb: 20 }) \u2192 { volume: { sizeGb: 20, \u2026 } }'
|
|
1496
1657
|
].join("\n"),
|
|
1497
1658
|
input: {
|
|
1498
|
-
service_id:
|
|
1499
|
-
volume_id:
|
|
1500
|
-
mount_path:
|
|
1501
|
-
size_gb:
|
|
1659
|
+
service_id: z11.string().describe("Service publicId."),
|
|
1660
|
+
volume_id: z11.string().describe("Volume publicId (e.g. vol_\u2026)."),
|
|
1661
|
+
mount_path: z11.string().startsWith("/").max(500).optional().describe("New mount path."),
|
|
1662
|
+
size_gb: z11.number().int().min(1).max(100).optional().describe("New size in GB.")
|
|
1502
1663
|
},
|
|
1503
1664
|
handler: async (args2, ctx) => {
|
|
1504
1665
|
const teamId = await ctx.resolveTeamId();
|
|
@@ -1536,8 +1697,8 @@ defineTool({
|
|
|
1536
1697
|
'Example: delete_volume({ service_id: "svc_abc", volume_id: "vol_xyz" }) \u2192 { ok: true }'
|
|
1537
1698
|
].join("\n"),
|
|
1538
1699
|
input: {
|
|
1539
|
-
service_id:
|
|
1540
|
-
volume_id:
|
|
1700
|
+
service_id: z11.string().describe("Service publicId."),
|
|
1701
|
+
volume_id: z11.string().describe("Volume publicId.")
|
|
1541
1702
|
},
|
|
1542
1703
|
handler: async (args2, ctx) => {
|
|
1543
1704
|
const teamId = await ctx.resolveTeamId();
|