@groundfloorcloud/mcp 0.1.5 → 0.1.6
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 +3 -1
- package/dist/index.js +160 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,7 +69,9 @@ The `command` must be your Node (from `which node`), not `npx` and not Cursor’
|
|
|
69
69
|
|------|------|
|
|
70
70
|
| `whoami` / `workspace_context` | Session + live workspace snapshot |
|
|
71
71
|
| `workspaces_list` | List; switch with `gf workspaces use` |
|
|
72
|
-
| `coderunner_list` / `_get_status` / `_get_logs` | Inspect workloads |
|
|
72
|
+
| `coderunner_list` / `_get_status` / `_get_logs` / `_process_log` | Inspect workloads (Process Log does not need a job_id) |
|
|
73
|
+
| `environments_list` | List workspace environments |
|
|
74
|
+
| `coderunner_cancel_deployment` | Delete current (or given) deployment |
|
|
73
75
|
| `apps_list` / `apps_get` | Inspect product Apps |
|
|
74
76
|
| `secrets_list` / `files_list` / `domains_list` / `dataplane_status` | Inspect (no secrets values) |
|
|
75
77
|
| `docs_list` / `docs_get` | Product docs (`coderunner`, `coderunner-runtime`, and `shell` are embedded how-tos) |
|
package/dist/index.js
CHANGED
|
@@ -191,6 +191,16 @@ async function cpGet(apiUrl, path2) {
|
|
|
191
191
|
}
|
|
192
192
|
return await res.json();
|
|
193
193
|
}
|
|
194
|
+
async function cpDelete(apiUrl, path2) {
|
|
195
|
+
const token = await getValidAccessToken();
|
|
196
|
+
const res = await fetch(`${apiUrl}${path2}`, {
|
|
197
|
+
method: "DELETE",
|
|
198
|
+
headers: { Authorization: `Bearer ${token}`, Accept: "application/json" }
|
|
199
|
+
});
|
|
200
|
+
if (!res.ok) {
|
|
201
|
+
throw new CpError(res.status, await parseError(res));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
194
204
|
function queryString(params) {
|
|
195
205
|
const u = new URLSearchParams();
|
|
196
206
|
for (const [key, value] of Object.entries(params)) {
|
|
@@ -229,6 +239,22 @@ async function getDeployment(apiUrl, workspaceId, coderunnerId) {
|
|
|
229
239
|
}
|
|
230
240
|
return await res.json();
|
|
231
241
|
}
|
|
242
|
+
function deleteCoderunnerDeployment(apiUrl, workspaceId, coderunnerId, deploymentId) {
|
|
243
|
+
return cpDelete(
|
|
244
|
+
apiUrl,
|
|
245
|
+
`/v1/workspaces/${encodeURIComponent(
|
|
246
|
+
workspaceId
|
|
247
|
+
)}/coderunners/${encodeURIComponent(
|
|
248
|
+
coderunnerId
|
|
249
|
+
)}/deployments/${encodeURIComponent(deploymentId)}`
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
function listWorkspaceEnvironments(apiUrl, workspaceId) {
|
|
253
|
+
return cpGet(
|
|
254
|
+
apiUrl,
|
|
255
|
+
`/v1/workspaces/${encodeURIComponent(workspaceId)}/environments`
|
|
256
|
+
);
|
|
257
|
+
}
|
|
232
258
|
function getCoderunnerStatus(apiUrl, workspaceId, coderunnerId) {
|
|
233
259
|
return cpGet(
|
|
234
260
|
apiUrl,
|
|
@@ -247,6 +273,18 @@ function getCoderunnerLogs(apiUrl, workspaceId, coderunnerId, jobId) {
|
|
|
247
273
|
)}/logs/${encodeURIComponent(jobId)}`
|
|
248
274
|
);
|
|
249
275
|
}
|
|
276
|
+
function getProcessLogs(apiUrl, workspaceId, query = {}) {
|
|
277
|
+
const params = new URLSearchParams();
|
|
278
|
+
for (const [key, value] of Object.entries(query)) {
|
|
279
|
+
if (value == null || value === "") continue;
|
|
280
|
+
params.set(key, String(value));
|
|
281
|
+
}
|
|
282
|
+
const qs = params.toString();
|
|
283
|
+
return cpGet(
|
|
284
|
+
apiUrl,
|
|
285
|
+
`/v1/workspaces/${encodeURIComponent(workspaceId)}/logs${qs ? `?${qs}` : ""}`
|
|
286
|
+
);
|
|
287
|
+
}
|
|
250
288
|
function domainsBase(workspaceId, coderunnerId) {
|
|
251
289
|
return `/v1/workspaces/${encodeURIComponent(
|
|
252
290
|
workspaceId
|
|
@@ -429,7 +467,9 @@ Bind \`0.0.0.0\` and \`PORT\` (default 8080), for example
|
|
|
429
467
|
## Jobs and schedules
|
|
430
468
|
|
|
431
469
|
Same package/start rules. The process may exit 0 when finished; it does not
|
|
432
|
-
need a public URL. Schedules have **no** Deployment URL.
|
|
470
|
+
need a public URL. Schedules have **no** Deployment URL. Set cron with
|
|
471
|
+
\`gf deploy --workload-type schedule --schedule "<cron>"\` or
|
|
472
|
+
\`groundfloor.json\` \`"schedule"\`.
|
|
433
473
|
|
|
434
474
|
## What \`gf deploy\` checks
|
|
435
475
|
|
|
@@ -506,8 +546,9 @@ Pick **one** type per coderunner. Changing type later means a new coderunner.
|
|
|
506
546
|
|
|
507
547
|
### Schedule
|
|
508
548
|
|
|
509
|
-
- Same as job, plus a cron expression at
|
|
510
|
-
\`
|
|
549
|
+
- Same as job, plus a cron expression at deploy:
|
|
550
|
+
\`gf deploy --workload-type schedule --schedule "<cron>"\`
|
|
551
|
+
(or \`groundfloor.json\` \`"schedule"\`).
|
|
511
552
|
- No public invoke URL. Debug with Process Log, not curl.
|
|
512
553
|
|
|
513
554
|
### Service (Deployment)
|
|
@@ -545,7 +586,7 @@ CMD ["npm", "start"]
|
|
|
545
586
|
\`gf secrets\` / deploy \`-e\`, never in the archive.
|
|
546
587
|
- Zip **contents** at root, not a wrapping folder.
|
|
547
588
|
- Optional \`groundfloor.json\`: \`name\`, \`runtime\`, \`workloadType\`,
|
|
548
|
-
\`cpu\`, \`memory\`, \`env
|
|
589
|
+
\`cpu\`, \`memory\`, \`env\`, \`schedule\` (cron, schedule workloads only).
|
|
549
590
|
|
|
550
591
|
## Local development with live workspace data
|
|
551
592
|
|
|
@@ -747,7 +788,7 @@ function suggestCli(intent, args) {
|
|
|
747
788
|
case "deploy":
|
|
748
789
|
return {
|
|
749
790
|
command: name ? `gf deploy -n ${name}${ws}` : `gf deploy${ws}`,
|
|
750
|
-
why:
|
|
791
|
+
why: 'Package the current (or --path) folder and deploy as a Coderunner. Workspace Authentication (groundfloor/external) must already be active. workloadType function|job|schedule|service (service = Deployment; requires a Dockerfile). Schedules need --schedule "<cron>" or groundfloor.json schedule. Node bootstrap: scripts.start, listen PORT||8080, bind 0.0.0.0. Do not create an App for this.',
|
|
751
792
|
docs: "https://docs.groundfloor.cloud/docs/customer-portal/coderunner"
|
|
752
793
|
};
|
|
753
794
|
case "run":
|
|
@@ -782,6 +823,18 @@ function suggestCli(intent, args) {
|
|
|
782
823
|
why: "Ship a Shell federated App. Always init the kit first. npm run release (not zip dist/, not a lone remoteEntry.js). Do not gf deploy. Do not invent App.tsx.",
|
|
783
824
|
docs: "https://docs.groundfloor.cloud/docs/integrations/shell"
|
|
784
825
|
};
|
|
826
|
+
case "environments":
|
|
827
|
+
return {
|
|
828
|
+
command: `gf environments ls${ws}`,
|
|
829
|
+
why: "List workspace environments (id, name, status) for secrets and deploy targeting.",
|
|
830
|
+
docs: "https://docs.groundfloor.cloud/docs/customer-portal/developers"
|
|
831
|
+
};
|
|
832
|
+
case "cancel_deployment":
|
|
833
|
+
return {
|
|
834
|
+
command: name ? `gf coderunner cancel-deployment -c ${name}${ws}` : `gf coderunner cancel-deployment -c <id-or-slug>${ws}`,
|
|
835
|
+
why: "Delete the current deployment (or --deployment-id). Use this for a deploy stuck in deploying.",
|
|
836
|
+
docs: "https://docs.groundfloor.cloud/docs/customer-portal/coderunner"
|
|
837
|
+
};
|
|
785
838
|
case "secrets":
|
|
786
839
|
return {
|
|
787
840
|
command: `gf secrets ls${ws}`,
|
|
@@ -797,7 +850,7 @@ function suggestCli(intent, args) {
|
|
|
797
850
|
default:
|
|
798
851
|
return {
|
|
799
852
|
command: "gf --help",
|
|
800
|
-
why: `Unknown intent "${intent}". Use login | switch_workspace | deploy | run | status | init_app | publish_app | secrets | dataplane.`,
|
|
853
|
+
why: `Unknown intent "${intent}". Use login | switch_workspace | deploy | run | status | logs | environments | cancel_deployment | init_app | publish_app | secrets | dataplane.`,
|
|
801
854
|
docs: "https://docs.groundfloor.cloud/docs/customer-portal/developers"
|
|
802
855
|
};
|
|
803
856
|
}
|
|
@@ -841,7 +894,7 @@ async function resolveCoderunnerId(apiUrl, workspaceId, idOrSlug) {
|
|
|
841
894
|
}
|
|
842
895
|
var server = new McpServer({
|
|
843
896
|
name: "groundfloor",
|
|
844
|
-
version: "0.1.
|
|
897
|
+
version: "0.1.6"
|
|
845
898
|
});
|
|
846
899
|
server.tool(
|
|
847
900
|
"whoami",
|
|
@@ -906,7 +959,7 @@ server.tool(
|
|
|
906
959
|
types: {
|
|
907
960
|
function: "HTTP handler on PORT/8080 bound to 0.0.0.0. Invoke with gf coderunner run or the Deployment URL. Node requires package.json scripts.start.",
|
|
908
961
|
job: "Run-to-completion worker. Deploy, then gf coderunner run.",
|
|
909
|
-
schedule:
|
|
962
|
+
schedule: 'Cron job. No public Deployment URL. Set cron with gf deploy --workload-type schedule --schedule "<cron>" (or groundfloor.json schedule).',
|
|
910
963
|
service: "Long-running Deployment (same type as service). Dockerfile at ZIP root is required. Listen on 8080 / 0.0.0.0."
|
|
911
964
|
},
|
|
912
965
|
node: "No Dockerfile \u2192 platform injects node:18-alpine CMD npm start EXPOSE 8080. Require scripts.start; listen on PORT||8080; bind 0.0.0.0. gf deploy fails fast if scripts.start is missing.",
|
|
@@ -922,6 +975,8 @@ server.tool(
|
|
|
922
975
|
switch_workspace: suggestCli("switch_workspace"),
|
|
923
976
|
run: suggestCli("run"),
|
|
924
977
|
logs: suggestCli("logs"),
|
|
978
|
+
environments: suggestCli("environments"),
|
|
979
|
+
cancel_deployment: suggestCli("cancel_deployment"),
|
|
925
980
|
init_app: suggestCli("init_app"),
|
|
926
981
|
publish_app: suggestCli("publish_app")
|
|
927
982
|
},
|
|
@@ -997,9 +1052,102 @@ server.tool(
|
|
|
997
1052
|
}
|
|
998
1053
|
}
|
|
999
1054
|
);
|
|
1055
|
+
server.tool(
|
|
1056
|
+
"coderunner_process_log",
|
|
1057
|
+
"Process Log (deploy/build stdout/stderr) by coderunner id. Prefer this over coderunner_get_logs when there is no job_id.",
|
|
1058
|
+
{
|
|
1059
|
+
workspace_id: wsId,
|
|
1060
|
+
coderunner_id: z.string().min(1).describe("Coderunner id or slug"),
|
|
1061
|
+
limit: z.number().int().positive().optional(),
|
|
1062
|
+
since_seconds: z.number().int().min(10).optional(),
|
|
1063
|
+
search: z.string().optional(),
|
|
1064
|
+
deployment_id: z.string().optional()
|
|
1065
|
+
},
|
|
1066
|
+
async (args) => {
|
|
1067
|
+
try {
|
|
1068
|
+
const c = await cfg(args.workspace_id);
|
|
1069
|
+
const id = await resolveCoderunnerId(
|
|
1070
|
+
c.apiUrl,
|
|
1071
|
+
c.workspaceId,
|
|
1072
|
+
args.coderunner_id
|
|
1073
|
+
);
|
|
1074
|
+
return text(
|
|
1075
|
+
await getProcessLogs(c.apiUrl, c.workspaceId, {
|
|
1076
|
+
runner_id: id,
|
|
1077
|
+
deployment_id: args.deployment_id,
|
|
1078
|
+
limit: args.limit ?? 50,
|
|
1079
|
+
since_seconds: args.since_seconds ?? 3600,
|
|
1080
|
+
search: args.search
|
|
1081
|
+
})
|
|
1082
|
+
);
|
|
1083
|
+
} catch (e) {
|
|
1084
|
+
return errText(e);
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
);
|
|
1088
|
+
server.tool(
|
|
1089
|
+
"environments_list",
|
|
1090
|
+
"List environments in the workspace (id, name, status).",
|
|
1091
|
+
{ workspace_id: wsId },
|
|
1092
|
+
async ({ workspace_id }) => {
|
|
1093
|
+
try {
|
|
1094
|
+
const c = await cfg(workspace_id);
|
|
1095
|
+
const environments = await listWorkspaceEnvironments(
|
|
1096
|
+
c.apiUrl,
|
|
1097
|
+
c.workspaceId
|
|
1098
|
+
);
|
|
1099
|
+
return text({ environments, count: environments.length });
|
|
1100
|
+
} catch (e) {
|
|
1101
|
+
return errText(e);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
);
|
|
1105
|
+
server.tool(
|
|
1106
|
+
"coderunner_cancel_deployment",
|
|
1107
|
+
"Delete a coderunner deployment (current deployment if deployment_id is omitted). Same as `gf coderunner cancel-deployment`.",
|
|
1108
|
+
{
|
|
1109
|
+
workspace_id: wsId,
|
|
1110
|
+
coderunner_id: z.string().min(1).describe("Coderunner id or slug"),
|
|
1111
|
+
deployment_id: z.string().optional().describe("Deployment id; defaults to the current deployment")
|
|
1112
|
+
},
|
|
1113
|
+
async (args) => {
|
|
1114
|
+
try {
|
|
1115
|
+
const c = await cfg(args.workspace_id);
|
|
1116
|
+
const id = await resolveCoderunnerId(
|
|
1117
|
+
c.apiUrl,
|
|
1118
|
+
c.workspaceId,
|
|
1119
|
+
args.coderunner_id
|
|
1120
|
+
);
|
|
1121
|
+
let deploymentId = args.deployment_id?.trim();
|
|
1122
|
+
if (!deploymentId) {
|
|
1123
|
+
const current = await getDeployment(c.apiUrl, c.workspaceId, id);
|
|
1124
|
+
deploymentId = current?.id?.trim();
|
|
1125
|
+
}
|
|
1126
|
+
if (!deploymentId) {
|
|
1127
|
+
throw new Error(
|
|
1128
|
+
`No current deployment for coderunner ${id}. Pass deployment_id.`
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
await deleteCoderunnerDeployment(
|
|
1132
|
+
c.apiUrl,
|
|
1133
|
+
c.workspaceId,
|
|
1134
|
+
id,
|
|
1135
|
+
deploymentId
|
|
1136
|
+
);
|
|
1137
|
+
return text({
|
|
1138
|
+
coderunner_id: id,
|
|
1139
|
+
deployment_id: deploymentId,
|
|
1140
|
+
deleted: true,
|
|
1141
|
+
next: suggestCli("logs", { coderunner: id })
|
|
1142
|
+
});
|
|
1143
|
+
} catch (e) {
|
|
1144
|
+
return errText(e);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
);
|
|
1000
1148
|
server.tool(
|
|
1001
1149
|
"coderunner_get_logs",
|
|
1002
|
-
"Job-run logs from a previous `gf coderunner run` (needs job_id). For deploy/build stdout use suggest_cli intent logs (`gf coderunner logs`).",
|
|
1150
|
+
"Job-run logs from a previous `gf coderunner run` (needs job_id). For deploy/build stdout use coderunner_process_log or suggest_cli intent logs (`gf coderunner logs`).",
|
|
1003
1151
|
{
|
|
1004
1152
|
workspace_id: wsId,
|
|
1005
1153
|
coderunner_id: z.string().min(1),
|
|
@@ -1160,13 +1308,15 @@ server.tool(
|
|
|
1160
1308
|
"run",
|
|
1161
1309
|
"status",
|
|
1162
1310
|
"logs",
|
|
1311
|
+
"environments",
|
|
1312
|
+
"cancel_deployment",
|
|
1163
1313
|
"init_app",
|
|
1164
1314
|
"publish_app",
|
|
1165
1315
|
"secrets",
|
|
1166
1316
|
"dataplane"
|
|
1167
1317
|
]),
|
|
1168
1318
|
workspace: z.string().optional(),
|
|
1169
|
-
name: z.string().optional().describe("Coderunner name/id for deploy/run/status/logs"),
|
|
1319
|
+
name: z.string().optional().describe("Coderunner name/id for deploy/run/status/logs/cancel_deployment"),
|
|
1170
1320
|
slug: z.string().optional().describe("Portal app slug for init_app / publish_app"),
|
|
1171
1321
|
cell: z.enum(["production", "stage", "dev"]).optional()
|
|
1172
1322
|
},
|