@cloudgrid-io/mcp 0.5.1 → 0.5.2
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 +11 -6
- package/package.json +2 -1
- package/src/tools.js +46 -59
package/README.md
CHANGED
|
@@ -13,6 +13,13 @@ The local edition wraps the `cloudgrid` CLI for authenticated operations (the CL
|
|
|
13
13
|
handles auth, org context, and error formatting) and calls the API directly for the
|
|
14
14
|
drop, claim, and login tools.
|
|
15
15
|
|
|
16
|
+
## CLI compatibility
|
|
17
|
+
|
|
18
|
+
MCP 0.5.2 is tested against CLI 0.10.1. The lazy-npx fallback pins
|
|
19
|
+
`@cloudgrid-io/cli@~0.10.1` so a future CLI major with renamed verbs cannot
|
|
20
|
+
silently break a released MCP. A CI drift guard (`npm run test:drift-guard`)
|
|
21
|
+
asserts every wrapped verb exists in the CLI help.
|
|
22
|
+
|
|
16
23
|
## Prerequisite
|
|
17
24
|
|
|
18
25
|
Install and log in to the CLI:
|
|
@@ -67,24 +74,22 @@ also work in the web edition where no CLI exists. `cloudgrid_login` writes the s
|
|
|
67
74
|
| `cloudgrid_logs` | `cloudgrid logs` | Snapshot of recent logs. Does not stream. Read-only. |
|
|
68
75
|
| `cloudgrid_share` | `cloudgrid visibility set` | Set visibility, default link. |
|
|
69
76
|
| `cloudgrid_feedback` | `cloudgrid feedback list` | Read the org feedback feed. Read-only. |
|
|
70
|
-
| `cloudgrid_brain` | `cloudgrid brain refresh` | Re-run the Grid Brain hooks. |
|
|
71
77
|
| `cloudgrid_whoami` | `cloudgrid whoami` | Show the signed-in user and active org. Read-only. |
|
|
72
78
|
| `cloudgrid_use` | `cloudgrid use` | Switch the active org. |
|
|
73
79
|
| `cloudgrid_logout` | `cloudgrid logout` | Sign out and clear local credentials. Destructive. |
|
|
74
80
|
| `cloudgrid_status` | `cloudgrid status` | Org dashboard or entity detail. Read-only. |
|
|
75
81
|
| `cloudgrid_info` | `cloudgrid info` | Entity metadata. Read-only. |
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `cloudgrid_rename` | `cloudgrid rename` | Rename an entity. |
|
|
82
|
+
| `cloudgrid_grid` | `cloudgrid get entities` | List entities on the grid. Read-only. |
|
|
83
|
+
| `cloudgrid_rename` | `cloudgrid rename` | Rename an entity's display name. |
|
|
79
84
|
| `cloudgrid_unplug` | `cloudgrid unplug` | Take an entity off the grid. Destructive; requires confirm. |
|
|
80
|
-
| `cloudgrid_delete` | `cloudgrid delete` | Archive
|
|
85
|
+
| `cloudgrid_delete` | `cloudgrid delete entity` | Archive an inspiration. Destructive; requires confirm. |
|
|
81
86
|
| `cloudgrid_rollback` | `cloudgrid rollback` | Rollback to a previous version. |
|
|
82
87
|
| `cloudgrid_versions` | `cloudgrid versions` | List published versions. Read-only. |
|
|
83
88
|
| `cloudgrid_env` | `cloudgrid env` | Get, set, or list environment variables. |
|
|
84
89
|
| `cloudgrid_secrets` | `cloudgrid secrets` | Set or list secret names. Never returns secret values. |
|
|
85
90
|
| `cloudgrid_scaffold` | `cloudgrid scaffold` | Generate starter files. |
|
|
86
91
|
| `cloudgrid_doctor` | `cloudgrid doctor` | Run local diagnostics. Read-only. |
|
|
87
|
-
| `cloudgrid_open` | `cloudgrid open` | Return the public URL. Does not open a browser. Read-only. |
|
|
92
|
+
| `cloudgrid_open` | `cloudgrid open --print` | Return the public URL. Does not open a browser. Read-only. |
|
|
88
93
|
|
|
89
94
|
`cloudgrid_share` and `cloudgrid_visibility` overlap on purpose: `cloudgrid_share`
|
|
90
95
|
wraps the CLI and defaults to `link`; `cloudgrid_visibility` is direct API, takes an
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudgrid-io/mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "MCP server for CloudGrid. Three editions: a local stdio server (full toolset), a hosted web server (light, CLI-free toolset), and a public docs server (search_cloudgrid_documentation) over MCP Streamable HTTP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"start": "node src/index.js",
|
|
17
17
|
"start:web": "node src/web.js",
|
|
18
18
|
"smoke": "node test/smoke.mjs",
|
|
19
|
+
"test:drift-guard": "node test/drift-guard.mjs",
|
|
19
20
|
"smoke:drop": "node test/smoke-drop.mjs",
|
|
20
21
|
"smoke:login": "node test/smoke-login.mjs",
|
|
21
22
|
"smoke:claim": "node test/smoke-claim.mjs",
|
package/src/tools.js
CHANGED
|
@@ -75,10 +75,37 @@ function resolveCwd(cwd) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
// Pin the CLI version for the lazy npx fallback so behaviour is reproducible.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
// MCP 0.5.2 is tested against CLI 0.10.1.
|
|
79
|
+
const CLI_NPX_PKG = "@cloudgrid-io/cli@~0.10.1";
|
|
80
|
+
|
|
81
|
+
// Minimum CLI version that supports the verbs and flags the MCP passes.
|
|
82
|
+
const MIN_CLI_VERSION = "0.10.1";
|
|
83
|
+
|
|
84
|
+
// Verb map for the drift guard: each CLI-wrapping tool's top-level verb(s).
|
|
85
|
+
// The drift-guard test imports this and asserts every verb exists in `cloudgrid --help`.
|
|
86
|
+
export const CLI_TOOL_VERBS = {
|
|
87
|
+
cloudgrid_init: ["init"],
|
|
88
|
+
cloudgrid_plug: ["plug"],
|
|
89
|
+
cloudgrid_logs: ["logs"],
|
|
90
|
+
cloudgrid_share: ["visibility"],
|
|
91
|
+
cloudgrid_feedback: ["feedback"],
|
|
92
|
+
cloudgrid_whoami: ["whoami"],
|
|
93
|
+
cloudgrid_use: ["use"],
|
|
94
|
+
cloudgrid_logout: ["logout"],
|
|
95
|
+
cloudgrid_status: ["status"],
|
|
96
|
+
cloudgrid_info: ["info"],
|
|
97
|
+
cloudgrid_grid: ["get"],
|
|
98
|
+
cloudgrid_rename: ["rename"],
|
|
99
|
+
cloudgrid_unplug: ["unplug"],
|
|
100
|
+
cloudgrid_delete: ["delete"],
|
|
101
|
+
cloudgrid_rollback: ["rollback"],
|
|
102
|
+
cloudgrid_versions: ["versions"],
|
|
103
|
+
cloudgrid_env: ["env"],
|
|
104
|
+
cloudgrid_secrets: ["secrets"],
|
|
105
|
+
cloudgrid_scaffold: ["scaffold"],
|
|
106
|
+
cloudgrid_doctor: ["doctor"],
|
|
107
|
+
cloudgrid_open: ["open"],
|
|
108
|
+
};
|
|
82
109
|
|
|
83
110
|
// Simple semver comparison: true when `version` >= MIN_CLI_VERSION.
|
|
84
111
|
function meetsMinVersion(version) {
|
|
@@ -1006,7 +1033,7 @@ export function registerTools(server, ctx) {
|
|
|
1006
1033
|
"Set an entity's visibility and print its URL. Defaults to link (anyone with the URL). Wraps `cloudgrid visibility set`.",
|
|
1007
1034
|
{
|
|
1008
1035
|
name: z.string().describe("Entity slug."),
|
|
1009
|
-
mode: z.enum(["link", "private", "authenticated", "
|
|
1036
|
+
mode: z.enum(["link", "private", "authenticated", "grid"]).optional().describe("Visibility mode. Default link."),
|
|
1010
1037
|
},
|
|
1011
1038
|
{ readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
1012
1039
|
cliTool(({ name, mode }) => ["visibility", "set", name, mode ?? "link"]),
|
|
@@ -1030,23 +1057,6 @@ export function registerTools(server, ctx) {
|
|
|
1030
1057
|
}),
|
|
1031
1058
|
);
|
|
1032
1059
|
|
|
1033
|
-
server.tool(
|
|
1034
|
-
"cloudgrid_brain",
|
|
1035
|
-
"Re-run an entity's Grid Brain hooks to re-classify its description, tags, and diagram. Wraps `cloudgrid brain refresh`.",
|
|
1036
|
-
{
|
|
1037
|
-
name: z.string().describe("Entity slug."),
|
|
1038
|
-
wait: z.boolean().optional().describe("Wait for the refresh to finish. Default true."),
|
|
1039
|
-
org: z.string().optional().describe("Target an entity in another org."),
|
|
1040
|
-
},
|
|
1041
|
-
{ readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
1042
|
-
cliTool(({ name, wait, org }) => {
|
|
1043
|
-
const args = ["brain", "refresh", name];
|
|
1044
|
-
if (wait !== false) args.push("--wait");
|
|
1045
|
-
if (org) args.push("--org", org);
|
|
1046
|
-
return args;
|
|
1047
|
-
}),
|
|
1048
|
-
);
|
|
1049
|
-
|
|
1050
1060
|
// ── New CLI-wrapping tools (local edition only) ───────────────────────────
|
|
1051
1061
|
|
|
1052
1062
|
server.tool(
|
|
@@ -1093,36 +1103,20 @@ export function registerTools(server, ctx) {
|
|
|
1093
1103
|
}),
|
|
1094
1104
|
);
|
|
1095
1105
|
|
|
1096
|
-
server.tool(
|
|
1097
|
-
"cloudgrid_builds",
|
|
1098
|
-
"List recent builds and deploys for an entity. Wraps `cloudgrid builds`.",
|
|
1099
|
-
{
|
|
1100
|
-
name: z.string().optional().describe("Entity name. Omit for the entity linked to the current directory."),
|
|
1101
|
-
limit: z.number().int().positive().optional().describe("Number of builds to show."),
|
|
1102
|
-
},
|
|
1103
|
-
{ readOnlyHint: true, destructiveHint: false, openWorldHint: true },
|
|
1104
|
-
cliTool(({ name, limit }) => {
|
|
1105
|
-
const args = ["builds"];
|
|
1106
|
-
if (name) args.push(name);
|
|
1107
|
-
if (limit) args.push("--limit", String(limit));
|
|
1108
|
-
return args;
|
|
1109
|
-
}),
|
|
1110
|
-
);
|
|
1111
|
-
|
|
1112
1106
|
server.tool(
|
|
1113
1107
|
"cloudgrid_grid",
|
|
1114
|
-
"List entities on the
|
|
1115
|
-
{
|
|
1108
|
+
"List entities on the grid. Wraps `cloudgrid get entities`.",
|
|
1109
|
+
{ grid: z.string().optional().describe("Grid slug. Omit for the active grid.") },
|
|
1116
1110
|
{ readOnlyHint: true, destructiveHint: false, openWorldHint: true },
|
|
1117
|
-
cliTool(({
|
|
1111
|
+
cliTool(({ grid }) => (grid ? ["get", "entities", "--grid", grid] : ["get", "entities"])),
|
|
1118
1112
|
);
|
|
1119
1113
|
|
|
1120
1114
|
server.tool(
|
|
1121
1115
|
"cloudgrid_rename",
|
|
1122
|
-
"Rename a CloudGrid entity. Wraps `cloudgrid rename`.",
|
|
1116
|
+
"Rename a CloudGrid entity's display name (slug stays the same). Wraps `cloudgrid rename`.",
|
|
1123
1117
|
{
|
|
1124
|
-
name: z.string().describe("
|
|
1125
|
-
new_name: z.string().describe("New
|
|
1118
|
+
name: z.string().describe("Entity slug."),
|
|
1119
|
+
new_name: z.string().describe("New display name."),
|
|
1126
1120
|
},
|
|
1127
1121
|
{ readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
1128
1122
|
cliTool(({ name, new_name }) => ["rename", name, new_name]),
|
|
@@ -1141,13 +1135,13 @@ export function registerTools(server, ctx) {
|
|
|
1141
1135
|
|
|
1142
1136
|
server.tool(
|
|
1143
1137
|
"cloudgrid_delete",
|
|
1144
|
-
"Archive
|
|
1138
|
+
"Archive a CloudGrid inspiration. Destructive. Wraps `cloudgrid delete entity`.",
|
|
1145
1139
|
{
|
|
1146
1140
|
name: z.string().describe("Entity slug to delete (required)."),
|
|
1147
1141
|
confirm: z.literal(true).describe("Must be true to proceed."),
|
|
1148
1142
|
},
|
|
1149
1143
|
{ readOnlyHint: false, destructiveHint: true, openWorldHint: true },
|
|
1150
|
-
cliTool(({ name }) => ["delete", name, "--yes"]),
|
|
1144
|
+
cliTool(({ name }) => ["delete", "entity", name, "--yes"]),
|
|
1151
1145
|
);
|
|
1152
1146
|
|
|
1153
1147
|
server.tool(
|
|
@@ -1159,7 +1153,7 @@ export function registerTools(server, ctx) {
|
|
|
1159
1153
|
},
|
|
1160
1154
|
{ readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
1161
1155
|
cliTool(({ name, to }) => {
|
|
1162
|
-
const args = ["rollback", name];
|
|
1156
|
+
const args = ["rollback", name, "--yes"];
|
|
1163
1157
|
if (to) args.push("--to", to);
|
|
1164
1158
|
return args;
|
|
1165
1159
|
}),
|
|
@@ -1215,7 +1209,7 @@ export function registerTools(server, ctx) {
|
|
|
1215
1209
|
cliTool(({ action, name, key, value }) => {
|
|
1216
1210
|
if (action === "set") {
|
|
1217
1211
|
if (!key || value === undefined) throw new Error("key and value are required for set");
|
|
1218
|
-
return ["secrets", "set", name, key
|
|
1212
|
+
return ["secrets", "set", name, `${key}=${value}`];
|
|
1219
1213
|
}
|
|
1220
1214
|
return ["secrets", "list", name];
|
|
1221
1215
|
}, { cwdParam: true }),
|
|
@@ -1223,19 +1217,12 @@ export function registerTools(server, ctx) {
|
|
|
1223
1217
|
|
|
1224
1218
|
server.tool(
|
|
1225
1219
|
"cloudgrid_scaffold",
|
|
1226
|
-
"
|
|
1220
|
+
"Scaffold service folders declared in cloudgrid.yaml (idempotent). Wraps `cloudgrid scaffold`.",
|
|
1227
1221
|
{
|
|
1228
|
-
template: z.string().optional().describe("Template name."),
|
|
1229
|
-
dir: z.string().optional().describe("Target directory."),
|
|
1230
1222
|
cwd: z.string().optional().describe("Working directory. The CLI runs in this directory. Defaults to the MCP server's working directory."),
|
|
1231
1223
|
},
|
|
1232
1224
|
{ readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
1233
|
-
cliTool((
|
|
1234
|
-
const args = ["scaffold"];
|
|
1235
|
-
if (template) args.push(template);
|
|
1236
|
-
if (dir) args.push("--dir", dir);
|
|
1237
|
-
return args;
|
|
1238
|
-
}, { cwdParam: true }),
|
|
1225
|
+
cliTool(() => ["scaffold"], { cwdParam: true }),
|
|
1239
1226
|
);
|
|
1240
1227
|
|
|
1241
1228
|
server.tool(
|
|
@@ -1248,11 +1235,11 @@ export function registerTools(server, ctx) {
|
|
|
1248
1235
|
|
|
1249
1236
|
server.tool(
|
|
1250
1237
|
"cloudgrid_open",
|
|
1251
|
-
"Return the public URL for an entity. Does not open a browser. Wraps `cloudgrid open --
|
|
1238
|
+
"Return the public URL for an entity. Does not open a browser. Wraps `cloudgrid open --print`.",
|
|
1252
1239
|
{ name: z.string().optional().describe("Entity name. Omit for the entity linked to the current directory.") },
|
|
1253
1240
|
{ readOnlyHint: true, destructiveHint: false, openWorldHint: true },
|
|
1254
1241
|
cliTool(({ name }) => {
|
|
1255
|
-
const args = ["open", "--
|
|
1242
|
+
const args = ["open", "--print"];
|
|
1256
1243
|
if (name) args.push(name);
|
|
1257
1244
|
return args;
|
|
1258
1245
|
}),
|