@groundfloorcloud/mcp 0.1.7 → 0.1.8
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 +4 -4
- package/dist/index.js +88 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,8 +74,8 @@ The `command` must be your Node (from `which node`), not `npx` and not Cursor’
|
|
|
74
74
|
| `coderunner_cancel_deployment` | Delete current (or given) deployment |
|
|
75
75
|
| `apps_list` / `apps_get` | Inspect product Apps |
|
|
76
76
|
| `secrets_list` / `files_list` / `domains_list` / `dataplane_status` | Inspect (no secrets values) |
|
|
77
|
-
| `docs_list` / `docs_get` | Product docs (`coderunner`, `shell`, `design-standard`, `css-and-styling`, `databases` are embedded
|
|
78
|
-
| `suggest_cli` | Command to run: login, deploy, init_app, publish_app, … |
|
|
77
|
+
| `docs_list` / `docs_get` | Product docs (`coderunner`, `shell`, `design-standard`, `css-and-styling`, `databases` are embedded; `access` and `m2m` are live pages) |
|
|
78
|
+
| `suggest_cli` | Command to run: login, deploy, init_app, publish_app, m2m_token, … |
|
|
79
79
|
|
|
80
80
|
Never create `app_kind=coderunner`. Deploy with `gf deploy`.
|
|
81
81
|
|
|
@@ -91,10 +91,10 @@ is ready through Dataplane; Postgres is what you can deploy today.
|
|
|
91
91
|
`coderunner-overview`). That page covers:
|
|
92
92
|
|
|
93
93
|
- Types: `function`, `job`, `schedule`, `service` (**also called Deployment**)
|
|
94
|
-
-
|
|
94
|
+
- App authentication is optional (end-user login); not required to create a coderunner
|
|
95
95
|
- **Dockerfile is required** for `service` / Deployment
|
|
96
96
|
- Runtime contract: Node `scripts.start`, listen on `PORT`/8080, bind `0.0.0.0` (`docs_get` id `coderunner-runtime`)
|
|
97
|
-
- Local development against live vault/files/secrets (`gf env`
|
|
97
|
+
- Local development against live vault/files/secrets (`gf env`; as the workload use `gf m2m token`, not `gf token`)
|
|
98
98
|
|
|
99
99
|
`workspace_context` includes a `coderunner_howto` summary so agents see this
|
|
100
100
|
without an extra fetch.
|
package/dist/index.js
CHANGED
|
@@ -169,11 +169,31 @@ var CpError = class extends Error {
|
|
|
169
169
|
}
|
|
170
170
|
status;
|
|
171
171
|
};
|
|
172
|
+
function formatCpErrorDetail(detail, fallback) {
|
|
173
|
+
if (typeof detail === "string" && detail.trim()) return detail.trim();
|
|
174
|
+
if (detail && typeof detail === "object") {
|
|
175
|
+
const obj = detail;
|
|
176
|
+
if (typeof obj.message === "string" && obj.message.trim()) {
|
|
177
|
+
return obj.message.trim();
|
|
178
|
+
}
|
|
179
|
+
if (typeof obj.detail === "string" && obj.detail.trim()) {
|
|
180
|
+
return obj.detail.trim();
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
return JSON.stringify(detail);
|
|
184
|
+
} catch {
|
|
185
|
+
return fallback;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return fallback;
|
|
189
|
+
}
|
|
172
190
|
async function parseError(res) {
|
|
173
191
|
let detail = res.statusText;
|
|
174
192
|
try {
|
|
175
193
|
const body = await res.json();
|
|
176
|
-
if (body?.detail
|
|
194
|
+
if (body?.detail !== void 0) {
|
|
195
|
+
detail = formatCpErrorDetail(body.detail, res.statusText);
|
|
196
|
+
}
|
|
177
197
|
} catch {
|
|
178
198
|
}
|
|
179
199
|
return `${res.status} ${detail}`;
|
|
@@ -504,13 +524,11 @@ Also \`docs_get\` id \`coderunner-runtime\`.
|
|
|
504
524
|
|
|
505
525
|
## Prerequisites (do these before create/deploy)
|
|
506
526
|
|
|
507
|
-
1.
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
2. \`gf login\` (\`--stage\` / \`--dev\` as needed) and \`gf workspaces use <uuid>\`.
|
|
513
|
-
3. Dataplane for vault/files/secrets: \`gf dataplane provision\` if those APIs
|
|
527
|
+
1. \`gf login\` (\`--stage\` / \`--dev\` as needed) and \`gf workspaces use <uuid>\`.
|
|
528
|
+
Team **write** can create Coderunners without App authentication. Site auth
|
|
529
|
+
(Groundfloor/external) is only for end-user login. Mode \`none\` mints
|
|
530
|
+
management JWTs against Portal JWKS (\`GET /v1/public/jwks.json\`).
|
|
531
|
+
2. Dataplane for vault/files: \`gf dataplane provision\` if those APIs
|
|
514
532
|
are needed (local live data or the deployed workload).
|
|
515
533
|
|
|
516
534
|
## Workload types
|
|
@@ -613,21 +631,41 @@ curl -sS -X POST http://127.0.0.1:8080/ -H 'Content-Type: application/json' \\
|
|
|
613
631
|
|
|
614
632
|
Live vault / files / secrets from the laptop:
|
|
615
633
|
|
|
634
|
+
\`gf token\` is a **builder** credential. Use it for operator Vault. To call
|
|
635
|
+
Vault and Files as a Coderunner does, use an M2M client and \`gf m2m token\`.
|
|
636
|
+
|
|
616
637
|
\`\`\`bash
|
|
638
|
+
# Builder token:
|
|
617
639
|
curl -sS -H "Authorization: Bearer $(gf token)" \\
|
|
618
640
|
"$CONTROLPLANE_URL/v1/workspaces/$GROUNDFLOOR_WORKSPACE_ID/vault/collections"
|
|
641
|
+
|
|
642
|
+
# M2M (same class as an attached Coderunner):
|
|
643
|
+
curl -sS -H "Authorization: Bearer $(gf m2m token)" \\
|
|
644
|
+
"$CONTROLPLANE_URL/v1/workspaces/$GROUNDFLOOR_WORKSPACE_ID/vault/collections"
|
|
645
|
+
curl -sS -H "Authorization: Bearer $(gf m2m token)" \\
|
|
646
|
+
"$CONTROLPLANE_URL/v1/workspaces/$GROUNDFLOOR_WORKSPACE_ID/files"
|
|
619
647
|
\`\`\`
|
|
620
648
|
|
|
621
|
-
In app code, use \`CONTROLPLANE_URL\` + Bearer
|
|
622
|
-
|
|
623
|
-
\`
|
|
649
|
+
In app code, use \`CONTROLPLANE_URL\` + Bearer from
|
|
650
|
+
\`POST \u2026/m2m/token\` (\`gf m2m token\` locally; injected
|
|
651
|
+
\`GROUNDFLOOR_M2M_CLIENT_ID\` / \`GROUNDFLOOR_M2M_CLIENT_SECRET\` after
|
|
652
|
+
\`gf deploy\`). Never put \`DATAPLANE_SERVICE_API_KEY\` in a browser bundle
|
|
653
|
+
or customer env.
|
|
624
654
|
|
|
625
655
|
When the handler looks right locally, \`gf deploy\` the same tree.
|
|
626
656
|
|
|
657
|
+
## M2M tokens (Vault and Files)
|
|
658
|
+
|
|
659
|
+
New Coderunners cannot call Vault or Files until an M2M client is attached
|
|
660
|
+
and the workload is redeployed. Create the client in Portal **Administer \u2192
|
|
661
|
+
M2M tokens**, attach it on the Coderunner card, then deploy. v1 M2M is Team
|
|
662
|
+
Writer on that workspace (full Vault skip-ACL + Files). Grant site users on
|
|
663
|
+
**Administer \u2192 Access**. Never inject a Dataplane key.
|
|
664
|
+
|
|
627
665
|
## Agent actions
|
|
628
666
|
|
|
629
667
|
Inspect: \`workspace_context\`, \`docs_get\` id \`coderunner\` or \`coderunner-runtime\`, \`suggest_cli\`.
|
|
630
|
-
Act: \`gf deploy\`, \`gf coderunner run|status\`. MCP does not deploy.
|
|
668
|
+
Act: \`gf deploy\`, \`gf coderunner run|status\`, \`gf m2m token\`. MCP does not deploy.
|
|
631
669
|
`.trim();
|
|
632
670
|
|
|
633
671
|
// src/css-and-styling-guide.ts
|
|
@@ -771,8 +809,9 @@ gf apps publish --path release.zip
|
|
|
771
809
|
\`\`\`
|
|
772
810
|
|
|
773
811
|
\`npm run release\` packs **all** of dist/assets (remoteEntry.js + hashed
|
|
774
|
-
\`__federation_*.js\` + CSS) at the zip root
|
|
775
|
-
|
|
812
|
+
\`__federation_*.js\` + CSS) at the zip root and rewrites \`./assets/\` imports
|
|
813
|
+
in remoteEntry.js. Do not zip \`dist/\`. Do not upload a lone \`remoteEntry.js\`.
|
|
814
|
+
\`gf apps publish\` rejects incomplete zips.
|
|
776
815
|
|
|
777
816
|
Production builds use Vite \`base: './'\` so imported images resolve next to
|
|
778
817
|
remoteEntry.js. Header logos: manifest \`theme.logoUrl\` (absolute https).
|
|
@@ -796,19 +835,19 @@ var DOC_CATALOG = [
|
|
|
796
835
|
id: "agents",
|
|
797
836
|
title: "Deploy with agents",
|
|
798
837
|
path: "/docs/customer-portal/agents",
|
|
799
|
-
summary: "How agents should deploy Coderunner workloads and init/publish Shell apps with gf / MCP.
|
|
838
|
+
summary: "How agents should deploy Coderunner workloads and init/publish Shell apps with gf / MCP. App authentication is optional (end-user login). Service (Deployment) requires a Dockerfile. Shell apps: gf apps init, never invent App.tsx."
|
|
800
839
|
},
|
|
801
840
|
{
|
|
802
841
|
id: "developers",
|
|
803
842
|
title: "Developers (gf CLI)",
|
|
804
843
|
path: "/docs/customer-portal/developers",
|
|
805
|
-
summary: "gf login, workspaces, deploy, secrets, files, apps. Coderunner types: function, job, schedule, service (also called Deployment)."
|
|
844
|
+
summary: "gf login, workspaces, deploy, secrets, files, apps, gf m2m token. Coderunner types: function, job, schedule, service (also called Deployment). App authentication optional."
|
|
806
845
|
},
|
|
807
846
|
{
|
|
808
847
|
id: "coderunner",
|
|
809
848
|
title: "Coderunner",
|
|
810
849
|
path: "/docs/customer-portal/coderunner",
|
|
811
|
-
summary: "Workload types (function, job, schedule, service/Deployment), runtime contract (scripts.start, 0.0.0.0:8080), Dockerfile for services,
|
|
850
|
+
summary: "Workload types (function, job, schedule, service/Deployment), runtime contract (scripts.start, 0.0.0.0:8080), Dockerfile for services, Coderunner identities for Vault, App authentication optional, local live data, gf deploy.",
|
|
812
851
|
embedded: CODERUNNER_GUIDE
|
|
813
852
|
},
|
|
814
853
|
{
|
|
@@ -822,14 +861,26 @@ var DOC_CATALOG = [
|
|
|
822
861
|
id: "coderunner-overview",
|
|
823
862
|
title: "Coderunner overview",
|
|
824
863
|
path: "/docs/integrations/coderunner/overview",
|
|
825
|
-
summary: "Architecture and lifecycle. Prefer docs_get id coderunner for type usage, Dockerfile, and
|
|
864
|
+
summary: "Architecture and lifecycle. Prefer docs_get id coderunner for type usage, Dockerfile, and create prerequisites.",
|
|
826
865
|
embedded: CODERUNNER_GUIDE
|
|
827
866
|
},
|
|
828
867
|
{
|
|
829
868
|
id: "authentication",
|
|
830
869
|
title: "Workspace Authentication",
|
|
831
870
|
path: "/docs/customer-portal/authentication",
|
|
832
|
-
summary: "Workspace site auth (Groundfloor or external)
|
|
871
|
+
summary: "Workspace site auth (Groundfloor or external) is optional end-user login. Leaving Groundfloor keeps the realm (disabled) until Delete Groundfloor login. Separate from portal Team. Not required to create Apps or Coderunners."
|
|
872
|
+
},
|
|
873
|
+
{
|
|
874
|
+
id: "access",
|
|
875
|
+
title: "Access",
|
|
876
|
+
path: "/docs/customer-portal/access",
|
|
877
|
+
summary: "Grant site roles Data Vault collections, workspace-wide Files, and Apps launch. Admin is implicit. M2M is not an Access subject. Team membership is unchanged."
|
|
878
|
+
},
|
|
879
|
+
{
|
|
880
|
+
id: "m2m",
|
|
881
|
+
title: "M2M tokens",
|
|
882
|
+
path: "/docs/customer-portal/m2m-tokens",
|
|
883
|
+
summary: "Confidential client secret \u2192 short Control Plane JWT (typ=m2m). Attach on Coderunner or gf m2m token. Never DATAPLANE_SERVICE_API_KEY. v1 is Team Writer, no collection ACL."
|
|
833
884
|
},
|
|
834
885
|
{
|
|
835
886
|
id: "api-authentication",
|
|
@@ -934,7 +985,7 @@ function suggestCli(intent, args) {
|
|
|
934
985
|
case "deploy":
|
|
935
986
|
return {
|
|
936
987
|
command: name ? `gf deploy -n ${name}${ws}` : `gf deploy${ws}`,
|
|
937
|
-
why: 'Package the current (or --path) folder and deploy as a Coderunner.
|
|
988
|
+
why: 'Package the current (or --path) folder and deploy as a Coderunner. App authentication is optional (end-user login only). 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.',
|
|
938
989
|
docs: "https://docs.groundfloor.cloud/docs/customer-portal/coderunner"
|
|
939
990
|
};
|
|
940
991
|
case "run":
|
|
@@ -993,10 +1044,17 @@ function suggestCli(intent, args) {
|
|
|
993
1044
|
why: "Dataplane is required for vault, files, and secrets.",
|
|
994
1045
|
docs: "https://docs.groundfloor.cloud/docs/customer-portal/developers"
|
|
995
1046
|
};
|
|
1047
|
+
case "vault_token":
|
|
1048
|
+
case "m2m_token":
|
|
1049
|
+
return {
|
|
1050
|
+
command: `gf m2m token${ws}`,
|
|
1051
|
+
why: "Exchange GROUNDFLOOR_M2M_CLIENT_ID + GROUNDFLOOR_M2M_CLIENT_SECRET for a short Control Plane JWT. Call Vault and Files at $CONTROLPLANE_URL. Never DATAPLANE_SERVICE_API_KEY. gf token is a builder credential.",
|
|
1052
|
+
docs: "https://docs.groundfloor.cloud/docs/customer-portal/m2m-tokens"
|
|
1053
|
+
};
|
|
996
1054
|
default:
|
|
997
1055
|
return {
|
|
998
1056
|
command: "gf --help",
|
|
999
|
-
why: `Unknown intent "${intent}". Use login | switch_workspace | deploy | run | status | logs | environments | cancel_deployment | init_app | publish_app | secrets | dataplane.`,
|
|
1057
|
+
why: `Unknown intent "${intent}". Use login | switch_workspace | deploy | run | status | logs | environments | cancel_deployment | init_app | publish_app | secrets | dataplane | vault_token.`,
|
|
1000
1058
|
docs: "https://docs.groundfloor.cloud/docs/customer-portal/developers"
|
|
1001
1059
|
};
|
|
1002
1060
|
}
|
|
@@ -1101,7 +1159,7 @@ server.tool(
|
|
|
1101
1159
|
coderunner_howto: {
|
|
1102
1160
|
docs_get: "coderunner",
|
|
1103
1161
|
runtime_contract: "coderunner-runtime",
|
|
1104
|
-
before_create: "
|
|
1162
|
+
before_create: "Team write can create Coderunners without App authentication. Site auth is optional (end-user login). Mode none uses Portal JWKS (GET /v1/public/jwks.json).",
|
|
1105
1163
|
types: {
|
|
1106
1164
|
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.",
|
|
1107
1165
|
job: "Run-to-completion worker. Deploy, then gf coderunner run.",
|
|
@@ -1109,7 +1167,7 @@ server.tool(
|
|
|
1109
1167
|
service: "Long-running Deployment (same type as service). Dockerfile at ZIP root is required. Listen on 8080 / 0.0.0.0."
|
|
1110
1168
|
},
|
|
1111
1169
|
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.",
|
|
1112
|
-
local_live_data: 'eval "$(gf env)"
|
|
1170
|
+
local_live_data: 'eval "$(gf env)". For files/secrets as a builder use Bearer $(gf token). For Vault/Files as the deployed workload, attach an M2M client and use Bearer $(gf m2m token). Never DATAPLANE_SERVICE_API_KEY. Do not zip .env files.'
|
|
1113
1171
|
},
|
|
1114
1172
|
shell_app_howto: {
|
|
1115
1173
|
docs_get: "shell",
|
|
@@ -1132,6 +1190,7 @@ server.tool(
|
|
|
1132
1190
|
logs: suggestCli("logs"),
|
|
1133
1191
|
environments: suggestCli("environments"),
|
|
1134
1192
|
cancel_deployment: suggestCli("cancel_deployment"),
|
|
1193
|
+
vault_token: suggestCli("m2m_token"),
|
|
1135
1194
|
init_app: suggestCli("init_app"),
|
|
1136
1195
|
publish_app: suggestCli("publish_app")
|
|
1137
1196
|
},
|
|
@@ -1430,10 +1489,10 @@ server.tool(
|
|
|
1430
1489
|
);
|
|
1431
1490
|
server.tool(
|
|
1432
1491
|
"docs_get",
|
|
1433
|
-
"How-to for Coderunner, Shell, design-standard, css-and-styling, databases. Pass id from docs_list. Prefer id coderunner or coderunner-runtime before deploying. For
|
|
1492
|
+
"How-to for Coderunner, Shell, design-standard, css-and-styling, databases, access, m2m. Pass id from docs_list. Prefer id coderunner or coderunner-runtime before deploying. For site grants use id access. For Coderunner Vault/Files use id m2m.",
|
|
1434
1493
|
{
|
|
1435
1494
|
id: z.string().min(1).describe(
|
|
1436
|
-
"Catalog id, e.g. coderunner | coderunner-runtime | shell | design-standard | css-and-styling | databases | agents | developers | authentication"
|
|
1495
|
+
"Catalog id, e.g. coderunner | coderunner-runtime | shell | design-standard | css-and-styling | databases | agents | developers | authentication | access | m2m"
|
|
1437
1496
|
)
|
|
1438
1497
|
},
|
|
1439
1498
|
async ({ id }) => {
|
|
@@ -1468,10 +1527,12 @@ server.tool(
|
|
|
1468
1527
|
"init_app",
|
|
1469
1528
|
"publish_app",
|
|
1470
1529
|
"secrets",
|
|
1471
|
-
"dataplane"
|
|
1530
|
+
"dataplane",
|
|
1531
|
+
"vault_token",
|
|
1532
|
+
"m2m_token"
|
|
1472
1533
|
]),
|
|
1473
1534
|
workspace: z.string().optional(),
|
|
1474
|
-
name: z.string().optional().describe("Coderunner name/id for deploy/run/status/logs/cancel_deployment"),
|
|
1535
|
+
name: z.string().optional().describe("Coderunner name/id for deploy/run/status/logs/cancel_deployment/vault_token"),
|
|
1475
1536
|
slug: z.string().optional().describe("Portal app slug for init_app / publish_app"),
|
|
1476
1537
|
cell: z.enum(["production", "stage", "dev"]).optional()
|
|
1477
1538
|
},
|