@groundfloorcloud/mcp 0.2.2 → 0.2.3

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 +1 -1
  2. package/dist/index.js +100 -22
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -81,7 +81,7 @@ Use the prefixed names: `GROUNDFLOOR_API_URL`, `GROUNDFLOOR_WORKSPACE_ID`, `GROU
81
81
  | `apps_list` / `apps_get` | Inspect product Apps |
82
82
  | `secrets_list` / `files_list` / `dataplane_status` | Inspect (no secrets values) |
83
83
  | `domains_list` | Custom domains of an App's Coderunner (`app_id` or `coderunner_id`). Domains exist on Apps, not standalone Coderunners |
84
- | `quota_get` / `billing_summary` | Plan quota and billing for the workspace's **account** (account id is not the workspace id; billing needs Owner or Billing admin) |
84
+ | `quota_get` / `billing_summary` | Plan quota and billing for the workspace's **account** (account id is not the workspace id; billing needs organization Owner, Admin or Billing admin) |
85
85
  | `docs_list` / `docs_get` | Product docs (`coderunner`, `coderunner-runtime`, `shell`, `design-standard`, `css-and-styling`, `databases`, `vault`, `feature-flags`, `authentication` are embedded; `access` and `m2m` are live pages, with an `offset` parameter to read past the 12,000-character page limit) |
86
86
  | `suggest_cli` | Command to run: login, deploy, create_app, init_app, publish_app, m2m_token, … |
87
87
 
package/dist/index.js CHANGED
@@ -516,9 +516,20 @@ the provider.
516
516
 
517
517
  ## Users and roles (Groundfloor mode)
518
518
 
519
- - **Invite user**: they set their own password from an emailed invitation.
520
- - **Add user**: you set a password now; they get an email with their sign-in
521
- address and role (never the password).
519
+ - **Invite user**: they set their own password from an emailed invitation
520
+ (the link works for 72 hours).
521
+ - **Add user**: they can sign in straight away. Prefer **Generate a temporary
522
+ password** (API: \`POST /v1/workspaces/{id}/users/add\` with
523
+ \`generate_password: true\`): it is returned once in \`temporary_password\`
524
+ with \`sign_in_url\`, never stored or emailed, and must be changed at first
525
+ sign-in. They also get an email with their sign-in address and role (never
526
+ the password).
527
+ - Invite and add take an optional \`app_id\` so the email's sign-in link opens
528
+ that app.
529
+ - Inviting or adding someone who can already sign in (a password, another
530
+ credential or single sign-on) returns 409 and sends nothing. Use
531
+ \`POST \u2026/users/{user_id}/reset-password\` for them instead.
532
+ - App users never appear on the portal **Team** page.
522
533
  - Each user has a role: built-in \`viewer\`, \`user\`, \`admin\`, or a custom role
523
534
  created on the **Roles** tab. Roles here are unrelated to Portal team roles.
524
535
  - The role decides what the user reaches once granted on **Site access**
@@ -549,6 +560,47 @@ the provider.
549
560
  stored custom server settings and password. Only send \`mail\` when the user
550
561
  means to change email settings.
551
562
 
563
+ ## When an invite email isn't sent
564
+
565
+ Never report an invite as delivered without checking. Invite, add, resend and
566
+ reset responses, and every user in \`GET /v1/workspaces/{id}/users\`, carry:
567
+
568
+ - \`email_sent\`: \`true\` sent, \`false\` not sent, \`null\` unknown.
569
+ - \`email_skipped_reason\`: \`smtp_not_configured\` (no email server set up for
570
+ the workspace's sign-in email), \`send_failed\` (the server refused or
571
+ failed), \`delivery_unconfirmed\` (timed out; it may still arrive),
572
+ \`not_requested\` (sent with \`send_email: false\`), or \`null\`.
573
+ \`keycloak_smtp_missing\` is retired and no longer returned.
574
+ - \`email_attempted_at\` (\`null\` = invited before delivery was recorded),
575
+ \`invite_pending\`, \`password_change_required\`,
576
+ \`temporary_password_set_at\`, \`invite_link_expires_at\`.
577
+
578
+ If \`email_sent\` is not \`true\` for a pending user, tell the user plainly
579
+ and offer the fallbacks. In the Portal they are on the user's row under
580
+ **App authentication \u2192 Users**; all need workspace \`administer\` (M2M and
581
+ app-user tokens get 403):
582
+
583
+ 1. **Resend** (\`POST \u2026/users/{user_id}/resend-invite\`, pending users only):
584
+ at most once per 60 s and 5 times per 24 h; re-inviting a pending user
585
+ counts against the same limit (429 with \`Retry-After\`). If the reason is
586
+ \`send_failed\` or \`smtp_not_configured\`, fix email first (Branding \u2192
587
+ Email sending, Send test email) or resending will fail the same way.
588
+ 2. **Temp password** (\`POST \u2026/users/{user_id}/temporary-password\`, pending
589
+ or still on an unused temporary password): returns \`temporary_password\`
590
+ and \`sign_in_url\` once; no email is sent; same user id and roles; must be
591
+ changed at first sign-in. 504 = it may or may not be set, retry.
592
+ 3. **Copy link** (\`POST \u2026/users/{user_id}/invite-link\`, pending and enabled
593
+ users only): returns a one-time \`url\` (the portal's \`/join\` page) and
594
+ \`expires_at\` (24 h), once. The user opens it and chooses their own
595
+ password. Each call cancels the previous link; \`DELETE\` cancels it;
596
+ at most 10 per user per hour. Anyone holding the link can set the
597
+ password.
598
+
599
+ Temporary passwords and invite links are credentials. Show them only to the
600
+ person who asked for them, tell them to share privately, and never write them
601
+ to files, commits, logs or chat with anyone else. Once a user has set their
602
+ own password, none of these apply (409): use reset-password.
603
+
552
604
  ## Multi-tenant (customer companies inside one workspace)
553
605
 
554
606
  Turn on **Multi-tenant** in Settings to get a Tenants tab: one tenant per
@@ -563,6 +615,15 @@ Switching to None or External keeps users, roles and settings (switch back and
563
615
  they return). To remove them, turn sign-in off first, then **Delete Groundfloor
564
616
  login**. Access grants and M2M tokens are kept.
565
617
 
618
+ ## What app users' tokens can call
619
+
620
+ App users' tokens work only on: app list and by-slug, Data Vault collection
621
+ list/schema and record query/count/create/update/delete (per collection
622
+ grants), Files list/upload/download/delete (per Files grants) and
623
+ \`GET \u2026/flags/runtime\`. Everything else returns 403 "This API is not
624
+ available to app end users", whatever their role, \`admin\` included. A user
625
+ with no role at all gets 403 too.
626
+
566
627
  ## In a Shell app
567
628
 
568
629
  The signed-in user's JWT comes from \`window.__GF_GET_ACCESS_TOKEN__()\`. See
@@ -817,6 +878,11 @@ CMD ["npm", "start"]
817
878
  \`externalEndpoint\` and status 4 means the container never became ready.
818
879
  \`gf deploy\` prints the last Process Log lines, ids, and a Portal link on
819
880
  failure. Fetch more with \`gf coderunner logs -c <id|slug>\`.
881
+ - \`coderunner_get_status\` (\`GET \u2026/coderunners/{id}/status\`) returns
882
+ \`deployment_status\` (same 1\u20137 codes) and \`deployment_status_message\` for
883
+ the current deployment. While it is 4 (Failed), an App address or custom
884
+ domain routed to it answers 503, and the Portal app page shows "Deployment
885
+ failed".
820
886
  - Strip \`.env*\`, \`.git\`, \`node_modules\` from ZIPs. Put secrets in
821
887
  \`gf secrets\` / deploy \`-e\`, never in the archive.
822
888
  - Zip **contents** at root, not a wrapping folder.
@@ -933,8 +999,9 @@ documented limit.
933
999
  Plan quota and usage are account-scoped, not workspace-scoped. The **account
934
1000
  id is not the workspace id**: read \`account_id\` from \`workspaces_list\`. If a
935
1001
  deploy is refused or you need to know what is in use, call \`quota_get\`.
936
- \`billing_summary\` shows spend, and only Owners and Billing admins can read it
937
- (others get 403).
1002
+ \`billing_summary\` shows spend, and only organization Owners, Admins and
1003
+ Billing admins can read it (others get 403). A Billing admin has no workspace
1004
+ access at all.
938
1005
 
939
1006
  ## Agent actions
940
1007
 
@@ -994,16 +1061,26 @@ deploy a dedicated PostgreSQL first.
994
1061
  ## Options
995
1062
 
996
1063
  - PostgreSQL (shared) \u2014 platform-managed, already there. Default for app data
997
- and Vault. No deploy step. This is NOT a workspace-owned resource: it does
998
- not appear on the customer Databases page, and there is nothing to scale,
999
- back up, or delete yourself \u2014 it's offered, not provisioned. Query via
1000
- Control Plane vault: POST /v1/workspaces/{id}/vault/collections/{name}/query
1064
+ and Vault. No deploy step. The portal Databases page lists it first as
1065
+ "Shared PostgreSQL" (Default, connected as \`postgresql\`), but it is NOT a
1066
+ workspace-owned resource: no credentials, and nothing to scale, back up, or
1067
+ delete yourself \u2014 it's offered, not provisioned. Query via Control Plane
1068
+ vault: POST /v1/workspaces/{id}/vault/collections/{name}/query
1001
1069
  - Dedicated PostgreSQL you deploy and own \u2014 portal Data \u2192 Databases, or
1002
1070
  POST /v1/workspaces/{id}/managed-databases with engine postgres. Heavier
1003
1071
  than the shared default: you own its scaling, backups, and lifecycle. Use it
1004
1072
  when you want a database isolated to this workspace.
1005
1073
  - A database they already run \u2014 through Dataplane if they wire it, or direct.
1006
1074
 
1075
+ A dedicated PostgreSQL is usable through Vault only once Dataplane has it:
1076
+ \`GET /v1/workspaces/{id}/managed-databases\` returns \`dataplane_status\`
1077
+ (\`connected\` | \`not_connected\` | null while not up) and
1078
+ \`dataplane_connection_name\` (pass it as Vault \`connection\`). If it is
1079
+ \`not_connected\`, retry with
1080
+ \`POST \u2026/managed-databases/{managed_database_id}/dataplane/register\` (write; the
1081
+ portal's Retry button), or tell the user to. New dedicated databases get a
1082
+ daily backup schedule (30-day retention) where the cell has backup storage.
1083
+
1007
1084
  PostgreSQL is the only engine offered today, shared or dedicated. Do not offer
1008
1085
  other engines (ArangoDB, MongoDB, Redis, ClickHouse, Qdrant, \u2026) as available,
1009
1086
  even if you see them mentioned elsewhere. Do not call Dataplane hosts from apps
@@ -1119,9 +1196,10 @@ with no role gets 403.
1119
1196
  ### Shell federated app (browser)
1120
1197
 
1121
1198
  - **Token**: the Shell end-user JWT, \`await window.__GF_GET_ACCESS_TOKEN__()\`.
1122
- - **Permission**: workspace \`read\`. Site users get it from a recognised site
1123
- role (member/admin); self-registered users with no role get 403 (same rule
1124
- as Vault). No per-flag Access grant exists or is needed.
1199
+ - **Permission**: any role from the workspace's App authentication (built-in
1200
+ or custom); a signed-in user with no role gets 403 (same rule as Vault).
1201
+ App users are not workspace members. No per-flag Access grant exists or is
1202
+ needed.
1125
1203
  - **Environment**: \`window.__GF_ENVIRONMENT_ID__\` \u2014 the environment the app is
1126
1204
  bound to, published by the Shell before your remote mounts. Unset in local
1127
1205
  Dev Shell \u2192 server default (dev); \`VITE_GF_ENVIRONMENT_ID\` pins one.
@@ -1425,7 +1503,7 @@ var DOC_CATALOG = [
1425
1503
  path: "/docs/deploy",
1426
1504
  summary: "Workload types (function, job, schedule, service/Deployment), runtime contract (handler.js for function/job/schedule; npm start, PORT 8080 for service), Dockerfile for services, Coderunner identities for Vault, App authentication optional, local live data, gf deploy.",
1427
1505
  embedded: CODERUNNER_GUIDE,
1428
- lastUpdated: "2026-10-08"
1506
+ lastUpdated: "2026-10-14"
1429
1507
  },
1430
1508
  {
1431
1509
  id: "coderunner-runtime",
@@ -1439,9 +1517,9 @@ var DOC_CATALOG = [
1439
1517
  id: "authentication",
1440
1518
  title: "Workspace Authentication",
1441
1519
  path: "/docs/access/app-authentication",
1442
- summary: "App end users sign in only to the app via the workspace App Authentication realm; no Groundfloor console account or workspace membership. Modes none / Groundfloor / external, users and roles, SSO, multi-tenant, sign-in email (Groundfloor email by default, or your own server). Optional; not required to create Apps or Coderunners. Separate from portal Team.",
1520
+ summary: "App end users sign in only to the app via the workspace App Authentication realm; no Groundfloor console account or workspace membership. Modes none / Groundfloor / external, users and roles, SSO, multi-tenant, sign-in email (Groundfloor email by default, or your own server). Invite delivery (email_sent, email_skipped_reason) and what to do when an invite isn't sent: resend, generated temporary password, one-time invite link; 409 for people who can already sign in. App users' tokens work only on the end-user routes. Optional; not required to create Apps or Coderunners. Separate from portal Team.",
1443
1521
  embedded: APP_AUTHENTICATION_GUIDE,
1444
- lastUpdated: "2026-10-13"
1522
+ lastUpdated: "2026-10-14"
1445
1523
  },
1446
1524
  {
1447
1525
  id: "access",
@@ -1489,9 +1567,9 @@ var DOC_CATALOG = [
1489
1567
  id: "databases",
1490
1568
  title: "Databases",
1491
1569
  path: "/docs/data/databases",
1492
- summary: "Dataplane is not a database. PostgreSQL (shared, platform-managed) is ready through Dataplane with no deploy step. A dedicated PostgreSQL you deploy and own is a separate, heavier path. PostgreSQL is the only engine offered.",
1570
+ summary: "Dataplane is not a database. PostgreSQL (shared, platform-managed) is ready through Dataplane with no deploy step. A dedicated PostgreSQL you deploy and own is a separate, heavier path; check its dataplane_status before using it in Vault. PostgreSQL is the only engine offered.",
1493
1571
  embedded: DATABASES_GUIDE,
1494
- lastUpdated: "2026-09-26"
1572
+ lastUpdated: "2026-10-14"
1495
1573
  },
1496
1574
  {
1497
1575
  id: "vault",
@@ -1507,7 +1585,7 @@ var DOC_CATALOG = [
1507
1585
  path: "/docs/configure/feature-flags",
1508
1586
  summary: "Built-in per-environment feature flags (toggles / config values) \u2014 use these, not a Vault collection. gf flags ls|set|compare|promote. Apps read GET \u2026/flags/runtime: Shell apps with the end-user JWT + window.__GF_ENVIRONMENT_ID__ (starter-kit useFlag), Coderunners with gf m2m token + GROUNDFLOOR_ENVIRONMENT_ID. Default environment is dev.",
1509
1587
  embedded: FLAGS_GUIDE,
1510
- lastUpdated: "2026-10-08"
1588
+ lastUpdated: "2026-10-14"
1511
1589
  },
1512
1590
  {
1513
1591
  id: "flags-api",
@@ -1515,7 +1593,7 @@ var DOC_CATALOG = [
1515
1593
  path: "/docs/api/flags",
1516
1594
  summary: "REST reference for flags: list/get/put/delete per environment_id (omitted \u2192 workspace default, dev), compare, promote, runtime read. Key format, value_type validation, auth per method (M2M read-only), error codes.",
1517
1595
  embedded: FLAGS_GUIDE,
1518
- lastUpdated: "2026-10-08"
1596
+ lastUpdated: "2026-10-14"
1519
1597
  },
1520
1598
  {
1521
1599
  id: "scheduled-jobs",
@@ -1523,7 +1601,7 @@ var DOC_CATALOG = [
1523
1601
  path: "/docs/deploy/schedules",
1524
1602
  summary: "workload_type=schedule plus cron. gf coderunner status shows type/schedule/last_job. Use Process Log, not a public URL.",
1525
1603
  embedded: CODERUNNER_GUIDE,
1526
- lastUpdated: "2026-10-08"
1604
+ lastUpdated: "2026-10-14"
1527
1605
  }
1528
1606
  ];
1529
1607
  function docUrl(entry) {
@@ -1818,7 +1896,7 @@ server.tool(
1818
1896
  default_environment_id: flags?.environment_id ?? null,
1819
1897
  default_environment_flags: flags ? flags.flags.map((f) => ({ key: f.key, value_type: f.value_type, value: f.value })) : null,
1820
1898
  manage: "gf flags ls|get|set|rm|compare|promote -e <env id or name>. Omitting -e uses the default environment (dev).",
1821
- shell_app: "Starter-kit src/lib/flags.ts: useFlag('key', fallback). Calls GET /v1/workspaces/{id}/flags/runtime?environment_id=window.__GF_ENVIRONMENT_ID__ with the Shell end-user JWT (needs a site role \u2192 workspace read).",
1899
+ shell_app: "Starter-kit src/lib/flags.ts: useFlag('key', fallback). Calls GET /v1/workspaces/{id}/flags/runtime?environment_id=window.__GF_ENVIRONMENT_ID__ with the Shell end-user JWT (needs any App authentication role; app users are not workspace members).",
1822
1900
  coderunner: "GET \u2026/flags/runtime?environment_id=$GROUNDFLOOR_ENVIRONMENT_ID with an M2M token (gf m2m token). M2M is read-only on flags; workload-identity tokens are rejected."
1823
1901
  },
1824
1902
  coderunner_howto: {
@@ -2229,7 +2307,7 @@ server.tool(
2229
2307
  );
2230
2308
  server.tool(
2231
2309
  "billing_summary",
2232
- "Compute-unit usage and billing estimate for the organization that owns the workspace (account-scoped, not workspace-scoped). Only Owners and Billing admins may read it; others get 403. The response notes whether it is an estimate.",
2310
+ "Compute-unit usage and billing estimate for the organization that owns the workspace (account-scoped, not workspace-scoped). Only organization Owners, Admins and Billing admins may read it; others get 403. The response notes whether it is an estimate.",
2233
2311
  {
2234
2312
  workspace_id: wsId,
2235
2313
  account_id: accountId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groundfloorcloud/mcp",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Groundfloor MCP — inspect workspace state and docs; take actions with the gf CLI.",
5
5
  "type": "module",
6
6
  "bin": {