@groundfloorcloud/mcp 0.1.13 → 0.1.15
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 -2
- package/dist/index.js +236 -70
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -84,8 +84,9 @@ then `npm run release` and `gf apps publish --path release.zip`. Do not invent
|
|
|
84
84
|
`App.tsx` / `vite.config`, zip `dist/`, or upload only `remoteEntry.js`.
|
|
85
85
|
Own CSS framework: `docs_get` id `css-and-styling` (`FederatedStyleRoot`).
|
|
86
86
|
|
|
87
|
-
**Databases:** `docs_get` id `databases`. Dataplane is not a database.
|
|
88
|
-
is ready through Dataplane;
|
|
87
|
+
**Databases:** `docs_get` id `databases`. Dataplane is not a database. Shared
|
|
88
|
+
PostgreSQL is ready through Dataplane; a dedicated PostgreSQL is what you can
|
|
89
|
+
deploy today. No other engines are offered.
|
|
89
90
|
|
|
90
91
|
**Coderunner how-to** is embedded: `docs_get` id `coderunner` (also
|
|
91
92
|
`coderunner-overview`). That page covers:
|
package/dist/index.js
CHANGED
|
@@ -327,6 +327,12 @@ function listSecrets(apiUrl, workspaceId, environmentId) {
|
|
|
327
327
|
})}`
|
|
328
328
|
);
|
|
329
329
|
}
|
|
330
|
+
function listFlags(apiUrl, workspaceId, environmentId) {
|
|
331
|
+
return cpGet(
|
|
332
|
+
apiUrl,
|
|
333
|
+
`${wsPath(workspaceId, "/flags")}${queryString({ environment_id: environmentId })}`
|
|
334
|
+
);
|
|
335
|
+
}
|
|
330
336
|
function listFiles(apiUrl, workspaceId) {
|
|
331
337
|
return cpGet(apiUrl, wsPath(workspaceId, "/files"));
|
|
332
338
|
}
|
|
@@ -764,7 +770,7 @@ If they opt out of Tailwind:
|
|
|
764
770
|
|
|
765
771
|
The kit ships FederatedStyleRoot in src/lib/FederatedStyleRoot.tsx.
|
|
766
772
|
|
|
767
|
-
Human docs: /docs/
|
|
773
|
+
Human docs: /docs/apps/shell/styling
|
|
768
774
|
`;
|
|
769
775
|
|
|
770
776
|
// src/databases-guide.ts
|
|
@@ -776,46 +782,43 @@ Dataplane is not a database. It is how Groundfloor talks to databases.
|
|
|
776
782
|
When the user starts any data or database work, say this first. Do not mention
|
|
777
783
|
infrastructure internals (cluster operators, installers, and the like):
|
|
778
784
|
|
|
779
|
-
You have
|
|
780
|
-
cluster, already there, no deploy step. If you want a
|
|
781
|
-
database that is entirely your own (own scaling, own
|
|
782
|
-
|
|
785
|
+
You have PostgreSQL ready to use through Dataplane \u2014 a shared,
|
|
786
|
+
platform-managed cluster, already there, no deploy step. If you want a
|
|
787
|
+
database that is entirely your own (own scaling, own backup schedule), you can
|
|
788
|
+
deploy a dedicated PostgreSQL first.
|
|
783
789
|
|
|
784
790
|
## Options
|
|
785
791
|
|
|
786
|
-
-
|
|
792
|
+
- PostgreSQL (shared) \u2014 platform-managed, already there. Default for app data
|
|
787
793
|
and Vault. No deploy step. This is NOT a workspace-owned resource: it does
|
|
788
794
|
not appear on the customer Databases page, and there is nothing to scale,
|
|
789
795
|
back up, or delete yourself \u2014 it's offered, not provisioned. Query via
|
|
790
796
|
Control Plane vault: POST /v1/workspaces/{id}/vault/collections/{name}/query
|
|
791
|
-
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
POST /v1/workspaces/{id}/managed-databases. Heavier than the shared
|
|
796
|
-
default: you own its scaling, backups, and lifecycle. Use this when you
|
|
797
|
-
need a tier/engine the shared default doesn't offer (Redis, ClickHouse,
|
|
798
|
-
Qdrant) or want a database isolated to this workspace.
|
|
797
|
+
- Dedicated PostgreSQL you deploy and own \u2014 portal Data \u2192 Databases, or
|
|
798
|
+
POST /v1/workspaces/{id}/managed-databases with engine postgres. Heavier
|
|
799
|
+
than the shared default: you own its scaling, backups, and lifecycle. Use it
|
|
800
|
+
when you want a database isolated to this workspace.
|
|
799
801
|
- A database they already run \u2014 through Dataplane if they wire it, or direct.
|
|
800
802
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
+
PostgreSQL is the only engine offered today, shared or dedicated. Do not offer
|
|
804
|
+
other engines (ArangoDB, MongoDB, Redis, ClickHouse, Qdrant, \u2026) as available,
|
|
805
|
+
even if you see them mentioned elsewhere. Do not call Dataplane hosts from apps
|
|
806
|
+
or embed service keys.
|
|
803
807
|
|
|
804
808
|
## Creating a collection / table
|
|
805
809
|
|
|
806
810
|
Pass the engine explicitly \u2014 do not rely on Dataplane's default connector
|
|
807
811
|
resolution. POST /v1/workspaces/{id}/vault/collections with
|
|
808
|
-
\`"schema": {"engine": "postgresql", ...}
|
|
809
|
-
\`"engine": "arangodb"\` to use ArangoDB instead.
|
|
812
|
+
\`"schema": {"engine": "postgresql", ...}\`.
|
|
810
813
|
|
|
811
814
|
## Paths
|
|
812
815
|
|
|
813
816
|
- Browse / edit rows \u2192 Data Vault (portal or vault APIs)
|
|
814
|
-
- Deploy your own
|
|
815
|
-
POST /v1/workspaces/{id}/managed-databases with engine postgres
|
|
817
|
+
- Deploy your own PostgreSQL \u2192 Customer Portal Databases page, or
|
|
818
|
+
POST /v1/workspaces/{id}/managed-databases with engine postgres
|
|
816
819
|
- Shell 403 / empty vault \u2192 collection Access for the site role
|
|
817
820
|
|
|
818
|
-
docs_get id databases. Human docs: /docs/
|
|
821
|
+
docs_get id databases. Human docs: /docs/data/databases and /docs/data/data-vault
|
|
819
822
|
`;
|
|
820
823
|
|
|
821
824
|
// src/design-standard-guide.ts
|
|
@@ -865,6 +868,112 @@ stay in Shadow DOM. Render modals inside that root, not document.body.
|
|
|
865
868
|
Full steps: docs_get id css-and-styling.
|
|
866
869
|
`;
|
|
867
870
|
|
|
871
|
+
// src/flags-guide.ts
|
|
872
|
+
var FLAGS_GUIDE = `
|
|
873
|
+
# Feature Flags
|
|
874
|
+
|
|
875
|
+
Groundfloor has built-in feature flags: per-environment key \u2192 value toggles
|
|
876
|
+
(boolean, string, number or JSON) stored in Control Plane. **Use them instead
|
|
877
|
+
of building a flags table in a Vault collection or reading \`.env\`.** Each
|
|
878
|
+
environment (dev / staging / prod) has its own values; \`promote\` copies
|
|
879
|
+
between them.
|
|
880
|
+
|
|
881
|
+
## Manage (builder)
|
|
882
|
+
|
|
883
|
+
\`\`\`bash
|
|
884
|
+
gf flags ls -e dev # -e takes an environment id or name
|
|
885
|
+
gf flags set new-checkout true -e dev # type inferred; --type json for objects
|
|
886
|
+
gf flags compare dev prod
|
|
887
|
+
gf flags promote dev prod --dry-run
|
|
888
|
+
gf flags rm new-checkout -e dev
|
|
889
|
+
\`\`\`
|
|
890
|
+
|
|
891
|
+
Or the Portal: Workspace \u2192 Feature Flags. API (builder \`gf token\`):
|
|
892
|
+
\`GET|PUT|DELETE /v1/workspaces/{id}/flags[/{key}]?environment_id=\`,
|
|
893
|
+
\`GET \u2026/flags/compare\`, \`POST \u2026/flags/promote\` \u2014 docs_get id \`flags-api\`.
|
|
894
|
+
|
|
895
|
+
- **Keys**: trimmed + lowercased, then \`^[a-z][a-z0-9_.-]{0,62}$\` (\`new-checkout\`,
|
|
896
|
+
\`ui.dark_mode\`). \`compare\`, \`promote\`, \`runtime\` are reserved.
|
|
897
|
+
- **Values**: \`value_type\` defaults to \`boolean\`; a mismatched value is 422.
|
|
898
|
+
- **Default environment**: omit \`environment_id\` \u2192 the active env named
|
|
899
|
+
\`dev\` (or the only active env). The response echoes the resolved
|
|
900
|
+
\`environment_id\`. Pass it explicitly for anything prod-facing.
|
|
901
|
+
|
|
902
|
+
## Read at runtime (apps)
|
|
903
|
+
|
|
904
|
+
One endpoint for every runtime:
|
|
905
|
+
|
|
906
|
+
\`GET /v1/workspaces/{workspace_id}/flags/runtime?environment_id=<env>\`
|
|
907
|
+
\u2192 \`{ "workspace_id", "environment_id", "flags": { "new-checkout": true, \u2026 } }\`
|
|
908
|
+
|
|
909
|
+
Weak \`ETag\` + \`Cache-Control: private, no-cache\`. Send \`If-None-Match\` \u2192 304.
|
|
910
|
+
Poll no faster than every 30s (the kit uses 60s). No push channel yet.
|
|
911
|
+
Flag values are not secrets \u2014 every signed-in end user can read them.
|
|
912
|
+
|
|
913
|
+
### Shell federated app (browser)
|
|
914
|
+
|
|
915
|
+
- **Token**: the Shell end-user JWT, \`await window.__GF_GET_ACCESS_TOKEN__()\`.
|
|
916
|
+
- **Permission**: workspace \`read\`. Site users get it from a recognised site
|
|
917
|
+
role (member/admin); self-registered users with no role get 403 (same rule
|
|
918
|
+
as Vault). No per-flag Access grant exists or is needed.
|
|
919
|
+
- **Environment**: \`window.__GF_ENVIRONMENT_ID__\` \u2014 the environment the app is
|
|
920
|
+
bound to, published by the Shell before your remote mounts. Unset in local
|
|
921
|
+
Dev Shell \u2192 server default (dev); \`VITE_GF_ENVIRONMENT_ID\` pins one.
|
|
922
|
+
- **Code**: the starter kit ships \`src/lib/flags.ts\`. Do not hand-roll it.
|
|
923
|
+
|
|
924
|
+
\`\`\`tsx
|
|
925
|
+
import { useFlag, useFlags } from './lib/flags';
|
|
926
|
+
|
|
927
|
+
export function Checkout() {
|
|
928
|
+
const newCheckout = useFlag('new-checkout', false);
|
|
929
|
+
const maxItems = useFlag('max-items', 10);
|
|
930
|
+
return newCheckout ? <NewCheckout max={maxItems} /> : <LegacyCheckout />;
|
|
931
|
+
}
|
|
932
|
+
// Many flags: const { flags, loading, error } = useFlags();
|
|
933
|
+
\`\`\`
|
|
934
|
+
|
|
935
|
+
### Coderunner (server)
|
|
936
|
+
|
|
937
|
+
- **Token**: M2M \u2014 \`gf m2m token\` locally, or exchange
|
|
938
|
+
\`GROUNDFLOOR_M2M_CLIENT_ID\`/\`_SECRET\` at \`POST \u2026/m2m/token\` in code. M2M is
|
|
939
|
+
**read-only** on flags (PUT/DELETE/promote \u2192 403). Workload-identity Vault
|
|
940
|
+
JWTs cannot read flags (403).
|
|
941
|
+
- **Environment**: \`GROUNDFLOOR_ENVIRONMENT_ID\` is injected on deploy (the
|
|
942
|
+
Coderunner's bound environment). \`GROUNDFLOOR_WORKSPACE_ID\`,
|
|
943
|
+
\`CONTROLPLANE_URL\` and the M2M client id/secret are injected when an M2M
|
|
944
|
+
client is attached. Redeploy once to pick up the variable on older deploys.
|
|
945
|
+
|
|
946
|
+
\`\`\`js
|
|
947
|
+
const CP = process.env.CONTROLPLANE_URL;
|
|
948
|
+
const WS = process.env.GROUNDFLOOR_WORKSPACE_ID;
|
|
949
|
+
const ENV = process.env.GROUNDFLOOR_ENVIRONMENT_ID;
|
|
950
|
+
let cache = { etag: null, flags: {} };
|
|
951
|
+
|
|
952
|
+
export async function getFlags(token) {
|
|
953
|
+
const qs = ENV ? \`?environment_id=\${encodeURIComponent(ENV)}\` : '';
|
|
954
|
+
const res = await fetch(\`\${CP}/v1/workspaces/\${WS}/flags/runtime\${qs}\`, {
|
|
955
|
+
headers: {
|
|
956
|
+
Authorization: \`Bearer \${token}\`,
|
|
957
|
+
...(cache.etag ? { 'If-None-Match': cache.etag } : {}),
|
|
958
|
+
},
|
|
959
|
+
});
|
|
960
|
+
if (res.status === 304) return cache.flags;
|
|
961
|
+
if (!res.ok) throw new Error(\`flags \${res.status}: \${await res.text()}\`);
|
|
962
|
+
const body = await res.json();
|
|
963
|
+
cache = { etag: res.headers.get('etag'), flags: body.flags };
|
|
964
|
+
return cache.flags;
|
|
965
|
+
}
|
|
966
|
+
// Call per request with a cached M2M token; refresh at most every 30\u201360s.
|
|
967
|
+
\`\`\`
|
|
968
|
+
|
|
969
|
+
## Errors
|
|
970
|
+
|
|
971
|
+
401 bad/missing token \xB7 403 no workspace read, M2M write, or workload identity \xB7
|
|
972
|
+
404 unknown workspace/environment/flag \xB7 409 environment not active, or no
|
|
973
|
+
active environments \xB7 400 bad or reserved key \xB7 422 value/value_type mismatch \xB7
|
|
974
|
+
423 workspace frozen (writes).
|
|
975
|
+
`.trim();
|
|
976
|
+
|
|
868
977
|
// src/shell-guide.ts
|
|
869
978
|
var SHELL_APP_GUIDE = `
|
|
870
979
|
# Shell federated apps
|
|
@@ -899,10 +1008,9 @@ remoteEntry.js. Header logos: manifest \`theme.logoUrl\` (absolute https).
|
|
|
899
1008
|
UI look: \`docs_get\` id \`design-standard\`. CSS: Tailwind by default;
|
|
900
1009
|
own framework uses FederatedStyleRoot (Shadow DOM) \u2014 \`docs_get\` id
|
|
901
1010
|
\`css-and-styling\`. Data: Dataplane is not a database. Say first: you have
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
(\`docs_get\` id \`databases\`). Local UI without live vault:
|
|
1011
|
+
PostgreSQL (shared, platform-managed, no deploy step) ready through Dataplane.
|
|
1012
|
+
Deploy a dedicated PostgreSQL only if you want workspace-owned isolation.
|
|
1013
|
+
No other engines are offered (\`docs_get\` id \`databases\`). Local UI without live vault:
|
|
906
1014
|
\`npm run dev:fixtures\`.
|
|
907
1015
|
|
|
908
1016
|
Detail routes (e.g. \`records/:id\`): once the record loads, call
|
|
@@ -934,12 +1042,14 @@ POST \`/v1/workspaces/{id}/vault/collections\` with a **JSON Schema** object
|
|
|
934
1042
|
**400** with a field error \u2014 not a 500.
|
|
935
1043
|
|
|
936
1044
|
Pass \`engine\` explicitly \u2014 don't rely on Dataplane's default connector.
|
|
937
|
-
\`"postgresql"\` is the platform default (shared, no deploy step)
|
|
938
|
-
\`
|
|
1045
|
+
\`"postgresql"\` is the platform default (shared, no deploy step) and the only
|
|
1046
|
+
engine offered today. \`?connection=\` must be \`postgresql\` or the name of a dedicated
|
|
1047
|
+
PostgreSQL in this workspace \u2014 another engine or an unknown name is **400**.
|
|
939
1048
|
|
|
940
|
-
\`id\` and \`
|
|
941
|
-
|
|
942
|
-
|
|
1049
|
+
\`id\`, \`tenant_id\`, and \`gf_extra\` are reserved field names \u2014 Dataplane adds
|
|
1050
|
+
them automatically as system columns on every Postgres table. Declaring any of
|
|
1051
|
+
them as a property is a **400**, not a 500. Undeclared record fields are kept in \`gf_extra\` and
|
|
1052
|
+
merged back on read, so extra keys are not lost.
|
|
943
1053
|
|
|
944
1054
|
Example:
|
|
945
1055
|
|
|
@@ -1021,19 +1131,19 @@ var DOC_CATALOG = [
|
|
|
1021
1131
|
{
|
|
1022
1132
|
id: "agents",
|
|
1023
1133
|
title: "Deploy with agents",
|
|
1024
|
-
path: "/docs/
|
|
1134
|
+
path: "/docs/developer-tools/ai-agents",
|
|
1025
1135
|
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."
|
|
1026
1136
|
},
|
|
1027
1137
|
{
|
|
1028
1138
|
id: "developers",
|
|
1029
1139
|
title: "Developers (gf CLI)",
|
|
1030
|
-
path: "/docs/
|
|
1031
|
-
summary: "gf login, workspaces, deploy, secrets, files, apps, gf m2m token. Coderunner types: function, job, schedule, service (also called Deployment). App authentication optional."
|
|
1140
|
+
path: "/docs/developer-tools/cli",
|
|
1141
|
+
summary: "gf login, workspaces, deploy, secrets, feature flags (gf flags), files, apps, gf m2m token. Coderunner types: function, job, schedule, service (also called Deployment). App authentication optional."
|
|
1032
1142
|
},
|
|
1033
1143
|
{
|
|
1034
1144
|
id: "coderunner",
|
|
1035
1145
|
title: "Coderunner",
|
|
1036
|
-
path: "/docs/
|
|
1146
|
+
path: "/docs/deploy",
|
|
1037
1147
|
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.",
|
|
1038
1148
|
embedded: CODERUNNER_GUIDE,
|
|
1039
1149
|
lastUpdated: "2026-09-25"
|
|
@@ -1041,7 +1151,7 @@ var DOC_CATALOG = [
|
|
|
1041
1151
|
{
|
|
1042
1152
|
id: "coderunner-runtime",
|
|
1043
1153
|
title: "Coderunner runtime contract",
|
|
1044
|
-
path: "/docs/
|
|
1154
|
+
path: "/docs/deploy",
|
|
1045
1155
|
summary: "What the platform expects your code to do: Node bootstrap (npm start, PORT/8080, bind 0.0.0.0), Python bind, service Dockerfile.",
|
|
1046
1156
|
embedded: CODERUNNER_RUNTIME_CONTRACT,
|
|
1047
1157
|
lastUpdated: "2026-09-23"
|
|
@@ -1049,7 +1159,7 @@ var DOC_CATALOG = [
|
|
|
1049
1159
|
{
|
|
1050
1160
|
id: "coderunner-overview",
|
|
1051
1161
|
title: "Coderunner overview",
|
|
1052
|
-
path: "/docs/
|
|
1162
|
+
path: "/docs/deploy",
|
|
1053
1163
|
summary: "Architecture and lifecycle. Prefer docs_get id coderunner for type usage, Dockerfile, and create prerequisites.",
|
|
1054
1164
|
embedded: CODERUNNER_GUIDE,
|
|
1055
1165
|
lastUpdated: "2026-09-25"
|
|
@@ -1057,19 +1167,19 @@ var DOC_CATALOG = [
|
|
|
1057
1167
|
{
|
|
1058
1168
|
id: "authentication",
|
|
1059
1169
|
title: "Workspace Authentication",
|
|
1060
|
-
path: "/docs/
|
|
1170
|
+
path: "/docs/access/app-authentication",
|
|
1061
1171
|
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."
|
|
1062
1172
|
},
|
|
1063
1173
|
{
|
|
1064
1174
|
id: "access",
|
|
1065
1175
|
title: "Access",
|
|
1066
|
-
path: "/docs/
|
|
1176
|
+
path: "/docs/access/site-access",
|
|
1067
1177
|
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."
|
|
1068
1178
|
},
|
|
1069
1179
|
{
|
|
1070
1180
|
id: "m2m",
|
|
1071
1181
|
title: "M2M tokens",
|
|
1072
|
-
path: "/docs/
|
|
1182
|
+
path: "/docs/access/m2m-tokens",
|
|
1073
1183
|
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. Secrets only with the opt-in secrets:read scope (read-only). Cache the token; minting is rate-limited per client and IP."
|
|
1074
1184
|
},
|
|
1075
1185
|
{
|
|
@@ -1081,15 +1191,15 @@ var DOC_CATALOG = [
|
|
|
1081
1191
|
{
|
|
1082
1192
|
id: "shell",
|
|
1083
1193
|
title: "Shell federated apps",
|
|
1084
|
-
path: "/docs/
|
|
1194
|
+
path: "/docs/apps/shell",
|
|
1085
1195
|
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.",
|
|
1086
1196
|
embedded: SHELL_APP_GUIDE,
|
|
1087
|
-
lastUpdated: "2026-09-
|
|
1197
|
+
lastUpdated: "2026-09-26"
|
|
1088
1198
|
},
|
|
1089
1199
|
{
|
|
1090
1200
|
id: "design-standard",
|
|
1091
1201
|
title: "Shell app design standard",
|
|
1092
|
-
path: "/docs/
|
|
1202
|
+
path: "/docs/apps/shell/styling",
|
|
1093
1203
|
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.",
|
|
1094
1204
|
embedded: DESIGN_STANDARD_GUIDE,
|
|
1095
1205
|
lastUpdated: "2026-09-04"
|
|
@@ -1097,7 +1207,7 @@ var DOC_CATALOG = [
|
|
|
1097
1207
|
{
|
|
1098
1208
|
id: "css-and-styling",
|
|
1099
1209
|
title: "CSS and styling",
|
|
1100
|
-
path: "/docs/
|
|
1210
|
+
path: "/docs/apps/shell/styling",
|
|
1101
1211
|
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.",
|
|
1102
1212
|
embedded: CSS_AND_STYLING_GUIDE,
|
|
1103
1213
|
lastUpdated: "2026-09-04"
|
|
@@ -1105,10 +1215,10 @@ var DOC_CATALOG = [
|
|
|
1105
1215
|
{
|
|
1106
1216
|
id: "databases",
|
|
1107
1217
|
title: "Databases",
|
|
1108
|
-
path: "/docs/
|
|
1109
|
-
summary: "Dataplane is not a database.
|
|
1218
|
+
path: "/docs/data/databases",
|
|
1219
|
+
summary: "Dataplane is not a database. PostgreSQL (shared, platform-managed) is ready through Dataplane with no deploy step. A dedicated PostgreSQL you deploy and own is a separate, heavier path. PostgreSQL is the only engine offered.",
|
|
1110
1220
|
embedded: DATABASES_GUIDE,
|
|
1111
|
-
lastUpdated: "2026-09-
|
|
1221
|
+
lastUpdated: "2026-09-26"
|
|
1112
1222
|
},
|
|
1113
1223
|
{
|
|
1114
1224
|
id: "vault",
|
|
@@ -1116,12 +1226,28 @@ var DOC_CATALOG = [
|
|
|
1116
1226
|
path: "/docs/api/vault",
|
|
1117
1227
|
summary: "Create collections with JSON Schema, query totals vs limit, ACLs, implicit tables, nested filters, identities vs M2M.",
|
|
1118
1228
|
embedded: VAULT_GUIDE,
|
|
1119
|
-
lastUpdated: "2026-09-
|
|
1229
|
+
lastUpdated: "2026-09-26"
|
|
1230
|
+
},
|
|
1231
|
+
{
|
|
1232
|
+
id: "feature-flags",
|
|
1233
|
+
title: "Feature Flags",
|
|
1234
|
+
path: "/docs/configure/feature-flags",
|
|
1235
|
+
summary: "Built-in per-environment feature flags (toggles / config values) \u2014 use these, not a Vault collection. gf flags ls|set|compare|promote. Apps read GET \u2026/flags/runtime: Shell apps with the end-user JWT + window.__GF_ENVIRONMENT_ID__ (starter-kit useFlag), Coderunners with gf m2m token + GROUNDFLOOR_ENVIRONMENT_ID. Default environment is dev.",
|
|
1236
|
+
embedded: FLAGS_GUIDE,
|
|
1237
|
+
lastUpdated: "2026-09-26"
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
id: "flags-api",
|
|
1241
|
+
title: "Feature flags API",
|
|
1242
|
+
path: "/docs/api/flags",
|
|
1243
|
+
summary: "REST reference for flags: list/get/put/delete per environment_id (omitted \u2192 workspace default, dev), compare, promote, runtime read. Key format, value_type validation, auth per method (M2M read-only), error codes.",
|
|
1244
|
+
embedded: FLAGS_GUIDE,
|
|
1245
|
+
lastUpdated: "2026-09-26"
|
|
1120
1246
|
},
|
|
1121
1247
|
{
|
|
1122
1248
|
id: "scheduled-jobs",
|
|
1123
1249
|
title: "Scheduled jobs",
|
|
1124
|
-
path: "/docs/
|
|
1250
|
+
path: "/docs/deploy/schedules",
|
|
1125
1251
|
summary: "workload_type=schedule plus cron. gf coderunner status shows type/schedule/last_job. Use Process Log, not a public URL.",
|
|
1126
1252
|
embedded: CODERUNNER_GUIDE,
|
|
1127
1253
|
lastUpdated: "2026-09-25"
|
|
@@ -1188,88 +1314,94 @@ function suggestCli(intent, args) {
|
|
|
1188
1314
|
return {
|
|
1189
1315
|
command: args?.cell === "stage" ? "gf login --stage" : args?.cell === "dev" ? "gf login --dev" : "gf login",
|
|
1190
1316
|
why: "Creates ~/.groundfloor session (auto-refresh). MCP reads this; do not paste JWTs into mcp.json.",
|
|
1191
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1317
|
+
docs: "https://docs.groundfloor.cloud/docs/developer-tools/cli"
|
|
1192
1318
|
};
|
|
1193
1319
|
case "switch_workspace":
|
|
1194
1320
|
return {
|
|
1195
1321
|
command: args?.workspace ? `gf workspaces use ${args.workspace}` : "gf workspaces && gf workspaces use <uuid>",
|
|
1196
1322
|
why: "Sets the default workspace for gf and MCP.",
|
|
1197
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1323
|
+
docs: "https://docs.groundfloor.cloud/docs/developer-tools/cli"
|
|
1198
1324
|
};
|
|
1199
1325
|
case "deploy":
|
|
1200
1326
|
return {
|
|
1201
1327
|
command: name ? `gf deploy -n ${name}${ws}` : `gf deploy${ws}`,
|
|
1202
1328
|
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.',
|
|
1203
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1329
|
+
docs: "https://docs.groundfloor.cloud/docs/deploy"
|
|
1204
1330
|
};
|
|
1205
1331
|
case "run":
|
|
1206
1332
|
return {
|
|
1207
1333
|
command: name ? `gf coderunner run -c ${name}${ws}` : `gf coderunner run -c <id-or-slug>${ws}`,
|
|
1208
1334
|
why: "Smoke-invoke a deployed function or job.",
|
|
1209
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1335
|
+
docs: "https://docs.groundfloor.cloud/docs/deploy"
|
|
1210
1336
|
};
|
|
1211
1337
|
case "status":
|
|
1212
1338
|
return {
|
|
1213
1339
|
command: name ? `gf coderunner status -c ${name}${ws}` : `gf coderunner ls${ws}`,
|
|
1214
1340
|
why: "Inspect build/deploy state.",
|
|
1215
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1341
|
+
docs: "https://docs.groundfloor.cloud/docs/deploy"
|
|
1216
1342
|
};
|
|
1217
1343
|
case "logs":
|
|
1218
1344
|
return {
|
|
1219
1345
|
command: name ? `gf coderunner logs -c ${name}${ws}` : `gf coderunner logs -c <id-or-slug>${ws}`,
|
|
1220
1346
|
why: "Process Log (stdout/stderr). gf deploy prints the last lines on failure; this command fetches more. runner_id accepts a coderunner id.",
|
|
1221
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1347
|
+
docs: "https://docs.groundfloor.cloud/docs/deploy"
|
|
1222
1348
|
};
|
|
1223
1349
|
case "init_app": {
|
|
1224
1350
|
const slug = args?.slug?.trim();
|
|
1225
1351
|
return {
|
|
1226
1352
|
command: slug ? `gf apps init --slug ${slug}` : "gf apps init --slug <portal-slug>",
|
|
1227
1353
|
why: "Download the official Shell starter-kit and stamp APP_ID. Never scaffold vite.config / App.tsx from memory. Never wrap App in BrowserRouter. Never zip dist/ or upload only remoteEntry.js.",
|
|
1228
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1354
|
+
docs: "https://docs.groundfloor.cloud/docs/apps/shell"
|
|
1229
1355
|
};
|
|
1230
1356
|
}
|
|
1231
1357
|
case "publish_app":
|
|
1232
1358
|
return {
|
|
1233
1359
|
command: args?.slug ? `gf apps init --slug ${args.slug} && cd ${args.slug} && npm install && npm run release && gf apps publish --path release.zip` : "gf apps init --slug <portal-slug> && cd <slug> && npm install && npm run release && gf apps publish --path release.zip",
|
|
1234
1360
|
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.",
|
|
1235
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1361
|
+
docs: "https://docs.groundfloor.cloud/docs/apps/shell"
|
|
1236
1362
|
};
|
|
1237
1363
|
case "environments":
|
|
1238
1364
|
return {
|
|
1239
1365
|
command: `gf environments ls${ws}`,
|
|
1240
1366
|
why: "List workspace environments (id, name, status) for secrets and deploy targeting.",
|
|
1241
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1367
|
+
docs: "https://docs.groundfloor.cloud/docs/developer-tools/cli"
|
|
1242
1368
|
};
|
|
1243
1369
|
case "cancel_deployment":
|
|
1244
1370
|
return {
|
|
1245
1371
|
command: name ? `gf coderunner cancel-deployment -c ${name}${ws}` : `gf coderunner cancel-deployment -c <id-or-slug>${ws}`,
|
|
1246
1372
|
why: "Delete the current deployment (or --deployment-id). Use this for a deploy stuck in deploying.",
|
|
1247
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1373
|
+
docs: "https://docs.groundfloor.cloud/docs/deploy"
|
|
1248
1374
|
};
|
|
1249
1375
|
case "secrets":
|
|
1250
1376
|
return {
|
|
1251
1377
|
command: `gf secrets ls${ws}`,
|
|
1252
1378
|
why: "Mutations: gf secrets set|get|rm. MCP only lists keys.",
|
|
1253
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1379
|
+
docs: "https://docs.groundfloor.cloud/docs/developer-tools/cli"
|
|
1380
|
+
};
|
|
1381
|
+
case "flags":
|
|
1382
|
+
return {
|
|
1383
|
+
command: `gf flags ls${ws}`,
|
|
1384
|
+
why: "Feature flags per environment. Mutations: gf flags set|rm|compare|promote (-e <id|name>). Apps read GET \u2026/flags/runtime (docs_get id feature-flags). Do not build flags in a Vault collection.",
|
|
1385
|
+
docs: "https://docs.groundfloor.cloud/docs/configure/feature-flags"
|
|
1254
1386
|
};
|
|
1255
1387
|
case "dataplane":
|
|
1256
1388
|
return {
|
|
1257
1389
|
command: `gf dataplane status${ws} # provision: gf dataplane provision`,
|
|
1258
1390
|
why: "Dataplane is required for vault, files, and secrets.",
|
|
1259
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1391
|
+
docs: "https://docs.groundfloor.cloud/docs/developer-tools/cli"
|
|
1260
1392
|
};
|
|
1261
1393
|
case "vault_token":
|
|
1262
1394
|
case "m2m_token":
|
|
1263
1395
|
return {
|
|
1264
1396
|
command: `gf m2m token${ws}`,
|
|
1265
1397
|
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.",
|
|
1266
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1398
|
+
docs: "https://docs.groundfloor.cloud/docs/access/m2m-tokens"
|
|
1267
1399
|
};
|
|
1268
1400
|
default:
|
|
1269
1401
|
return {
|
|
1270
1402
|
command: "gf --help",
|
|
1271
|
-
why: `Unknown intent "${intent}". Use login | switch_workspace | deploy | run | status | logs | environments | cancel_deployment | init_app | publish_app | secrets | dataplane | vault_token.`,
|
|
1272
|
-
docs: "https://docs.groundfloor.cloud/docs/
|
|
1403
|
+
why: `Unknown intent "${intent}". Use login | switch_workspace | deploy | run | status | logs | environments | cancel_deployment | init_app | publish_app | secrets | flags | dataplane | vault_token.`,
|
|
1404
|
+
docs: "https://docs.groundfloor.cloud/docs/developer-tools/cli"
|
|
1273
1405
|
};
|
|
1274
1406
|
}
|
|
1275
1407
|
}
|
|
@@ -1339,16 +1471,18 @@ server.tool(
|
|
|
1339
1471
|
);
|
|
1340
1472
|
server.tool(
|
|
1341
1473
|
"workspace_context",
|
|
1342
|
-
"Live context for the selected workspace: session, coderunners, apps, dataplane (access layer, not a database), databases_howto, suggested gf commands. Use docs_get id coderunner before deploying; id databases for data work; id css-and-styling for own CSS framework.",
|
|
1474
|
+
"Live context for the selected workspace: session, coderunners, apps, environments (with the default one), feature flags, dataplane (access layer, not a database), databases_howto, suggested gf commands. Use docs_get id coderunner before deploying; id databases for data work; id feature-flags for toggles/config; id css-and-styling for own CSS framework.",
|
|
1343
1475
|
{ workspace_id: wsId },
|
|
1344
1476
|
async ({ workspace_id }) => {
|
|
1345
1477
|
try {
|
|
1346
1478
|
const c = await cfg(workspace_id);
|
|
1347
1479
|
const claims = decodeJwt(c.token) ?? {};
|
|
1348
|
-
const [coderunners, apps, dataplane] = await Promise.all([
|
|
1480
|
+
const [coderunners, apps, dataplane, environments, flags] = await Promise.all([
|
|
1349
1481
|
listCoderunners(c.apiUrl, c.workspaceId),
|
|
1350
1482
|
listApps(c.apiUrl, c.workspaceId).catch(() => ({ apps: [] })),
|
|
1351
|
-
getDataplaneStatus(c.apiUrl, c.workspaceId).catch(() => null)
|
|
1483
|
+
getDataplaneStatus(c.apiUrl, c.workspaceId).catch(() => null),
|
|
1484
|
+
listWorkspaceEnvironments(c.apiUrl, c.workspaceId).catch(() => []),
|
|
1485
|
+
listFlags(c.apiUrl, c.workspaceId).catch(() => null)
|
|
1352
1486
|
]);
|
|
1353
1487
|
return text({
|
|
1354
1488
|
session: {
|
|
@@ -1370,6 +1504,21 @@ server.tool(
|
|
|
1370
1504
|
status: app.status
|
|
1371
1505
|
})),
|
|
1372
1506
|
dataplane,
|
|
1507
|
+
environments: environments.map((env) => ({
|
|
1508
|
+
id: env.id,
|
|
1509
|
+
name: env.name,
|
|
1510
|
+
status: env.status,
|
|
1511
|
+
default: flags ? env.id === flags.environment_id : void 0
|
|
1512
|
+
})),
|
|
1513
|
+
feature_flags_howto: {
|
|
1514
|
+
docs_get: "feature-flags",
|
|
1515
|
+
rule: "Groundfloor has built-in per-environment feature flags. Use them; never build a flags collection in Vault or read toggles from .env.",
|
|
1516
|
+
default_environment_id: flags?.environment_id ?? null,
|
|
1517
|
+
default_environment_flags: flags ? flags.flags.map((f) => ({ key: f.key, value_type: f.value_type, value: f.value })) : null,
|
|
1518
|
+
manage: "gf flags ls|get|set|rm|compare|promote -e <env id or name>. Omitting -e uses the default environment (dev).",
|
|
1519
|
+
shell_app: "Starter-kit src/lib/flags.ts: useFlag('key', fallback). Calls GET /v1/workspaces/{id}/flags/runtime?environment_id=window.__GF_ENVIRONMENT_ID__ with the Shell end-user JWT (needs a site role \u2192 workspace read).",
|
|
1520
|
+
coderunner: "GET \u2026/flags/runtime?environment_id=$GROUNDFLOOR_ENVIRONMENT_ID with an M2M token (gf m2m token). M2M is read-only on flags; workload-identity tokens are rejected."
|
|
1521
|
+
},
|
|
1373
1522
|
coderunner_howto: {
|
|
1374
1523
|
docs_get: "coderunner",
|
|
1375
1524
|
runtime_contract: "coderunner-runtime",
|
|
@@ -1393,10 +1542,10 @@ server.tool(
|
|
|
1393
1542
|
databases_howto: {
|
|
1394
1543
|
docs_get: "databases",
|
|
1395
1544
|
dataplane: "Dataplane is not a database. It is how Groundfloor talks to databases.",
|
|
1396
|
-
say_first: "You have
|
|
1545
|
+
say_first: "You have PostgreSQL ready to use through Dataplane \u2014 shared, platform-managed, already there, no deploy step. If you want your own dedicated database instead, deploy a dedicated PostgreSQL first.",
|
|
1397
1546
|
shared_postgres: 'Default for app data and Vault. Platform-managed, not workspace-owned \u2014 nothing to scale/backup/delete yourself. Pass engine "postgresql" explicitly when creating a collection.',
|
|
1398
|
-
|
|
1399
|
-
|
|
1547
|
+
deploy: "A dedicated PostgreSQL you own is what you can deploy today (portal Data \u2192 Databases).",
|
|
1548
|
+
engines: "PostgreSQL only, shared or dedicated. Do not offer ArangoDB, MongoDB, Redis, ClickHouse, Qdrant or other engines."
|
|
1400
1549
|
},
|
|
1401
1550
|
actions: {
|
|
1402
1551
|
deploy: suggestCli("deploy"),
|
|
@@ -1404,6 +1553,7 @@ server.tool(
|
|
|
1404
1553
|
run: suggestCli("run"),
|
|
1405
1554
|
logs: suggestCli("logs"),
|
|
1406
1555
|
environments: suggestCli("environments"),
|
|
1556
|
+
flags: suggestCli("flags"),
|
|
1407
1557
|
cancel_deployment: suggestCli("cancel_deployment"),
|
|
1408
1558
|
vault_token: suggestCli("m2m_token"),
|
|
1409
1559
|
init_app: suggestCli("init_app"),
|
|
@@ -1641,6 +1791,21 @@ server.tool(
|
|
|
1641
1791
|
}
|
|
1642
1792
|
}
|
|
1643
1793
|
);
|
|
1794
|
+
server.tool(
|
|
1795
|
+
"flags_list",
|
|
1796
|
+
"List feature flags and values in one environment (omit environment_id \u2192 workspace default, dev; response echoes the resolved id). To set/delete/promote, use `gf flags`. docs_get id feature-flags for runtime use.",
|
|
1797
|
+
{ workspace_id: wsId, environment_id: z.string().optional() },
|
|
1798
|
+
async (args) => {
|
|
1799
|
+
try {
|
|
1800
|
+
const c = await cfg(args.workspace_id);
|
|
1801
|
+
return text(
|
|
1802
|
+
await listFlags(c.apiUrl, c.workspaceId, args.environment_id)
|
|
1803
|
+
);
|
|
1804
|
+
} catch (e) {
|
|
1805
|
+
return errText(e);
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
);
|
|
1644
1809
|
server.tool(
|
|
1645
1810
|
"files_list",
|
|
1646
1811
|
"List workspace files (read-only). Upload/download with `gf files`.",
|
|
@@ -1674,7 +1839,7 @@ server.tool(
|
|
|
1674
1839
|
);
|
|
1675
1840
|
server.tool(
|
|
1676
1841
|
"dataplane_status",
|
|
1677
|
-
"Dataplane setup status (Dataplane is how Groundfloor talks to databases, not a database itself).
|
|
1842
|
+
"Dataplane setup status (Dataplane is how Groundfloor talks to databases, not a database itself). PostgreSQL (shared, platform-managed) is ready through it by default. Provision with `gf dataplane provision`.",
|
|
1678
1843
|
{ workspace_id: wsId },
|
|
1679
1844
|
async ({ workspace_id }) => {
|
|
1680
1845
|
try {
|
|
@@ -1744,6 +1909,7 @@ server.tool(
|
|
|
1744
1909
|
"init_app",
|
|
1745
1910
|
"publish_app",
|
|
1746
1911
|
"secrets",
|
|
1912
|
+
"flags",
|
|
1747
1913
|
"dataplane",
|
|
1748
1914
|
"vault_token",
|
|
1749
1915
|
"m2m_token"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@groundfloorcloud/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "Groundfloor MCP — inspect workspace state and docs; take actions with the gf CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"url": "git+ssh://git@bitbucket.org/codementeam/groundfloor-client-portal.git",
|
|
19
19
|
"directory": "packages/mcp"
|
|
20
20
|
},
|
|
21
|
-
"homepage": "https://docs.groundfloor.cloud/docs/
|
|
21
|
+
"homepage": "https://docs.groundfloor.cloud/docs/developer-tools/ai-agents",
|
|
22
22
|
"keywords": [
|
|
23
23
|
"groundfloor",
|
|
24
24
|
"mcp",
|