@cloudgrid-io/mcp 0.4.2 → 0.4.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/package.json +1 -1
- package/src/tools.js +44 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudgrid-io/mcp",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "MCP server for CloudGrid. Two editions: a local stdio server (full toolset) and a hosted web server (light, CLI-free toolset) over MCP Streamable HTTP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/tools.js
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
import { execFile } from "node:child_process";
|
|
12
12
|
import { promisify } from "node:util";
|
|
13
13
|
import { readFile } from "node:fs/promises";
|
|
14
|
-
import { readFileSync } from "node:fs";
|
|
15
|
-
import { basename } from "node:path";
|
|
14
|
+
import { readFileSync, existsSync, statSync } from "node:fs";
|
|
15
|
+
import { basename, resolve } from "node:path";
|
|
16
16
|
import { z } from "zod";
|
|
17
17
|
import { newLoginCode, buildLoginUrl, pollStatusOnce, decodeJwt } from "./auth.js";
|
|
18
18
|
|
|
@@ -59,11 +59,29 @@ function okResult({ text, structured, meta }) {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// ── CLI wrapping (local edition only) ──────────────────────────────────────────
|
|
62
|
-
|
|
62
|
+
|
|
63
|
+
// Resolve and validate a caller-supplied working directory. Returns the resolved
|
|
64
|
+
// absolute path, or process.cwd() when omitted.
|
|
65
|
+
function resolveCwd(cwd) {
|
|
66
|
+
if (cwd === undefined || cwd === null || cwd === "") return undefined; // let execFile default
|
|
67
|
+
const abs = resolve(cwd);
|
|
68
|
+
if (!existsSync(abs)) {
|
|
69
|
+
throw new Error(`Directory does not exist: ${abs}`);
|
|
70
|
+
}
|
|
71
|
+
if (!statSync(abs).isDirectory()) {
|
|
72
|
+
throw new Error(`Not a directory: ${abs}`);
|
|
73
|
+
}
|
|
74
|
+
return abs;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function runCloudgrid(args, opts = {}) {
|
|
78
|
+
const cwd = resolveCwd(opts.cwd);
|
|
63
79
|
try {
|
|
64
80
|
const { stdout, stderr } = await execFileAsync("cloudgrid", args, {
|
|
65
81
|
maxBuffer: 16 * 1024 * 1024,
|
|
66
82
|
timeout: 10 * 60 * 1000,
|
|
83
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
84
|
+
...(cwd ? { cwd } : {}),
|
|
67
85
|
});
|
|
68
86
|
return (stdout || stderr || "").trim() || "Done.";
|
|
69
87
|
} catch (err) {
|
|
@@ -80,10 +98,16 @@ async function runCloudgrid(args) {
|
|
|
80
98
|
}
|
|
81
99
|
}
|
|
82
100
|
|
|
83
|
-
function cliTool(buildArgs) {
|
|
101
|
+
function cliTool(buildArgs, { cwdParam = false } = {}) {
|
|
84
102
|
return async (input) => {
|
|
85
103
|
try {
|
|
86
|
-
|
|
104
|
+
const params = input || {};
|
|
105
|
+
const opts = {};
|
|
106
|
+
if (cwdParam) {
|
|
107
|
+
// Accept cwd, directory, or dir as the working-directory override.
|
|
108
|
+
opts.cwd = params.cwd ?? params.directory ?? params.dir;
|
|
109
|
+
}
|
|
110
|
+
return ok(await runCloudgrid(buildArgs(params), opts));
|
|
87
111
|
} catch (err) {
|
|
88
112
|
return fail(err.message);
|
|
89
113
|
}
|
|
@@ -774,6 +798,7 @@ export function registerTools(server, ctx) {
|
|
|
774
798
|
description: z.string().optional().describe("Initial one-line description."),
|
|
775
799
|
dir: z.string().optional().describe("Target directory. Defaults to ./<name>."),
|
|
776
800
|
org: z.string().optional().describe("Override the active org for this init."),
|
|
801
|
+
cwd: z.string().optional().describe("Working directory. The CLI runs in this directory. Defaults to the MCP server's working directory."),
|
|
777
802
|
},
|
|
778
803
|
{ readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
779
804
|
cliTool(({ kind, name, type, description, dir, org }) => {
|
|
@@ -783,7 +808,7 @@ export function registerTools(server, ctx) {
|
|
|
783
808
|
if (dir) args.push("--dir", dir);
|
|
784
809
|
if (org) args.push("--org", org);
|
|
785
810
|
return args;
|
|
786
|
-
}),
|
|
811
|
+
}, { cwdParam: true }),
|
|
787
812
|
);
|
|
788
813
|
|
|
789
814
|
server.tool(
|
|
@@ -793,6 +818,7 @@ export function registerTools(server, ctx) {
|
|
|
793
818
|
target: z.string().optional().describe("Path or URL. Omit to deploy the entity linked to the current directory."),
|
|
794
819
|
org: z.string().optional().describe("Pick or override the org."),
|
|
795
820
|
no_deploy: z.boolean().optional().describe("Register the entity but do not build or deploy."),
|
|
821
|
+
cwd: z.string().optional().describe("Working directory. The CLI runs in this directory. Defaults to the MCP server's working directory."),
|
|
796
822
|
},
|
|
797
823
|
{ readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
798
824
|
cliTool(({ target, org, no_deploy }) => {
|
|
@@ -800,9 +826,9 @@ export function registerTools(server, ctx) {
|
|
|
800
826
|
if (target) args.push(target);
|
|
801
827
|
if (org) args.push("--org", org);
|
|
802
828
|
if (no_deploy) args.push("--no-deploy");
|
|
803
|
-
args.push("--no-clipboard", "--no-notify");
|
|
829
|
+
args.push("--auto", "--no-clipboard", "--no-notify");
|
|
804
830
|
return args;
|
|
805
|
-
}),
|
|
831
|
+
}, { cwdParam: true }),
|
|
806
832
|
);
|
|
807
833
|
|
|
808
834
|
server.tool(
|
|
@@ -958,7 +984,7 @@ export function registerTools(server, ctx) {
|
|
|
958
984
|
confirm: z.literal(true).describe("Must be true to proceed."),
|
|
959
985
|
},
|
|
960
986
|
{ readOnlyHint: false, destructiveHint: true, openWorldHint: true },
|
|
961
|
-
cliTool(({ name }) => ["unplug", name]),
|
|
987
|
+
cliTool(({ name }) => ["unplug", name, "--skip-confirm"]),
|
|
962
988
|
);
|
|
963
989
|
|
|
964
990
|
server.tool(
|
|
@@ -969,7 +995,7 @@ export function registerTools(server, ctx) {
|
|
|
969
995
|
confirm: z.literal(true).describe("Must be true to proceed."),
|
|
970
996
|
},
|
|
971
997
|
{ readOnlyHint: false, destructiveHint: true, openWorldHint: true },
|
|
972
|
-
cliTool(({ name }) => ["delete", name]),
|
|
998
|
+
cliTool(({ name }) => ["delete", name, "--yes"]),
|
|
973
999
|
);
|
|
974
1000
|
|
|
975
1001
|
server.tool(
|
|
@@ -1007,19 +1033,20 @@ export function registerTools(server, ctx) {
|
|
|
1007
1033
|
name: z.string().describe("Entity slug."),
|
|
1008
1034
|
key: z.string().optional().describe("Variable name. Required for get and set."),
|
|
1009
1035
|
value: z.string().optional().describe("Variable value. Required for set."),
|
|
1036
|
+
cwd: z.string().optional().describe("Working directory. The CLI runs in this directory. Defaults to the MCP server's working directory."),
|
|
1010
1037
|
},
|
|
1011
1038
|
{ readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
1012
1039
|
cliTool(({ action, name, key, value }) => {
|
|
1013
1040
|
if (action === "set") {
|
|
1014
1041
|
if (!key || value === undefined) throw new Error("key and value are required for set");
|
|
1015
|
-
return ["env", "set", name, key
|
|
1042
|
+
return ["env", "set", name, `${key}=${value}`];
|
|
1016
1043
|
}
|
|
1017
1044
|
if (action === "get") {
|
|
1018
1045
|
if (!key) throw new Error("key is required for get");
|
|
1019
|
-
return ["env", "get",
|
|
1046
|
+
return ["env", "get", key, name];
|
|
1020
1047
|
}
|
|
1021
1048
|
return ["env", "list", name];
|
|
1022
|
-
}),
|
|
1049
|
+
}, { cwdParam: true }),
|
|
1023
1050
|
);
|
|
1024
1051
|
|
|
1025
1052
|
server.tool(
|
|
@@ -1030,6 +1057,7 @@ export function registerTools(server, ctx) {
|
|
|
1030
1057
|
name: z.string().describe("Entity slug."),
|
|
1031
1058
|
key: z.string().optional().describe("Secret name. Required for set."),
|
|
1032
1059
|
value: z.string().optional().describe("Secret value. Required for set."),
|
|
1060
|
+
cwd: z.string().optional().describe("Working directory. The CLI runs in this directory. Defaults to the MCP server's working directory."),
|
|
1033
1061
|
},
|
|
1034
1062
|
{ readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
1035
1063
|
cliTool(({ action, name, key, value }) => {
|
|
@@ -1038,7 +1066,7 @@ export function registerTools(server, ctx) {
|
|
|
1038
1066
|
return ["secrets", "set", name, key, value];
|
|
1039
1067
|
}
|
|
1040
1068
|
return ["secrets", "list", name];
|
|
1041
|
-
}),
|
|
1069
|
+
}, { cwdParam: true }),
|
|
1042
1070
|
);
|
|
1043
1071
|
|
|
1044
1072
|
server.tool(
|
|
@@ -1047,6 +1075,7 @@ export function registerTools(server, ctx) {
|
|
|
1047
1075
|
{
|
|
1048
1076
|
template: z.string().optional().describe("Template name."),
|
|
1049
1077
|
dir: z.string().optional().describe("Target directory."),
|
|
1078
|
+
cwd: z.string().optional().describe("Working directory. The CLI runs in this directory. Defaults to the MCP server's working directory."),
|
|
1050
1079
|
},
|
|
1051
1080
|
{ readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
1052
1081
|
cliTool(({ template, dir }) => {
|
|
@@ -1054,7 +1083,7 @@ export function registerTools(server, ctx) {
|
|
|
1054
1083
|
if (template) args.push(template);
|
|
1055
1084
|
if (dir) args.push("--dir", dir);
|
|
1056
1085
|
return args;
|
|
1057
|
-
}),
|
|
1086
|
+
}, { cwdParam: true }),
|
|
1058
1087
|
);
|
|
1059
1088
|
|
|
1060
1089
|
server.tool(
|