@groundfloorcloud/mcp 0.1.7 → 0.1.9

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 (3) hide show
  1. package/README.md +4 -4
  2. package/dist/index.js +229 -47
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -74,8 +74,8 @@ The `command` must be your Node (from `which node`), not `npx` and not Cursor’
74
74
  | `coderunner_cancel_deployment` | Delete current (or given) deployment |
75
75
  | `apps_list` / `apps_get` | Inspect product Apps |
76
76
  | `secrets_list` / `files_list` / `domains_list` / `dataplane_status` | Inspect (no secrets values) |
77
- | `docs_list` / `docs_get` | Product docs (`coderunner`, `shell`, `design-standard`, `css-and-styling`, `databases` are embedded how-tos) |
78
- | `suggest_cli` | Command to run: login, deploy, init_app, publish_app, … |
77
+ | `docs_list` / `docs_get` | Product docs (`coderunner`, `shell`, `design-standard`, `css-and-styling`, `databases` are embedded; `access` and `m2m` are live pages) |
78
+ | `suggest_cli` | Command to run: login, deploy, init_app, publish_app, m2m_token, … |
79
79
 
80
80
  Never create `app_kind=coderunner`. Deploy with `gf deploy`.
81
81
 
@@ -91,10 +91,10 @@ is ready through Dataplane; Postgres is what you can deploy today.
91
91
  `coderunner-overview`). That page covers:
92
92
 
93
93
  - Types: `function`, `job`, `schedule`, `service` (**also called Deployment**)
94
- - **Authentication must be active** before creating a coderunner
94
+ - App authentication is optional (end-user login); not required to create a coderunner
95
95
  - **Dockerfile is required** for `service` / Deployment
96
96
  - Runtime contract: Node `scripts.start`, listen on `PORT`/8080, bind `0.0.0.0` (`docs_get` id `coderunner-runtime`)
97
- - Local development against live vault/files/secrets (`gf env` + `gf token`)
97
+ - Local development against live vault/files/secrets (`gf env`; as the workload use `gf m2m token`, not `gf token`)
98
98
 
99
99
  `workspace_context` includes a `coderunner_howto` summary so agents see this
100
100
  without an extra fetch.
package/dist/index.js CHANGED
@@ -169,11 +169,31 @@ var CpError = class extends Error {
169
169
  }
170
170
  status;
171
171
  };
