@groundfloorcloud/mcp 0.1.9 → 0.1.11
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/dist/index.js +97 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -473,6 +473,22 @@ server.listen(port, "0.0.0.0", () => {
|
|
|
473
473
|
|
|
474
474
|
Offer GET \`/\` or \`/health\` for the probe. Sample: \`samples/hello-fn/\`.
|
|
475
475
|
|
|
476
|
+
## Known issue: bootstrap has been reported to skip \`npm start\`
|
|
477
|
+
|
|
478
|
+
Reported 2026-09-22 against a \`function\` deploy with no Dockerfile, **unresolved as of this
|
|
479
|
+
writing**: instead of running \`npm start\` per the contract above, the platform's own
|
|
480
|
+
\`/app/main.js\` ran \`require('./handler')\` \u2014 a file/module contract this document does not
|
|
481
|
+
describe \u2014 even though \`scripts.start\` and the entrypoint were present and correct. Symptom in
|
|
482
|
+
\`gf coderunner logs -c <id>\`: \`Cannot find module './handler'\` (\`MODULE_NOT_FOUND\`), repeated
|
|
483
|
+
probe \`127.0.0.1:8080\` connection refused, deployment **Failed (status 4)**. Whether \`job\` and
|
|
484
|
+
\`schedule\` share this bootstrap path and are equally affected has not been confirmed either way \u2014
|
|
485
|
+
treat the workaround below as precautionary for those types too if you hit the same signature.
|
|
486
|
+
|
|
487
|
+
**Workaround:** add your own root \`Dockerfile\` (e.g. \`CMD ["npm", "start"]\`) and keep your
|
|
488
|
+
existing \`workload_type\` \u2014 a Dockerfile bypasses the injected bootstrap entirely regardless of
|
|
489
|
+
type (see "Node (with Dockerfile)" below), so this sidesteps the bug without changing how the
|
|
490
|
+
workload is invoked.
|
|
491
|
+
|
|
476
492
|
## Node (with Dockerfile)
|
|
477
493
|
|
|
478
494
|
You own \`CMD\`. If it is \`npm start\`, you still need \`scripts.start\`.
|
|
@@ -556,11 +572,17 @@ Pick **one** type per coderunner. Changing type later means a new coderunner.
|
|
|
556
572
|
probe \`127.0.0.1:8080\` connection refused, deployment **Failed (status 4)**.
|
|
557
573
|
- Python: process must bind 0.0.0.0:\${PORT:-8080}.
|
|
558
574
|
- After deploy: \`gf coderunner run -c <slug> --payload '{"hello":"world"}'\`.
|
|
575
|
+
- \u26A0\uFE0F See "Known issue" in \`docs_get\` id \`coderunner-runtime\` if \`gf coderunner logs\` shows
|
|
576
|
+
\`Cannot find module './handler'\` despite a correct \`scripts.start\` \u2014 add a Dockerfile as the
|
|
577
|
+
workaround, no type change needed.
|
|
559
578
|
|
|
560
579
|
### Job
|
|
561
580
|
|
|
562
581
|
- Same package rules as function. No need to serve forever; exit 0 on success.
|
|
563
582
|
- Deploy, then start a run (\`gf coderunner run\`). Check Process Log.
|
|
583
|
+
- \u26A0\uFE0F Not confirmed whether the no-Dockerfile bootstrap bug in \`docs_get\` id \`coderunner-runtime\`
|
|
584
|
+
("Known issue") also hits \`job\` \u2014 if a run never starts and logs show the same
|
|
585
|
+
\`MODULE_NOT_FOUND: './handler'\`, apply the same Dockerfile workaround.
|
|
564
586
|
|
|
565
587
|
### Schedule
|
|
566
588
|
|
|
@@ -570,6 +592,8 @@ Pick **one** type per coderunner. Changing type later means a new coderunner.
|
|
|
570
592
|
- GET/list/status expose top-level \`workload_type\` and \`schedule\`.
|
|
571
593
|
\`gf coderunner status -c <slug>\` prints type, schedule, last_job.
|
|
572
594
|
- No public invoke URL. Debug with \`gf coderunner logs\`, not curl.
|
|
595
|
+
- \u26A0\uFE0F Same caveat as Job: unconfirmed whether the bootstrap "Known issue" affects scheduled runs;
|
|
596
|
+
same Dockerfile workaround if you see the identical crash signature.
|
|
573
597
|
|
|
574
598
|
### Service (Deployment)
|
|
575
599
|
|
|
@@ -661,8 +685,13 @@ When the handler looks right locally, \`gf deploy\` the same tree.
|
|
|
661
685
|
Do not pass credential-shaped keys as \`--env KEY=VALUE\` (\`*_SECRET\`,
|
|
662
686
|
\`*_API_KEY\`, \`DATABASE_URL\`, \u2026). Control Plane returns **422**.
|
|
663
687
|
\`gf secrets set KEY\` then \`gf deploy --secret KEY\` (inject by reference).
|
|
688
|
+
This requires \`CODERUNNER_INJECT_ENV_SECRETS\` enabled for the workspace \u2014
|
|
689
|
+
**off by default**. If \`--secret\` 422s naming that setting, either ask your
|
|
690
|
+
platform operator to enable it, or read the secret live via M2M
|
|
691
|
+
\`secrets:read\` instead (below) rather than falling back to plaintext
|
|
692
|
+
\`--env\`.
|
|
664
693
|
|
|
665
|
-
## M2M tokens (Vault and
|
|
694
|
+
## M2M tokens (Vault, Files, and Secrets)
|
|
666
695
|
|
|
667
696
|
New Coderunners cannot call Vault or Files until an M2M client is attached
|
|
668
697
|
and the workload is redeployed. Create the client in Portal **Administer \u2192
|
|
@@ -670,6 +699,29 @@ M2M tokens**, attach it on the Coderunner card, then deploy. v1 M2M is Team
|
|
|
670
699
|
Writer on that workspace (full Vault skip-ACL + Files). Grant site users on
|
|
671
700
|
**Administer \u2192 Access**. Never inject a Dataplane key.
|
|
672
701
|
|
|
702
|
+
An M2M client can also read secret **values** directly at runtime instead
|
|
703
|
+
of (or alongside) \`--secret\` deploy-time injection: grant it the
|
|
704
|
+
**\`secrets:read\`** scope (same Portal **Administer \u2192 M2M tokens** screen,
|
|
705
|
+
per-client toggle), then call
|
|
706
|
+
\`GET {CONTROLPLANE_URL}/v1/workspaces/{workspace_id}/secrets/{key}\` with
|
|
707
|
+
\`Authorization: Bearer\` from \`gf m2m token\` locally, or the deployed
|
|
708
|
+
workload's injected \`GROUNDFLOOR_M2M_CLIENT_ID\`/\`GROUNDFLOOR_M2M_CLIENT_SECRET\`
|
|
709
|
+
exchanged the same way. This path is:
|
|
710
|
+
|
|
711
|
+
- **Read-only** \u2014 \`secrets:read\` never grants \`upsert\`/\`delete\`, regardless
|
|
712
|
+
of the client's writer relation on Vault/Files.
|
|
713
|
+
- **Live** \u2014 a rotated secret is visible on your next call, no redeploy
|
|
714
|
+
needed. \`--secret\` injection only updates on the next deploy.
|
|
715
|
+
- **Workspace-wide, not per-key or per-environment** \u2014 granting the scope
|
|
716
|
+
exposes every secret in the workspace across all environments to that
|
|
717
|
+
client's code, same class of trade as the existing Vault/Files writer
|
|
718
|
+
grant. Not a fit for isolating one secret to one Coderunner.
|
|
719
|
+
|
|
720
|
+
Prefer it over \`--secret\` injection when you want live rotation and can
|
|
721
|
+
do the fetch yourself; keep using \`--secret\` injection for SDKs that only
|
|
722
|
+
read a literal \`process.env\` value. Either way, cache the revealed value
|
|
723
|
+
in your process rather than calling \`reveal\` on every request.
|
|
724
|
+
|
|
673
725
|
## Agent actions
|
|
674
726
|
|
|
675
727
|
Inspect: \`workspace_context\`, \`docs_get\` id \`coderunner\` or \`coderunner-runtime\`, \`suggest_cli\`.
|
|
@@ -872,6 +924,10 @@ Pass \`engine\` explicitly \u2014 don't rely on Dataplane's default connector.
|
|
|
872
924
|
\`"postgresql"\` is the platform default (shared, no deploy step);
|
|
873
925
|
\`"arangodb"\` is also available the same way.
|
|
874
926
|
|
|
927
|
+
\`id\` and \`tenant_id\` are reserved field names on Postgres (and any SQL-shaped
|
|
928
|
+
engine) \u2014 Dataplane adds them automatically as system columns on every table.
|
|
929
|
+
Declaring either as a property is a **400**, not a 500. Not reserved on ArangoDB.
|
|
930
|
+
|
|
875
931
|
Example:
|
|
876
932
|
|
|
877
933
|
\`\`\`json
|
|
@@ -934,6 +990,18 @@ Do not \`--env SENDGRID_SECRET=\u2026\`. That is **422**.
|
|
|
934
990
|
\`gf secrets set SENDGRID_SECRET\` then \`gf deploy --secret SENDGRID_SECRET\`.
|
|
935
991
|
`.trim();
|
|
936
992
|
|
|
993
|
+
// src/version.ts
|
|
994
|
+
import { readFileSync } from "fs";
|
|
995
|
+
import { dirname, join } from "path";
|
|
996
|
+
import { fileURLToPath } from "url";
|
|
997
|
+
var moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
998
|
+
function readPackageVersion() {
|
|
999
|
+
const pkgPath = join(moduleDir, "..", "package.json");
|
|
1000
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
1001
|
+
return pkg.version;
|
|
1002
|
+
}
|
|
1003
|
+
var GF_MCP_VERSION = readPackageVersion();
|
|
1004
|
+
|
|
937
1005
|
// src/docs.ts
|
|
938
1006
|
var DOCS_ORIGIN = "https://docs.groundfloor.cloud";
|
|
939
1007
|
var DOC_CATALOG = [
|
|
@@ -954,21 +1022,24 @@ var DOC_CATALOG = [
|
|
|
954
1022
|
title: "Coderunner",
|
|
955
1023
|
path: "/docs/customer-portal/coderunner",
|
|
956
1024
|
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.",
|
|
957
|
-
embedded: CODERUNNER_GUIDE
|
|
1025
|
+
embedded: CODERUNNER_GUIDE,
|
|
1026
|
+
lastUpdated: "2026-09-23"
|
|
958
1027
|
},
|
|
959
1028
|
{
|
|
960
1029
|
id: "coderunner-runtime",
|
|
961
1030
|
title: "Coderunner runtime contract",
|
|
962
1031
|
path: "/docs/customer-portal/coderunner",
|
|
963
1032
|
summary: "What the platform expects your code to do: Node bootstrap (npm start, PORT/8080, bind 0.0.0.0), Python bind, service Dockerfile.",
|
|
964
|
-
embedded: CODERUNNER_RUNTIME_CONTRACT
|
|
1033
|
+
embedded: CODERUNNER_RUNTIME_CONTRACT,
|
|
1034
|
+
lastUpdated: "2026-09-23"
|
|
965
1035
|
},
|
|
966
1036
|
{
|
|
967
1037
|
id: "coderunner-overview",
|
|
968
1038
|
title: "Coderunner overview",
|
|
969
1039
|
path: "/docs/integrations/coderunner/overview",
|
|
970
1040
|
summary: "Architecture and lifecycle. Prefer docs_get id coderunner for type usage, Dockerfile, and create prerequisites.",
|
|
971
|
-
embedded: CODERUNNER_GUIDE
|
|
1041
|
+
embedded: CODERUNNER_GUIDE,
|
|
1042
|
+
lastUpdated: "2026-09-23"
|
|
972
1043
|
},
|
|
973
1044
|
{
|
|
974
1045
|
id: "authentication",
|
|
@@ -999,42 +1070,48 @@ var DOC_CATALOG = [
|
|
|
999
1070
|
title: "Shell federated apps",
|
|
1000
1071
|
path: "/docs/integrations/shell",
|
|
1001
1072
|
summary: "Product Apps vs Coderunner. Always gf apps init --slug <portal-slug>, then npm run release and gf apps publish --path release.zip. Never zip dist/ or upload only remoteEntry.js.",
|
|
1002
|
-
embedded: SHELL_APP_GUIDE
|
|
1073
|
+
embedded: SHELL_APP_GUIDE,
|
|
1074
|
+
lastUpdated: "2026-09-22"
|
|
1003
1075
|
},
|
|
1004
1076
|
{
|
|
1005
1077
|
id: "design-standard",
|
|
1006
1078
|
title: "Shell app design standard",
|
|
1007
1079
|
path: "/docs/integrations/shell/design-standard",
|
|
1008
1080
|
summary: "Visual rules for Shell apps: grey ground, flat controls, Geist, one brand accent from theme.primaryColor, DataGrid, PhaseChevron. Use the kit; do not restyle to stock Tailwind.",
|
|
1009
|
-
embedded: DESIGN_STANDARD_GUIDE
|
|
1081
|
+
embedded: DESIGN_STANDARD_GUIDE,
|
|
1082
|
+
lastUpdated: "2026-09-04"
|
|
1010
1083
|
},
|
|
1011
1084
|
{
|
|
1012
1085
|
id: "css-and-styling",
|
|
1013
1086
|
title: "CSS and styling",
|
|
1014
1087
|
path: "/docs/integrations/shell/css-and-styling",
|
|
1015
1088
|
summary: "Tailwind is the default. Own CSS framework (Bootstrap, MUI, \u2026) uses FederatedStyleRoot and Shadow DOM \u2014 do not load it globally onto the Shell page.",
|
|
1016
|
-
embedded: CSS_AND_STYLING_GUIDE
|
|
1089
|
+
embedded: CSS_AND_STYLING_GUIDE,
|
|
1090
|
+
lastUpdated: "2026-09-04"
|
|
1017
1091
|
},
|
|
1018
1092
|
{
|
|
1019
1093
|
id: "databases",
|
|
1020
1094
|
title: "Databases",
|
|
1021
1095
|
path: "/docs/customer-portal/databases",
|
|
1022
1096
|
summary: "Dataplane is not a database. Postgres (shared, platform-managed) is the default, ready through Dataplane with no deploy step. ArangoDB is also ready the same way. A dedicated database you deploy and own is a separate, heavier path.",
|
|
1023
|
-
embedded: DATABASES_GUIDE
|
|
1097
|
+
embedded: DATABASES_GUIDE,
|
|
1098
|
+
lastUpdated: "2026-09-22"
|
|
1024
1099
|
},
|
|
1025
1100
|
{
|
|
1026
1101
|
id: "vault",
|
|
1027
1102
|
title: "Data Vault",
|
|
1028
1103
|
path: "/docs/api/vault",
|
|
1029
1104
|
summary: "Create collections with JSON Schema, query totals vs limit, ACLs, implicit tables, nested filters, identities vs M2M.",
|
|
1030
|
-
embedded: VAULT_GUIDE
|
|
1105
|
+
embedded: VAULT_GUIDE,
|
|
1106
|
+
lastUpdated: "2026-09-22"
|
|
1031
1107
|
},
|
|
1032
1108
|
{
|
|
1033
1109
|
id: "scheduled-jobs",
|
|
1034
1110
|
title: "Scheduled jobs",
|
|
1035
1111
|
path: "/docs/customer-portal/scheduled-jobs",
|
|
1036
1112
|
summary: "workload_type=schedule plus cron. gf coderunner status shows type/schedule/last_job. Use Process Log, not a public URL.",
|
|
1037
|
-
embedded: CODERUNNER_GUIDE
|
|
1113
|
+
embedded: CODERUNNER_GUIDE,
|
|
1114
|
+
lastUpdated: "2026-09-23"
|
|
1038
1115
|
}
|
|
1039
1116
|
];
|
|
1040
1117
|
function docUrl(entry) {
|
|
@@ -1061,7 +1138,9 @@ async function fetchDocPage(entry) {
|
|
|
1061
1138
|
title: entry.title,
|
|
1062
1139
|
text: entry.embedded.trim(),
|
|
1063
1140
|
truncated: false,
|
|
1064
|
-
source: "embedded"
|
|
1141
|
+
source: "embedded",
|
|
1142
|
+
lastUpdated: entry.lastUpdated ?? null,
|
|
1143
|
+
mcpVersion: GF_MCP_VERSION
|
|
1065
1144
|
};
|
|
1066
1145
|
}
|
|
1067
1146
|
const res = await fetch(url, {
|
|
@@ -1081,7 +1160,9 @@ async function fetchDocPage(entry) {
|
|
|
1081
1160
|
title: entry.title,
|
|
1082
1161
|
text: body,
|
|
1083
1162
|
truncated,
|
|
1084
|
-
source: "docs.groundfloor.cloud"
|
|
1163
|
+
source: "docs.groundfloor.cloud",
|
|
1164
|
+
lastUpdated: null,
|
|
1165
|
+
mcpVersion: GF_MCP_VERSION
|
|
1085
1166
|
};
|
|
1086
1167
|
}
|
|
1087
1168
|
|
|
@@ -1218,7 +1299,7 @@ async function resolveCoderunnerId(apiUrl, workspaceId, idOrSlug) {
|
|
|
1218
1299
|
}
|
|
1219
1300
|
var server = new McpServer({
|
|
1220
1301
|
name: "groundfloor",
|
|
1221
|
-
version:
|
|
1302
|
+
version: GF_MCP_VERSION
|
|
1222
1303
|
});
|
|
1223
1304
|
server.tool(
|
|
1224
1305
|
"whoami",
|
|
@@ -1599,11 +1680,13 @@ server.tool(
|
|
|
1599
1680
|
const hits = findDoc(query ?? "");
|
|
1600
1681
|
return text({
|
|
1601
1682
|
origin: "https://docs.groundfloor.cloud",
|
|
1683
|
+
mcpVersion: GF_MCP_VERSION,
|
|
1602
1684
|
docs: hits.map((d) => ({
|
|
1603
1685
|
id: d.id,
|
|
1604
1686
|
title: d.title,
|
|
1605
1687
|
url: `https://docs.groundfloor.cloud${d.path}`,
|
|
1606
|
-
summary: d.summary
|
|
1688
|
+
summary: d.summary,
|
|
1689
|
+
lastUpdated: d.lastUpdated ?? null
|
|
1607
1690
|
}))
|
|
1608
1691
|
});
|
|
1609
1692
|
}
|