@groundfloorcloud/mcp 0.1.7 → 0.1.8

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 +88 -27
  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
@@ -613,21 +631,41 @@ curl -sS -X POST http://127.0.0.1:8080/ -H 'Content-Type: application/json' \\
613
631
 
614
632
  Live vault / files / secrets from the laptop:
615
633
 
634
+ \`gf token\` is a **builder** credential. Use it for operator Vault. To call
635
+ Vault and Files as a Coderunner does, use an M2M client and \`gf m2m token\`.
636
+
616
637
  \`\`\`bash
638
+ # Builder token:
617
639
  curl -sS -H "Authorization: Bearer $(gf token)" \\
618
640
  "$CONTROLPLANE_URL/v1/workspaces/$GROUNDFLOOR_WORKSPACE_ID/vault/collections"
641
+
642
+ # M2M (same class as an attached Coderunner):
643
+ curl -sS -H "Authorization: Bearer $(gf m2m token)" \\
644
+ "$CONTROLPLANE_URL/v1/workspaces/$GROUNDFLOOR_WORKSPACE_ID/vault/collections"
645
+ curl -sS -H "Authorization: Bearer $(gf m2m token)" \\
646
+ "$CONTROLPLANE_URL/v1/workspaces/$GROUNDFLOOR_WORKSPACE_ID/files"
619
647
  \`\`\`
620
648
 
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.
649
+ In app code, use \`CONTROLPLANE_URL\` + Bearer from
650
+ \`POST \u2026/m2m/token\` (\`gf m2m token\` locally; injected
651
+ \`GROUNDFLOOR_M2M_CLIENT_ID\` / \`GROUNDFLOOR_M2M_CLIENT_SECRET\` after
652
+ \`gf deploy\`). Never put \`DATAPLANE_SERVICE_API_KEY\` in a browser bundle
653
+ or customer env.
624
654
 
625
655
  When the handler looks right locally, \`gf deploy\` the same tree.
626
656
 
657
+ ## M2M tokens (Vault and Files)
658
+
659
+ New Coderunners cannot call Vault or Files until an M2M client is attached
660
+ and the workload is redeployed. Create the client in Portal **Administer \u2192
661
+ M2M tokens**, attach it on the Coderunner card, then deploy. v1 M2M is Team
662
+ Writer on that workspace (full Vault skip-ACL + Files). Grant site users on
663
+ **Administer \u2192 Access**. Never inject a Dataplane key.
664
+
627
665
  ## Agent actions
628
666
 
629
667
  Inspect: \`workspace_context\`, \`docs_get\` id \`coderunner\` or \`coderunner-runtime\`, \`suggest_cli\`.
630
- Act: \`gf deploy\`, \`gf coderunner run|status\`. MCP does not deploy.
668
+ Act: \`gf deploy\`, \`gf coderunner run|status\`, \`gf m2m token\`. MCP does not deploy.
631
669
  `.trim();
632
670
 
633
671
  // src/css-and-styling-guide.ts
@@ -771,8 +809,9 @@ gf apps publish --path release.zip
771
809
  \`\`\`
772
810
 
773
811
  \`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.
812
+ \`__federation_*.js\` + CSS) at the zip root and rewrites \`./assets/\` imports
813
+ in remoteEntry.js. Do not zip \`dist/\`. Do not upload a lone \`remoteEntry.js\`.
814
+ \`gf apps publish\` rejects incomplete zips.
776
815
 
777
816
  Production builds use Vite \`base: './'\` so imported images resolve next to
778
817
  remoteEntry.js. Header logos: manifest \`theme.logoUrl\` (absolute https).
@@ -796,19 +835,19 @@ var DOC_CATALOG = [
796
835
  id: "agents",
797
836
  title: "Deploy with agents",
798
837
  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."
838
+ 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
839
  },
801
840
  {
802
841
  id: "developers",
803
842
  title: "Developers (gf CLI)",
804
843
  path: "/docs/customer-portal/developers",
805
- summary: "gf login, workspaces, deploy, secrets, files, apps. Coderunner types: function, job, schedule, service (also called Deployment)."
844
+ summary: "gf login, workspaces, deploy, secrets, files, apps, gf m2m token. Coderunner types: function, job, schedule, service (also called Deployment). App authentication optional."
806
845
  },
807
846
  {
808
847
  id: "coderunner",
809
848
  title: "Coderunner",
810
849
  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.",
850
+ 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
851
  embedded: CODERUNNER_GUIDE
813
852
  },
814
853
  {
@@ -822,14 +861,26 @@ var DOC_CATALOG = [
822
861
  id: "coderunner-overview",
823
862
  title: "Coderunner overview",
824
863
  path: "/docs/integrations/coderunner/overview",
825
- summary: "Architecture and lifecycle. Prefer docs_get id coderunner for type usage, Dockerfile, and auth prerequisites.",
864
+ summary: "Architecture and lifecycle. Prefer docs_get id coderunner for type usage, Dockerfile, and create prerequisites.",
826
865
  embedded: CODERUNNER_GUIDE
827
866
  },
828
867
  {
829
868
  id: "authentication",
830
869
  title: "Workspace Authentication",
831
870
  path: "/docs/customer-portal/authentication",
832
- summary: "Workspace site auth (Groundfloor or external) must be active before creating a Coderunner. Separate from portal Team."
871
+ 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."
872
+ },
873
+ {
874
+ id: "access",
875
+ title: "Access",
876
+ path: "/docs/customer-portal/access",
877
+ 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."
878
+ },
879
+ {
880
+ id: "m2m",
881
+ title: "M2M tokens",
882
+ path: "/docs/customer-portal/m2m-tokens",
883
+ 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
884
  },
834
885
  {
835
886
  id: "api-authentication",
@@ -934,7 +985,7 @@ function suggestCli(intent, args) {
934
985
  case "deploy":
935
986
  return {
936
987
  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.',
988
+ 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
989
  docs: "https://docs.groundfloor.cloud/docs/customer-portal/coderunner"
939
990
  };
940
991
  case "run":
@@ -993,10 +1044,17 @@ function suggestCli(intent, args) {
993
1044
  why: "Dataplane is required for vault, files, and secrets.",
994
1045
  docs: "https://docs.groundfloor.cloud/docs/customer-portal/developers"
995
1046
  };
1047
+ case "vault_token":
1048
+ case "m2m_token":
1049
+ return {
1050
+ command: `gf m2m token${ws}`,
1051
+ 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.",
1052
+ docs: "https://docs.groundfloor.cloud/docs/customer-portal/m2m-tokens"
1053
+ };
996
1054
  default:
997
1055
  return {
998
1056
  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.`,