172
+ function formatCpErrorDetail(detail, fallback) {
173
+ if (typeof detail === "string" && detail.trim()) return detail.trim();
174
+ if (detail && typeof detail === "object") {
175
+ const obj = detail;
176
+ if (typeof obj.message === "string" && obj.message.trim()) {
177
+ return obj.message.trim();
178
+ }
179
+ if (typeof obj.detail === "string" && obj.detail.trim()) {
180
+ return obj.detail.trim();
181
+ }
182
+ try {
183
+ return JSON.stringify(detail);
184
+ } catch {
185
+ return fallback;
186
+ }
187
+ }
188
+ return fallback;
189
+ }
172
190
  async function parseError(res) {
173
191
  let detail = res.statusText;
174
192
  try {
175
193
  const body = await res.json();
176
- if (body?.detail) detail = String(body.detail);
194
+ if (body?.detail !== void 0) {
195
+ detail = formatCpErrorDetail(body.detail, res.statusText);
196
+ }
177
197
  } catch {
178
198
  }
179
199
  return `${res.status} ${detail}`;
@@ -504,13 +524,11 @@ Also \`docs_get\` id \`coderunner-runtime\`.
504
524
 
505
525
  ## Prerequisites (do these before create/deploy)
506
526
 
507
- 1. **Workspace Authentication is required** before creating a coderunner.
508
- Portal \u2192 Administer \u2192 Authentication \u2192 set mode to \`groundfloor\` (or
509
- \`external\` with an issuer) and wait until the realm is **active**.
510
- Code Runner JWTs use the workspace site issuer. Mode \`none\` cannot mint
511
- that token \u2014 create/deploy fails with "requires the workspace site issuer".
512
- 2. \`gf login\` (\`--stage\` / \`--dev\` as needed) and \`gf workspaces use <uuid>\`.
513
- 3. Dataplane for vault/files/secrets: \`gf dataplane provision\` if those APIs
527
+ 1. \`gf login\` (\`--stage\` / \`--dev\` as needed) and \`gf workspaces use <uuid>\`.
528
+ Team **write** can create Coderunners without App authentication. Site auth
529
+ (Groundfloor/external) is only for end-user login. Mode \`none\` mints
530
+ management JWTs against Portal JWKS (\`GET /v1/public/jwks.json\`).
531
+ 2. Dataplane for vault/files: \`gf dataplane provision\` if those APIs
514
532
  are needed (local live data or the deployed workload).
515
533
 
516
534
  ## Workload types
@@ -549,7 +567,9 @@ Pick **one** type per coderunner. Changing type later means a new coderunner.
549
567
  - Same as job, plus a cron expression at deploy:
550
568
  \`gf deploy --workload-type schedule --schedule "<cron>"\`
551
569
  (or \`groundfloor.json\` \`"schedule"\`).
552
- - No public invoke URL. Debug with Process Log, not curl.
570
+ - GET/list/status expose top-level \`workload_type\` and \`schedule\`.
571
+ \`gf coderunner status -c <slug>\` prints type, schedule, last_job.
572
+ - No public invoke URL. Debug with \`gf coderunner logs\`, not curl.
553
573
 
554
574
  ### Service (Deployment)
555
575
 
@@ -613,21 +633,47 @@ curl -sS -X POST http://127.0.0.1:8080/ -H 'Content-Type: application/json' \\
613
633
 
614
634
  Live vault / files / secrets from the laptop:
615
635
 
636
+ \`gf token\` is a **builder** credential. Use it for operator Vault. To call
637
+ Vault and Files as a Coderunner does, use an M2M client and \`gf m2m token\`.
638
+
616
639
  \`\`\`bash
640
+ # Builder token:
617
641
  curl -sS -H "Authorization: Bearer $(gf token)" \\
618
642
  "$CONTROLPLANE_URL/v1/workspaces/$GROUNDFLOOR_WORKSPACE_ID/vault/collections"
643
+
644
+ # M2M (same class as an attached Coderunner):
645
+ curl -sS -H "Authorization: Bearer $(gf m2m token)" \\
646
+ "$CONTROLPLANE_URL/v1/workspaces/$GROUNDFLOOR_WORKSPACE_ID/vault/collections"
647
+ curl -sS -H "Authorization: Bearer $(gf m2m token)" \\
648
+ "$CONTROLPLANE_URL/v1/workspaces/$GROUNDFLOOR_WORKSPACE_ID/files"
619
649
  \`\`\`
620
650
 
621
- In app code, use \`CONTROLPLANE_URL\` + Bearer (\`gf token\` locally;
622
- injected env / workspace secrets after \`gf deploy\`). Never put
623
- \`DATAPLANE_SERVICE_API_KEY\` in a browser bundle.
651
+ In app code, use \`CONTROLPLANE_URL\` + Bearer from
652
+ \`POST \u2026/m2m/token\` (\`gf m2m token\` locally; injected
653
+ \`GROUNDFLOOR_M2M_CLIENT_ID\` / \`GROUNDFLOOR_M2M_CLIENT_SECRET\` after
654
+ \`gf deploy\`). Never put \`DATAPLANE_SERVICE_API_KEY\` in a browser bundle
655
+ or customer env.
624
656
 
625
657
  When the handler looks right locally, \`gf deploy\` the same tree.
626
658
 
659
+ ## Secrets on deploy
660
+
661
+ Do not pass credential-shaped keys as \`--env KEY=VALUE\` (\`*_SECRET\`,
662
+ \`*_API_KEY\`, \`DATABASE_URL\`, \u2026). Control Plane returns **422**.
663
+ \`gf secrets set KEY\` then \`gf deploy --secret KEY\` (inject by reference).
664
+
665
+ ## M2M tokens (Vault and Files)
666
+
667
+ New Coderunners cannot call Vault or Files until an M2M client is attached
668
+ and the workload is redeployed. Create the client in Portal **Administer \u2192
669
+ M2M tokens**, attach it on the Coderunner card, then deploy. v1 M2M is Team
670
+ Writer on that workspace (full Vault skip-ACL + Files). Grant site users on
671
+ **Administer \u2192 Access**. Never inject a Dataplane key.
672
+
627
673
  ## Agent actions
628
674
 
629
675
  Inspect: \`workspace_context\`, \`docs_get\` id \`coderunner\` or \`coderunner-runtime\`, \`suggest_cli\`.
630
- Act: \`gf deploy\`, \`gf coderunner run|status\`. MCP does not deploy.
676
+ Act: \`gf deploy\`, \`gf coderunner run|status|logs\`, \`gf m2m token\`, \`gf identities ls|mint\`, \`gf api\`. MCP does not deploy.
631
677
  `.trim();
632
678
 
633
679
  // src/css-and-styling-guide.ts
@@ -673,30 +719,46 @@ Dataplane is not a database. It is how Groundfloor talks to databases.
673
719
  When the user starts any data or database work, say this first. Do not mention
674
720
  infrastructure internals (cluster operators, installers, and the like):
675
721
 
676
- You have ArangoDB ready to use through Dataplane. If you want another
677
- database, deploy it first. You can use a deployed database through Dataplane,
678
- or connect to it on your own.
722
+ You have Postgres ready to use through Dataplane \u2014 a shared, platform-managed
723
+ cluster, already there, no deploy step. If you want a different engine, or a
724
+ database that is entirely your own (own scaling, own backups schedule), you
725
+ can deploy one first.
679
726
 
680
727
  ## Options
681
728
 
682
- - ArangoDB \u2014 shared, managed, already there. Default for app data and Vault.
683
- No deploy step. Query via Control Plane vault:
684
- POST /v1/workspaces/{id}/vault/collections/{name}/query
685
- - Postgres \u2014 what you can deploy today (portal Data \u2192 Databases). After it is
686
- ready, use it through Dataplane or with the connection secrets.
729
+ - Postgres (shared) \u2014 platform-managed, already there. Default for app data
730
+ and Vault. No deploy step. This is NOT a workspace-owned resource: it does
731
+ not appear on the customer Databases page, and there is nothing to scale,
732
+ back up, or delete yourself \u2014 it's offered, not provisioned. Query via
733
+ Control Plane vault: POST /v1/workspaces/{id}/vault/collections/{name}/query
734
+ - ArangoDB \u2014 also shared, managed, already there, no deploy step. Still fully
735
+ supported; just no longer the pre-selected engine for new collections.
736
+ - A dedicated database you deploy and own (Postgres, Redis, ClickHouse,
737
+ Qdrant) \u2014 portal Data \u2192 Databases, or
738
+ POST /v1/workspaces/{id}/managed-databases. Heavier than the shared
739
+ default: you own its scaling, backups, and lifecycle. Use this when you
740
+ need a tier/engine the shared default doesn't offer (Redis, ClickHouse,
741
+ Qdrant) or want a database isolated to this workspace.
687
742
  - A database they already run \u2014 through Dataplane if they wire it, or direct.
