@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.
Files changed (2) hide show
  1. package/dist/index.js +237 -33
  2. 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
- - No public invoke URL. Debug with Process Log, not curl.
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
- ## M2M tokens (Vault and Files)
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 ArangoDB ready to use through Dataplane. If you want another
715
- database, deploy it first. You can use a deployed database through Dataplane,
716
- or connect to it on your own.
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
- - ArangoDB \u2014 shared, managed, already there. Default for app data and Vault.
721
- No deploy step. Query via Control Plane vault:
722
- POST /v1/workspaces/{id}/vault/collections/{name}/query
723
- - Postgres \u2014 what you can deploy today (portal Data \u2192 Databases). After it is
724
- ready, use it through Dataplane or with the connection secrets.
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 Postgres \u2192 Customer Portal Databases page, or
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
- ArangoDB ready through Dataplane; deploy Postgres if you want another
822
- database; use it through Dataplane or on your own (\`docs_get\` id
823
- \`databases\`). Local UI without live vault: \`npm run dev:fixtures\`.
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. ArangoDB is ready through Dataplane. Postgres you deploy first, then use through Dataplane or on your own.",
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: "0.1.7"
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 ArangoDB ready to use through Dataplane. If you want another database, deploy it first. You can use a deployed database through Dataplane, or connect to it on your own.",
1183
- arango: "Shared, managed, already there. Default for app data and Vault. No deploy step.",
1184
- deploy: "Postgres is what you can deploy today."
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). ArangoDB is ready through it. Provision with `gf dataplane provision`.",
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groundfloorcloud/mcp",
3
- "version": "0.1.8",
3
+ "version": "0.1.11",
4
4
  "description": "Groundfloor MCP — inspect workspace state and docs; take actions with the gf CLI.",
5
5
  "type": "module",
6
6
  "bin": {