1057
+ why: `Unknown intent "${intent}". Use login | switch_workspace | deploy | run | status | logs | environments | cancel_deployment | init_app | publish_app | secrets | dataplane | vault_token.`,
1000
1058
  docs: "https://docs.groundfloor.cloud/docs/customer-portal/developers"
1001
1059
  };
1002
1060
  }
@@ -1101,7 +1159,7 @@ server.tool(
1101
1159
  coderunner_howto: {
1102
1160
  docs_get: "coderunner",
1103
1161
  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.",
1162
+ 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
1163
  types: {
1106
1164
  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
1165
  job: "Run-to-completion worker. Deploy, then gf coderunner run.",
@@ -1109,7 +1167,7 @@ server.tool(
1109
1167
  service: "Long-running Deployment (same type as service). Dockerfile at ZIP root is required. Listen on 8080 / 0.0.0.0."
1110
1168
  },
1111
1169
  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.'
1170
+ 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
1171
  },
1114
1172
  shell_app_howto: {
1115
1173
  docs_get: "shell",
@@ -1132,6 +1190,7 @@ server.tool(
1132
1190
  logs: suggestCli("logs"),
1133
1191
  environments: suggestCli("environments"),
1134
1192
  cancel_deployment: suggestCli("cancel_deployment"),
1193
+ vault_token: suggestCli("m2m_token"),
1135
1194
  init_app: suggestCli("init_app"),
1136
1195
  publish_app: suggestCli("publish_app")
1137
1196
  },
@@ -1430,10 +1489,10 @@ server.tool(
1430
1489
  );
1431
1490
  server.tool(
1432
1491
  "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.",
1492
+ "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
1493
  {
1435
1494
  id: z.string().min(1).describe(
1436
- "Catalog id, e.g. coderunner | coderunner-runtime | shell | design-standard | css-and-styling | databases | agents | developers | authentication"
1495
+ "Catalog id, e.g. coderunner | coderunner-runtime | shell | design-standard | css-and-styling | databases | agents | developers | authentication | access | m2m"
1437
1496
  )
1438
1497
  },
1439
1498
  async ({ id }) => {
@@ -1468,10 +1527,12 @@ server.tool(
1468
1527
  "init_app",
1469
1528
  "publish_app",
1470
1529
  "secrets",
1471
- "dataplane"
1530
+ "dataplane",
1531
+ "vault_token",
1532
+ "m2m_token"
1472
1533
  ]),
1473
1534
  workspace: z.string().optional(),
1474
- name: z.string().optional().describe("Coderunner name/id for deploy/run/status/logs/cancel_deployment"),
1535
+ name: z.string().optional().describe("Coderunner name/id for deploy/run/status/logs/cancel_deployment/vault_token"),
1475
1536
  slug: z.string().optional().describe("Portal app slug for init_app / publish_app"),
1476
1537
  cell: z.enum(["production", "stage", "dev"]).optional()
1477
1538
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groundfloorcloud/mcp",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Groundfloor MCP — inspect workspace state and docs; take actions with the gf CLI.",
5
5
  "type": "module",
6
6
  "bin": {