688
743
 
689
744
  Do not list other engines as available to deploy. Do not call Dataplane hosts
690
745
  from apps or embed service keys.
691
746
 
747
+ ## Creating a collection / table
748
+
749
+ Pass the engine explicitly \u2014 do not rely on Dataplane's default connector
750
+ resolution. POST /v1/workspaces/{id}/vault/collections with
751
+ \`"schema": {"engine": "postgresql", ...}\` for the shared default, or
752
+ \`"engine": "arangodb"\` to use ArangoDB instead.
753
+
692
754
  ## Paths
693
755
 
694
756
  - Browse / edit rows \u2192 Data Vault (portal or vault APIs)
695
- - Deploy Postgres \u2192 Customer Portal Databases page, or
696
- POST /v1/workspaces/{id}/managed-databases with engine postgres
757
+ - Deploy your own database \u2192 Customer Portal Databases page, or
758
+ POST /v1/workspaces/{id}/managed-databases with engine postgres|redis|clickhouse|qdrant
697
759
  - Shell 403 / empty vault \u2192 collection Access for the site role
698
760
 
699
- docs_get id databases. Human docs: /docs/customer-portal/databases
761
+ docs_get id databases. Human docs: /docs/customer-portal/databases and /docs/customer-portal/data-vault
700
762
  `;
701
763
 
702
764
  // src/design-standard-guide.ts
