@groundfloorcloud/mcp 0.1.8 → 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 +237 -33
- 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,18 +572,28 @@ 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
|
|
|
567
589
|
- Same as job, plus a cron expression at deploy:
|
|
568
590
|
\`gf deploy --workload-type schedule --schedule "<cron>"\`
|
|
569
591
|
(or \`groundfloor.json\` \`"schedule"\`).
|
|
570
|
-
-
|
|
592
|
+
- GET/list/status expose top-level \`workload_type\` and \`schedule\`.
|
|
593
|
+
\`gf coderunner status -c <slug>\` prints type, schedule, last_job.
|
|
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.
|
|
571
597
|
|
|
572
598
|
### Service (Deployment)
|
|
573
599
|
|
|
@@ -654,7 +680,18 @@ or customer env.
|
|
|
654
680
|
|
|
655
681
|
When the handler looks right locally, \`gf deploy\` the same tree.
|
|
656
682
|
|
|
657
|
-
##
|
|
683
|
+
## Secrets on deploy
|
|
684
|
+
|
|
685
|
+
Do not pass credential-shaped keys as \`--env KEY=VALUE\` (\`*_SECRET\`,
|
|
686
|
+
\`*_API_KEY\`, \`DATABASE_URL\`, \u2026). Control Plane returns **422**.
|
|
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\`.
|
|
693
|
+
|
|
694
|
+
## M2M tokens (Vault, Files, and Secrets)
|
|
658
695
|
|
|
659
696
|
New Coderunners cannot call Vault or Files until an M2M client is attached
|
|
660
697
|
and the workload is redeployed. Create the client in Portal **Administer \u2192
|
|
@@ -662,10 +699,33 @@ M2M tokens**, attach it on the Coderunner card, then deploy. v1 M2M is Team
|
|
|
662
699
|
Writer on that workspace (full Vault skip-ACL + Files). Grant site users on
|
|
663
700
|
**Administer \u2192 Access**. Never inject a Dataplane key.
|
|
664
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
|
+
|
|
665
725
|
## Agent actions
|
|
666
726
|
|
|
667
727
|
Inspect: \`workspace_context\`, \`docs_get\` id \`coderunner\` or \`coderunner-runtime\`, \`suggest_cli\`.
|
|
668
|
-
Act: \`gf deploy\`, \`gf coderunner run|status\`, \`gf m2m token\`. MCP does not deploy.
|
|
728
|
+
Act: \`gf deploy\`, \`gf coderunner run|status|logs\`, \`gf m2m token\`, \`gf identities ls|mint\`, \`gf api\`. MCP does not deploy.
|
|
669
729
|
`.trim();
|
|
670
730
|
|
|
671
731
|
// src/css-and-styling-guide.ts
|
|
@@ -711,30 +771,46 @@ Dataplane is not a database. It is how Groundfloor talks to databases.
|
|
|
711
771
|
When the user starts any data or database work, say this first. Do not mention
|
|
712
772
|
infrastructure internals (cluster operators, installers, and the like):
|
|
713
773
|
|
|
714
|
-
You have
|
|
715
|
-
|
|
716
|
-
|
|
774
|
+
You have Postgres ready to use through Dataplane \u2014 a shared, platform-managed
|
|
775
|
+
cluster, already there, no deploy step. If you want a different engine, or a
|
|
776
|
+
database that is entirely your own (own scaling, own backups schedule), you
|
|
777
|
+
can deploy one first.
|
|
717
778
|
|
|
718
779
|
## Options
|
|
719
780
|
|
|
720
|
-
-
|
|
721
|
-
No deploy step.
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
781
|
+
- Postgres (shared) \u2014 platform-managed, already there. Default for app data
|
|
782
|
+
and Vault. No deploy step. This is NOT a workspace-owned resource: it does
|
|
783
|
+
not appear on the customer Databases page, and there is nothing to scale,
|
|
784
|
+
back up, or delete yourself \u2014 it's offered, not provisioned. Query via
|
|
785
|
+
Control Plane vault: POST /v1/workspaces/{id}/vault/collections/{name}/query
|
|
786
|
+
- ArangoDB \u2014 also shared, managed, already there, no deploy step. Still fully
|
|
787
|
+
supported; just no longer the pre-selected engine for new collections.
|
|
788
|
+
- A dedicated database you deploy and own (Postgres, Redis, ClickHouse,
|
|
789
|
+
Qdrant) \u2014 portal Data \u2192 Databases, or
|
|
790
|
+
POST /v1/workspaces/{id}/managed-databases. Heavier than the shared
|
|
791
|
+
default: you own its scaling, backups, and lifecycle. Use this when you
|
|
792
|
+
need a tier/engine the shared default doesn't offer (Redis, ClickHouse,
|
|
793
|
+
Qdrant) or want a database isolated to this workspace.
|
|
725
794
|
- A database they already run \u2014 through Dataplane if they wire it, or direct.
|
|
726
795
|
|
|
727
796
|
Do not list other engines as available to deploy. Do not call Dataplane hosts
|
|
728
797
|
from apps or embed service keys.
|
|
729
798
|
|
|
799
|
+
## Creating a collection / table
|
|
800
|
+
|
|
801
|
+
Pass the engine explicitly \u2014 do not rely on Dataplane's default connector
|
|
802
|
+
resolution. POST /v1/workspaces/{id}/vault/collections with
|
|
803
|
+
\`"schema": {"engine": "postgresql", ...}\` for the shared default, or
|
|
804
|
+
\`"engine": "arangodb"\` to use ArangoDB instead.
|
|
805
|
+
|
|
730
806
|
## Paths
|
|
731
807
|
|
|
732
808
|
- Browse / edit rows \u2192 Data Vault (portal or vault APIs)
|
|
733
|
-
- Deploy
|
|
734
|
-
POST /v1/workspaces/{id}/managed-databases with engine postgres
|
|
809
|
+
- Deploy your own database \u2192 Customer Portal Databases page, or
|
|
810
|
+
POST /v1/workspaces/{id}/managed-databases with engine postgres|redis|clickhouse|qdrant
|
|
735
811
|
- Shell 403 / empty vault \u2192 collection Access for the site role
|
|
736
812
|
|
|
737
|
-
docs_get id databases. Human docs: /docs/customer-portal/databases
|
|
813
|
+
docs_get id databases. Human docs: /docs/customer-portal/databases and /docs/customer-portal/data-vault
|
|
738
814
|
`;
|
|
739
815
|
|
|
740
816
|
// src/design-standard-guide.ts
|
|
@@ -818,9 +894,11 @@ remoteEntry.js. Header logos: manifest \`theme.logoUrl\` (absolute https).
|
|
|
818
894
|
UI look: \`docs_get\` id \`design-standard\`. CSS: Tailwind by default;
|
|
819
895
|
own framework uses FederatedStyleRoot (Shadow DOM) \u2014 \`docs_get\` id
|
|
820
896
|
\`css-and-styling\`. Data: Dataplane is not a database. Say first: you have
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
897
|
+
Postgres (shared, platform-managed, no deploy step) ready through Dataplane
|
|
898
|
+
by default; ArangoDB is also ready the same way. Deploy your own dedicated
|
|
899
|
+
database only if you need a different engine or workspace-owned isolation
|
|
900
|
+
(\`docs_get\` id \`databases\`). Local UI without live vault:
|
|
901
|
+
\`npm run dev:fixtures\`.
|
|
824
902
|
|
|
825
903
|
## suggest_cli
|
|
826
904
|
|
|
@@ -828,6 +906,102 @@ database; use it through Dataplane or on your own (\`docs_get\` id
|
|
|
828
906
|
- publish_app \u2192 init + npm install + npm run release + gf apps publish --path release.zip
|
|
829
907
|
`;
|
|
830
908
|
|
|
909
|
+
// src/vault-guide.ts
|
|
910
|
+
var VAULT_GUIDE = `
|
|
911
|
+
# Data Vault collections
|
|
912
|
+
|
|
913
|
+
Vault is workspace data behind Control Plane
|
|
914
|
+
\`/v1/workspaces/{workspace_id}/vault/\u2026\`. Browser apps send the Shell JWT.
|
|
915
|
+
Coderunners use \`gf m2m token\` (preferred) or a workload-identity Vault JWT.
|
|
916
|
+
|
|
917
|
+
## Create a collection (JSON Schema)
|
|
918
|
+
|
|
919
|
+
POST \`/v1/workspaces/{id}/vault/collections\` with a **JSON Schema** object
|
|
920
|
+
(\`type: object\`, \`properties\`, optional \`required\`). A missing schema is a
|
|
921
|
+
**400** with a field error \u2014 not a 500.
|
|
922
|
+
|
|
923
|
+
Pass \`engine\` explicitly \u2014 don't rely on Dataplane's default connector.
|
|
924
|
+
\`"postgresql"\` is the platform default (shared, no deploy step);
|
|
925
|
+
\`"arangodb"\` is also available the same way.
|
|
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
|
+
|
|
931
|
+
Example:
|
|
932
|
+
|
|
933
|
+
\`\`\`json
|
|
934
|
+
{
|
|
935
|
+
"name": "properties",
|
|
936
|
+
"engine": "postgresql",
|
|
937
|
+
"schema": {
|
|
938
|
+
"type": "object",
|
|
939
|
+
"properties": {
|
|
940
|
+
"name": { "type": "string" },
|
|
941
|
+
"metadata": { "type": "object" }
|
|
942
|
+
},
|
|
943
|
+
"required": ["name"]
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
\`\`\`
|
|
947
|
+
|
|
948
|
+
Or use \`gf api -X POST /v1/workspaces/{workspace_id}/vault/collections --body '{...}'\`.
|
|
949
|
+
|
|
950
|
+
\`GET \u2026/vault/collections\` lists schema-registered collections. Implicit
|
|
951
|
+
tables created by the first \`POST \u2026/vault/{collection}\` appear when you pass
|
|
952
|
+
\`include_implicit=true\` (or after a schema create).
|
|
953
|
+
|
|
954
|
+
## Query totals
|
|
955
|
+
|
|
956
|
+
\`POST \u2026/vault/{collection}/query\` \`total\` is the **unpaged** match count.
|
|
957
|
+
\`limit\` only sizes \`records\`. Do not treat \`total === records.length\` as
|
|
958
|
+
the full table size.
|
|
959
|
+
|
|
960
|
+
## Filters
|
|
961
|
+
|
|
962
|
+
Top-level fields work in \`filter\`. Nested paths such as \`metadata.sector\`
|
|
963
|
+
are either supported by the connector or rejected with **400 unsupported
|
|
964
|
+
path** \u2014 never a silent empty page.
|
|
965
|
+
|
|
966
|
+
## ACLs
|
|
967
|
+
|
|
968
|
+
Grant site roles on **Administer \u2192 Access**. Workload identities get
|
|
969
|
+
collection grants via \`PUT \u2026/vault/collections/{name}/acl\`. M2M is Team
|
|
970
|
+
Writer (workspace-wide), not an Access subject.
|
|
971
|
+
|
|
972
|
+
## Identities vs M2M
|
|
973
|
+
|
|
974
|
+
- Unattended Coderunners: attach an M2M client, \`gf deploy\`, then
|
|
975
|
+
\`gf m2m token\`.
|
|
976
|
+
- Workload identity mint: \`gf identities mint --identity <id>\`. The **first**
|
|
977
|
+
mint returns \`refresh_secret\` once. Later mints omit it unless
|
|
978
|
+
\`--rotate-refresh\`. Prefer M2M for new workloads.
|
|
979
|
+
|
|
980
|
+
## Scheduled jobs
|
|
981
|
+
|
|
982
|
+
\`gf deploy --workload-type schedule --schedule "<cron>"\`.
|
|
983
|
+
\`gf coderunner status -c <slug>\` shows **type**, **schedule**, and **last_job**.
|
|
984
|
+
\`gf coderunner logs -c <slug>\` shows stdout. There is no public URL for
|
|
985
|
+
schedules.
|
|
986
|
+
|
|
987
|
+
## Secrets on deploy
|
|
988
|
+
|
|
989
|
+
Do not \`--env SENDGRID_SECRET=\u2026\`. That is **422**.
|
|
990
|
+
\`gf secrets set SENDGRID_SECRET\` then \`gf deploy --secret SENDGRID_SECRET\`.
|
|
991
|
+
`.trim();
|
|
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
|
+
|
|
831
1005
|
// src/docs.ts
|
|
832
1006
|
var DOCS_ORIGIN = "https://docs.groundfloor.cloud";
|
|
833
1007
|
var DOC_CATALOG = [
|
|
@@ -848,21 +1022,24 @@ var DOC_CATALOG = [
|
|
|
848
1022
|
title: "Coderunner",
|
|
849
1023
|
path: "/docs/customer-portal/coderunner",
|
|
850
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.",
|
|
851
|
-
embedded: CODERUNNER_GUIDE
|
|
1025
|
+
embedded: CODERUNNER_GUIDE,
|
|
1026
|
+
lastUpdated: "2026-09-23"
|
|
852
1027
|
},
|
|
853
1028
|
{
|
|
854
1029
|
id: "coderunner-runtime",
|
|
855
1030
|
title: "Coderunner runtime contract",
|
|
856
1031
|
path: "/docs/customer-portal/coderunner",
|
|
857
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.",
|
|
858
|
-
embedded: CODERUNNER_RUNTIME_CONTRACT
|
|
1033
|
+
embedded: CODERUNNER_RUNTIME_CONTRACT,
|
|
1034
|
+
lastUpdated: "2026-09-23"
|
|
859
1035
|
},
|
|
860
1036
|
{
|
|
861
1037
|
id: "coderunner-overview",
|
|
862
1038
|
title: "Coderunner overview",
|
|
863
1039
|
path: "/docs/integrations/coderunner/overview",
|
|
864
1040
|
summary: "Architecture and lifecycle. Prefer docs_get id coderunner for type usage, Dockerfile, and create prerequisites.",
|
|
865
|
-
embedded: CODERUNNER_GUIDE
|
|
1041
|
+
embedded: CODERUNNER_GUIDE,
|
|
1042
|
+
lastUpdated: "2026-09-23"
|
|
866
1043
|
},
|
|
867
1044
|
{
|
|
868
1045
|
id: "authentication",
|
|
@@ -893,28 +1070,48 @@ var DOC_CATALOG = [
|
|
|
893
1070
|
title: "Shell federated apps",
|
|
894
1071
|
path: "/docs/integrations/shell",
|
|
895
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.",
|
|
896
|
-
embedded: SHELL_APP_GUIDE
|
|
1073
|
+
embedded: SHELL_APP_GUIDE,
|
|
1074
|
+
lastUpdated: "2026-09-22"
|
|
897
1075
|
},
|
|
898
1076
|
{
|
|
899
1077
|
id: "design-standard",
|
|
900
1078
|
title: "Shell app design standard",
|
|
901
1079
|
path: "/docs/integrations/shell/design-standard",
|
|
902
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.",
|
|
903
|
-
embedded: DESIGN_STANDARD_GUIDE
|
|
1081
|
+
embedded: DESIGN_STANDARD_GUIDE,
|
|
1082
|
+
lastUpdated: "2026-09-04"
|
|
904
1083
|
},
|
|
905
1084
|
{
|
|
906
1085
|
id: "css-and-styling",
|
|
907
1086
|
title: "CSS and styling",
|
|
908
1087
|
path: "/docs/integrations/shell/css-and-styling",
|
|
909
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.",
|
|
910
|
-
embedded: CSS_AND_STYLING_GUIDE
|
|
1089
|
+
embedded: CSS_AND_STYLING_GUIDE,
|
|
1090
|
+
lastUpdated: "2026-09-04"
|
|
911
1091
|
},
|
|
912
1092
|
{
|
|
913
1093
|
id: "databases",
|
|
914
1094
|
title: "Databases",
|
|
915
1095
|
path: "/docs/customer-portal/databases",
|
|
916
|
-
summary: "Dataplane is not a database.
|
|
917
|
-
embedded: DATABASES_GUIDE
|
|
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.",
|
|
1097
|
+
embedded: DATABASES_GUIDE,
|
|
1098
|
+
lastUpdated: "2026-09-22"
|
|
1099
|
+
},
|
|
1100
|
+
{
|
|
1101
|
+
id: "vault",
|
|
1102
|
+
title: "Data Vault",
|
|
1103
|
+
path: "/docs/api/vault",
|
|
1104
|
+
summary: "Create collections with JSON Schema, query totals vs limit, ACLs, implicit tables, nested filters, identities vs M2M.",
|
|
1105
|
+
embedded: VAULT_GUIDE,
|
|
1106
|
+
lastUpdated: "2026-09-22"
|
|
1107
|
+
},
|
|
1108
|
+
{
|
|
1109
|
+
id: "scheduled-jobs",
|
|
1110
|
+
title: "Scheduled jobs",
|
|
1111
|
+
path: "/docs/customer-portal/scheduled-jobs",
|
|
1112
|
+
summary: "workload_type=schedule plus cron. gf coderunner status shows type/schedule/last_job. Use Process Log, not a public URL.",
|
|
1113
|
+
embedded: CODERUNNER_GUIDE,
|
|
1114
|
+
lastUpdated: "2026-09-23"
|
|
918
1115
|
}
|
|
919
1116
|
];
|
|
920
1117
|
function docUrl(entry) {
|
|
@@ -941,7 +1138,9 @@ async function fetchDocPage(entry) {
|
|
|
941
1138
|
title: entry.title,
|
|
942
1139
|
text: entry.embedded.trim(),
|
|
943
1140
|
truncated: false,
|
|
944
|
-
source: "embedded"
|
|
1141
|
+
source: "embedded",
|
|
1142
|
+
lastUpdated: entry.lastUpdated ?? null,
|
|
1143
|
+
mcpVersion: GF_MCP_VERSION
|
|
945
1144
|
};
|
|
946
1145
|
}
|
|
947
1146
|
const res = await fetch(url, {
|
|
@@ -961,7 +1160,9 @@ async function fetchDocPage(entry) {
|
|
|
961
1160
|
title: entry.title,
|
|
962
1161
|
text: body,
|
|
963
1162
|
truncated,
|
|
964
|
-
source: "docs.groundfloor.cloud"
|
|
1163
|
+
source: "docs.groundfloor.cloud",
|
|
1164
|
+
lastUpdated: null,
|
|
1165
|
+
mcpVersion: GF_MCP_VERSION
|
|
965
1166
|
};
|
|
966
1167
|
}
|
|
967
1168
|
|
|
@@ -1098,7 +1299,7 @@ async function resolveCoderunnerId(apiUrl, workspaceId, idOrSlug) {
|
|
|
1098
1299
|
}
|
|
1099
1300
|
var server = new McpServer({
|
|
1100
1301
|
name: "groundfloor",
|
|
1101
|
-
version:
|
|
1302
|
+
version: GF_MCP_VERSION
|
|
1102
1303
|
});
|
|
1103
1304
|
server.tool(
|
|
1104
1305
|
"whoami",
|
|
@@ -1179,9 +1380,10 @@ server.tool(
|
|
|
1179
1380
|
databases_howto: {
|
|
1180
1381
|
docs_get: "databases",
|
|
1181
1382
|
dataplane: "Dataplane is not a database. It is how Groundfloor talks to databases.",
|
|
1182
|
-
say_first: "You have
|
|
1183
|
-
|
|
1184
|
-
|
|
1383
|
+
say_first: "You have Postgres ready to use through Dataplane \u2014 shared, platform-managed, already there, no deploy step. ArangoDB is also available the same way. If you want your own dedicated database instead, deploy it first.",
|
|
1384
|
+
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.',
|
|
1385
|
+
arango: "Also shared, managed, already there, no deploy step. Still fully supported; just no longer pre-selected.",
|
|
1386
|
+
deploy: "A dedicated Postgres/Redis/ClickHouse/Qdrant you own is what you can deploy today (portal Data \u2192 Databases)."
|
|
1185
1387
|
},
|
|
1186
1388
|
actions: {
|
|
1187
1389
|
deploy: suggestCli("deploy"),
|
|
@@ -1459,7 +1661,7 @@ server.tool(
|
|
|
1459
1661
|
);
|
|
1460
1662
|
server.tool(
|
|
1461
1663
|
"dataplane_status",
|
|
1462
|
-
"Dataplane setup status (Dataplane is how Groundfloor talks to databases, not a database itself).
|
|
1664
|
+
"Dataplane setup status (Dataplane is how Groundfloor talks to databases, not a database itself). Postgres (shared, platform-managed) is ready through it by default; ArangoDB is also ready. Provision with `gf dataplane provision`.",
|
|
1463
1665
|
{ workspace_id: wsId },
|
|
1464
1666
|
async ({ workspace_id }) => {
|
|
1465
1667
|
try {
|
|
@@ -1478,11 +1680,13 @@ server.tool(
|
|
|
1478
1680
|
const hits = findDoc(query ?? "");
|
|
1479
1681
|
return text({
|
|
1480
1682
|
origin: "https://docs.groundfloor.cloud",
|
|
1683
|
+
mcpVersion: GF_MCP_VERSION,
|
|
1481
1684
|
docs: hits.map((d) => ({
|
|
1482
1685
|
id: d.id,
|
|
1483
1686
|
title: d.title,
|
|
1484
1687
|
url: `https://docs.groundfloor.cloud${d.path}`,
|
|
1485
|
-
summary: d.summary
|
|
1688
|
+
summary: d.summary,
|
|
1689
|
+
lastUpdated: d.lastUpdated ?? null
|
|
1486
1690
|
}))
|
|
1487
1691
|
});
|
|
1488
1692
|
}
|