@@ -771,17 +833,20 @@ gf apps publish --path release.zip
771
833
  \`\`\`
772
834
 
773
835
  \`npm run release\` packs **all** of dist/assets (remoteEntry.js + hashed
774
- \`__federation_*.js\` + CSS) at the zip root. Do not zip \`dist/\`. Do not
775
- upload a lone \`remoteEntry.js\`. \`gf apps publish\` rejects incomplete zips.
836
+ \`__federation_*.js\` + CSS) at the zip root and rewrites \`./assets/\` imports
837
+ in remoteEntry.js. Do not zip \`dist/\`. Do not upload a lone \`remoteEntry.js\`.
838
+ \`gf apps publish\` rejects incomplete zips.
776
839
 
777
840
  Production builds use Vite \`base: './'\` so imported images resolve next to
778
841
  remoteEntry.js. Header logos: manifest \`theme.logoUrl\` (absolute https).
779
842
  UI look: \`docs_get\` id \`design-standard\`. CSS: Tailwind by default;
780
843
  own framework uses FederatedStyleRoot (Shadow DOM) \u2014 \`docs_get\` id
781
844
  \`css-and-styling\`. Data: Dataplane is not a database. Say first: you have
782
- ArangoDB ready through Dataplane; deploy Postgres if you want another
783
- database; use it through Dataplane or on your own (\`docs_get\` id
784
- \`databases\`). Local UI without live vault: \`npm run dev:fixtures\`.
845
+ Postgres (shared, platform-managed, no deploy step) ready through Dataplane
846
+ by default; ArangoDB is also ready the same way. Deploy your own dedicated
847
+ database only if you need a different engine or workspace-owned isolation
848
+ (\`docs_get\` id \`databases\`). Local UI without live vault:
849
+ \`npm run dev:fixtures\`.
785
850
 
786
851
  ## suggest_cli
787
852
 
@@ -789,6 +854,86 @@ database; use it through Dataplane or on your own (\`docs_get\` id
789
854
  - publish_app \u2192 init + npm install + npm run release + gf apps publish --path release.zip
790
855
  `;
791
856
 
857
+ // src/vault-guide.ts
858
+ var VAULT_GUIDE = `
859
+ # Data Vault collections
860
+
861
+ Vault is workspace data behind Control Plane
862
+ \`/v1/workspaces/{workspace_id}/vault/\u2026\`. Browser apps send the Shell JWT.
863
+ Coderunners use \`gf m2m token\` (preferred) or a workload-identity Vault JWT.
864
+
865
+ ## Create a collection (JSON Schema)
866
+
867
+ POST \`/v1/workspaces/{id}/vault/collections\` with a **JSON Schema** object
868
+ (\`type: object\`, \`properties\`, optional \`required\`). A missing schema is a
869
+ **400** with a field error \u2014 not a 500.
870
+
871
+ Pass \`engine\` explicitly \u2014 don't rely on Dataplane's default connector.
872
+ \`"postgresql"\` is the platform default (shared, no deploy step);
873
+ \`"arangodb"\` is also available the same way.
874
+
875
+ Example:
876
+
877
+ \`\`\`json
878
+ {
879
+ "name": "properties",
880
+ "engine": "postgresql",
881
+ "schema": {
882
+ "type": "object",
883
+ "properties": {
884
+ "name": { "type": "string" },
885
+ "metadata": { "type": "object" }
886
+ },
887
+ "required": ["name"]
888
+ }
889
+ }
890
+ \`\`\`
891
+
892
+ Or use \`gf api -X POST /v1/workspaces/{workspace_id}/vault/collections --body '{...}'\`.
893
+
894
+ \`GET \u2026/vault/collections\` lists schema-registered collections. Implicit
895
+ tables created by the first \`POST \u2026/vault/{collection}\` appear when you pass
896
+ \`include_implicit=true\` (or after a schema create).
897
+
898
+ ## Query totals
899
+
900
+ \`POST \u2026/vault/{collection}/query\` \`total\` is the **unpaged** match count.
901
+ \`limit\` only sizes \`records\`. Do not treat \`total === records.length\` as
902
+ the full table size.
903
+
904
+ ## Filters
905
+
906
+ Top-level fields work in \`filter\`. Nested paths such as \`metadata.sector\`
907
+ are either supported by the connector or rejected with **400 unsupported
908
+ path** \u2014 never a silent empty page.
909
+
910
+ ## ACLs
911
+
912
+ Grant site roles on **Administer \u2192 Access**. Workload identities get
913
+ collection grants via \`PUT \u2026/vault/collections/{name}/acl\`. M2M is Team
914
+ Writer (workspace-wide), not an Access subject.
915
+
916
+ ## Identities vs M2M
917
+
918
+ - Unattended Coderunners: attach an M2M client, \`gf deploy\`, then
919
+ \`gf m2m token\`.
920
+ - Workload identity mint: \`gf identities mint --identity <id>\`. The **first**
921
+ mint returns \`refresh_secret\` once. Later mints omit it unless
922
+ \`--rotate-refresh\`. Prefer M2M for new workloads.
923
+
924
+ ## Scheduled jobs
925
+
926
+ \`gf deploy --workload-type schedule --schedule "<cron>"\`.
927
+ \`gf coderunner status -c <slug>\` shows **type**, **schedule**, and **last_job**.
928
+ \`gf coderunner logs -c <slug>\` shows stdout. There is no public URL for
929
+ schedules.
930
+
931
+ ## Secrets on deploy
932
+
933
+ Do not \`--env SENDGRID_SECRET=\u2026\`. That is **422**.
934
+ \`gf secrets set SENDGRID_SECRET\` then \`gf deploy --secret SENDGRID_SECRET\`.
935
+ `.trim();
936
+
792
937
  // src/docs.ts
793
938
  var DOCS_ORIGIN = "https://docs.groundfloor.cloud";
794
939
  var DOC_CATALOG = [
@@ -796,19 +941,19 @@ var DOC_CATALOG = [
796
941
  id: "agents",
797
942
  title: "Deploy with agents",
798
943
  path: "/docs/customer-portal/agents",
799
- summary: "How agents should deploy Coderunner workloads and init/publish Shell apps with gf / MCP. Enable workspace Authentication before create. Service (Deployment) requires a Dockerfile. Shell apps: gf apps init, never invent App.tsx."
944
+ summary: "How agents should deploy Coderunner workloads and init/publish Shell apps with gf / MCP. App authentication is optional (end-user login). Service (Deployment) requires a Dockerfile. Shell apps: gf apps init, never invent App.tsx."
800
945
  },
801
946
  {
802
947
  id: "developers",
803
948
  title: "Developers (gf CLI)",
804
949
  path: "/docs/customer-portal/developers",
805
- summary: "gf login, workspaces, deploy, secrets, files, apps. Coderunner types: function, job, schedule, service (also called Deployment)."
950
+ summary: "gf login, workspaces, deploy, secrets, files, apps, gf m2m token. Coderunner types: function, job, schedule, service (also called Deployment). App authentication optional."
806
951
  },
807
952
  {
808
953
  id: "coderunner",
809
954
  title: "Coderunner",
810
955
  path: "/docs/customer-portal/coderunner",
811
- summary: "Workload types (function, job, schedule, service/Deployment), runtime contract (scripts.start, 0.0.0.0:8080), Dockerfile for services, Authentication before create, local live data, gf deploy.",
956
+ summary: "Workload types (function, job, schedule, service/Deployment), runtime contract (scripts.start, 0.0.0.0:8080), Dockerfile for services, Coderunner identities for Vault, App authentication optional, local live data, gf deploy.",
812
957
  embedded: CODERUNNER_GUIDE
813
958
  },
814
959
  {
@@ -822,14 +967,26 @@ var DOC_CATALOG = [
822
967
  id: "coderunner-overview",
823
968
  title: "Coderunner overview",
824
969
  path: "/docs/integrations/coderunner/overview",
825
- summary: "Architecture and lifecycle. Prefer docs_get id coderunner for type usage, Dockerfile, and auth prerequisites.",
970
+ summary: "Architecture and lifecycle. Prefer docs_get id coderunner for type usage, Dockerfile, and create prerequisites.",
826
971
  embedded: CODERUNNER_GUIDE
827
972
  },
828
973
  {
829
974
  id: "authentication",
830
975
  title: "Workspace Authentication",
831
976
  path: "/docs/customer-portal/authentication",
832
- summary: "Workspace site auth (Groundfloor or external) must be active before creating a Coderunner. Separate from portal Team."
977
+ 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."
978
+ },
979
+ {
980
+ id: "access",
981
+ title: "Access",
982
+ path: "/docs/customer-portal/access",
983
+ 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."
984
+ },
985
+ {
986
+ id: "m2m",
987
+ title: "M2M tokens",
988
+ path: "/docs/customer-portal/m2m-tokens",
989
+ summary: "Confidential client secret \u2192 short Control Plane JWT (typ=m2m). Attach on Coderunner or gf m2m token. Never DATAPLANE_SERVICE_API_KEY. v1 is Team Writer, no collection ACL."
833
990
  },
834
991
  {
835
992
  id: "api-authentication",
@@ -862,8 +1019,22 @@ var DOC_CATALOG = [
862
1019
  id: "databases",
863
1020
  title: "Databases",
864
1021
  path: "/docs/customer-portal/databases",
865
- summary: "Dataplane is not a database. ArangoDB is ready through Dataplane. Postgres you deploy first, then use through Dataplane or on your own.",
1022
+ 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.",
866
1023
  embedded: DATABASES_GUIDE
1024
+ },
1025
+ {
1026
+ id: "vault",
1027
+ title: "Data Vault",
1028
+ path: "/docs/api/vault",
1029
+ summary: "Create collections with JSON Schema, query totals vs limit, ACLs, implicit tables, nested filters, identities vs M2M.",
1030
+ embedded: VAULT_GUIDE
1031
+ },
1032
+ {
1033
+ id: "scheduled-jobs",
1034
+ title: "Scheduled jobs",
1035
+ path: "/docs/customer-portal/scheduled-jobs",
1036
+ 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
867
1038
  }
868
1039
  ];
869
1040
  function docUrl(entry) {
@@ -934,7 +1105,7 @@ function suggestCli(intent, args) {
934
1105
  case "deploy":
935
1106
  return {
936
1107
  command: name ? `gf deploy -n ${name}${ws}` : `gf deploy${ws}`,
937
- why: 'Package the current (or --path) folder and deploy as a Coderunner. Workspace Authentication (groundfloor/external) must already be active. 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.',
1108
+ why: 'Package the current (or --path) folder and deploy as a Coderunner. App authentication is optional (end-user login only). workloadType function|job|schedule|service (service = Deployment; requires a Dockerfile). Schedules need --schedule "<cron>" or groundfloor.json schedule. Node bootstrap: scripts.start, listen PORT||8080, bind 0.0.0.0. Do not create an App for this.',
938
1109
  docs: "https://docs.groundfloor.cloud/docs/customer-portal/coderunner"
939
1110
  };
940
1111
  case "run":
@@ -993,10 +1164,17 @@ function suggestCli(intent, args) {
993
1164
  why: "Dataplane is required for vault, files, and secrets.",
994
1165
  docs: "https://docs.groundfloor.cloud/docs/customer-portal/developers"
995
1166
  };
1167
+ case "vault_token":
1168
+ case "m2m_token":
1169
+ return {
1170
+ command: `gf m2m token${ws}`,
1171
+ 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.",
1172
+ docs: "https://docs.groundfloor.cloud/docs/customer-portal/m2m-tokens"
1173
+ };
996
1174
  default:
997
1175
  return {
998
1176
  command: "gf --help",
999
- why: `Unknown intent "${intent}". Use login | switch_workspace | deploy | run | status | logs | environments | cancel_deployment | init_app | publish_app | secrets | dataplane.`,
1177
+ why: `Unknown intent "${intent}". Use login | switch_workspace | deploy | run | status | logs | environments | cancel_deployment | init_app | publish_app | secrets | dataplane | vault_token.`,
1000
1178
  docs: "https://docs.groundfloor.cloud/docs/customer-portal/developers"
1001
1179
  };
1002
1180
  }
@@ -1101,7 +1279,7 @@ server.tool(
1101
1279
  coderunner_howto: {
1102
1280
  docs_get: "coderunner",
1103
1281
  runtime_contract: "coderunner-runtime",
1104
- before_create: "Enable Administer \u2192 Authentication (mode groundfloor or external, realm active). Mode none cannot mint a Code Runner JWT.",
1282
+ before_create: "Team write can create Coderunners without App authentication. Site auth is optional (end-user login). Mode none uses Portal JWKS (GET /v1/public/jwks.json).",
1105
1283
  types: {
1106
1284
  function: "HTTP handler on PORT/8080 bound to 0.0.0.0. Invoke with gf coderunner run or the Deployment URL. Node requires package.json scripts.start.",
1107
1285
  job: "Run-to-completion worker. Deploy, then gf coderunner run.",
@@ -1109,7 +1287,7 @@ server.tool(
1109
1287
  service: "Long-running Deployment (same type as service). Dockerfile at ZIP root is required. Listen on 8080 / 0.0.0.0."
1110
1288
  },
1111
1289
  node: "No Dockerfile \u2192 platform injects node:18-alpine CMD npm start EXPOSE 8080. Require scripts.start; listen on PORT||8080; bind 0.0.0.0. gf deploy fails fast if scripts.start is missing.",
1112
- local_live_data: 'eval "$(gf env)" then call Control Plane vault/files/secrets with Bearer $(gf token). Do not zip .env files.'
1290
+ local_live_data: 'eval "$(gf env)". For files/secrets as a builder use Bearer $(gf token). For Vault/Files as the deployed workload, attach an M2M client and use Bearer $(gf m2m token). Never DATAPLANE_SERVICE_API_KEY. Do not zip .env files.'
1113
1291
  },
1114
1292
  shell_app_howto: {
1115
1293
  docs_get: "shell",
@@ -1121,9 +1299,10 @@ server.tool(
1121
1299
  databases_howto: {
1122
1300
  docs_get: "databases",
1123
1301
  dataplane: "Dataplane is not a database. It is how Groundfloor talks to databases.",
1124
- 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.",
1125
- arango: "Shared, managed, already there. Default for app data and Vault. No deploy step.",
1126
- deploy: "Postgres is what you can deploy today."
1302
+ 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.",
1303
+ 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.',
1304
+ arango: "Also shared, managed, already there, no deploy step. Still fully supported; just no longer pre-selected.",
1305
+ deploy: "A dedicated Postgres/Redis/ClickHouse/Qdrant you own is what you can deploy today (portal Data \u2192 Databases)."
1127
1306
  },
1128
1307
  actions: {
1129
1308
  deploy: suggestCli("deploy"),
@@ -1132,6 +1311,7 @@ server.tool(
1132
1311
  logs: suggestCli("logs"),
1133
1312
  environments: suggestCli("environments"),
1134
1313
  cancel_deployment: suggestCli("cancel_deployment"),
1314
+ vault_token: suggestCli("m2m_token"),
1135
1315
  init_app: suggestCli("init_app"),
1136
1316
  publish_app: suggestCli("publish_app")
1137
1317
  },
@@ -1400,7 +1580,7 @@ server.tool(
1400
1580
  );
1401
1581
  server.tool(
1402
1582
  "dataplane_status",
1403
- "Dataplane setup status (Dataplane is how Groundfloor talks to databases, not a database itself). ArangoDB is ready through it. Provision with `gf dataplane provision`.",
1583
+ "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`.",
1404
1584
  { workspace_id: wsId },
1405
1585
  async ({ workspace_id }) => {
1406
1586
  try {
@@ -1430,10 +1610,10 @@ server.tool(
1430
1610
  );
1431
1611
  server.tool(
1432
1612
  "docs_get",
1433
- "How-to for Coderunner, Shell, design-standard, css-and-styling, databases. Pass id from docs_list. Prefer id coderunner or coderunner-runtime before deploying. For data work use id databases. For own CSS framework use id css-and-styling.",
1613
+ "How-to for Coderunner, Shell, design-standard, css-and-styling, databases, access, m2m. Pass id from docs_list. Prefer id coderunner or coderunner-runtime before deploying. For site grants use id access. For Coderunner Vault/Files use id m2m.",
1434
1614
  {
1435
1615
  id: z.string().min(1).describe(
1436
- "Catalog id, e.g. coderunner | coderunner-runtime | shell | design-standard | css-and-styling | databases | agents | developers | authentication"
1616
+ "Catalog id, e.g. coderunner | coderunner-runtime | shell | design-standard | css-and-styling | databases | agents | developers | authentication | access | m2m"
1437
1617
  )
1438
1618
  },
1439
1619
  async ({ id }) => {
@@ -1468,10 +1648,12 @@ server.tool(
1468
1648
  "init_app",
1469
1649
  "publish_app",
1470
1650
  "secrets",
1471
- "dataplane"
1651
+ "dataplane",
1652
+ "vault_token",
1653
+ "m2m_token"
1472
1654
  ]),
1473
1655
  workspace: z.string().optional(),
1474
- name: z.string().optional().describe("Coderunner name/id for deploy/run/status/logs/cancel_deployment"),
1656
+ name: z.string().optional().describe("Coderunner name/id for deploy/run/status/logs/cancel_deployment/vault_token"),
1475
1657
  slug: z.string().optional().describe("Portal app slug for init_app / publish_app"),
1476
1658
  cell: z.enum(["production", "stage", "dev"]).optional()
1477
1659
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groundfloorcloud/mcp",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Groundfloor MCP — inspect workspace state and docs; take actions with the gf CLI.",
5
5
  "type": "module",
6
6
  "bin": {