@cloudgrid-io/mcp 0.20.18 → 0.20.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudgrid-io/mcp",
3
- "version": "0.20.18",
3
+ "version": "0.20.19",
4
4
  "description": "Use CloudGrid via MCP to brainstorm, build, deploy, and improve apps, games, websites, dashboards, and tools and get a live URL - templates, recipes, managed databases and AI, instant single-page publish, and full-app deploys, for developers and non-technical users. Three editions: local stdio (full toolset), hosted web (light, CLI-free), and a public docs-search server, over MCP.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -29,6 +29,7 @@
29
29
  "test:grid-picker": "node test/grid-picker.test.mjs",
30
30
  "test:plug-output-schema": "node test/plug-output-schema.test.mjs",
31
31
  "test:zip-deploy": "node test/zip-deploy.test.mjs",
32
+ "test:create-gates": "node test/create-gates.test.mjs",
32
33
  "test:mcpb-boot": "node test/mcpb-boot.test.mjs",
33
34
  "test:plug-timeout": "node test/plug-timeout.test.mjs",
34
35
  "test:manifest-confirm": "node test/manifest-confirm.test.mjs",
@@ -7,7 +7,7 @@ Operating rules:
7
7
  4. Always return the live share URL at the end — that is the deliverable. On a NEW deploy, then ASK the user who should be able to open it — private (only you), a space, your grid, anyone with the link, or anyone signed in — and set their choice with grid_set_sharing. Never pick the visibility silently. On a re-plug/edit of an existing entity, leave its current visibility as-is unless the user asks to change it.
8
8
  5. Brainstorm first (lightly) for a real app, then minimize questions. For a substantial runtime app, take ONE lightweight beat before generating/deploying: confirm the goal + 3-5 core features in a sentence, check for a matching template/recipe (capability-map), and infer the data/runtime needs and STATE them ("I'll add a database so entries are saved"). Keep it to a line or two; never ask a non-technical user infra questions they can't answer. A simple single page skips this and builds immediately. Otherwise use sensible defaults and build; don't front-load setup questions.
9
9
  6. If a signed-in publish fails with a server error, do not fall back to anonymous publishing (it burns the anonymous quota and downgrades ownership); surface the error, use the CLI fallback if offered, or ask the user.
10
- 7. When signed in and the user has more than one grid, do not assume a target — the publish tools will ask; relay the choice to the user and pass the chosen grid.
10
+ 7. When signed in and the user has more than one grid, do not assume a target. For a NEW app, establish the grid UP FRONT — grid_start returns the grids; if there is more than one, ask "which grid should this go on?" before you start building, and carry that slug into grid_deploy. As a backstop, grid_deploy hard-gates this: an authed create with >1 grid and no chosen grid returns needs_grid (the picker) instead of deploying; a create with no auth and no anon returns needs_auth (sign-in vs anonymous) instead of silently publishing anonymously. Relay either ask to the user; never pick silently.
11
11
  8. When a build/deploy fails unexpectedly, offer to report it to the CloudGrid team — only with the user's explicit consent (ask first). Send just the error + the failed request by default (call grid_report), and never send the whole conversation unless the user agrees (include_conversation). Respect privacy.
12
12
  9. To modify an existing page when you don't already have its HTML in context, first call grid_get_app_source to fetch the current HTML, apply your change, then call grid_deploy with target_entity_id (the entity_id) to update the SAME URL in place. Do not ask the user to paste the HTML back.
13
13
  10. Publishing a single HTML page: pass it inline as grid_deploy's html parameter (a full self-contained document). For a heavy or image-heavy page in the local edition, pass the path parameter instead so it is read from disk (no inline size limit); never base64-encode HTML and never pass a file path (or an @-prefixed path) as html. If a page looks empty, use grid_get_app_source to check what was actually published, then re-plug with the real HTML/path and target_entity_id.
@@ -288,6 +288,7 @@ export function registerTools(server, ctx) {
288
288
  // they validate: (1) the grid-picker "which grid?" ask (resolveGridOrAsk),
289
289
  // and (2) the signed-in CLI-fallback recovery.
290
290
  needs_grid: z.boolean().optional().describe("Grid-picker ask: a signed-in user with >1 grid must choose one before this create proceeds. Pass the chosen slug back in `grid`."),
291
+ needs_auth: z.boolean().optional().describe("Auth gate: a NEW deploy was attempted while not signed in. Ask the user to sign in (grid_login) to publish to their grid, OR re-call grid_deploy with anon: true to publish anonymously (claimable later). Do not proceed silently."),
291
292
  needs_org: z.boolean().optional().describe("Alias of needs_grid (legacy picker alias)."),
292
293
  grids: z.array(z.object({
293
294
  slug: z.string(),
@@ -357,7 +358,20 @@ export function registerTools(server, ctx) {
357
358
  }
358
359
  if (input?.anon !== true && !isEdit) {
359
360
  const token = await ctx.getToken();
360
- if (token) {
361
+ if (!token) {
362
+ // AUTH HARD GATE (create only): not signed in and not anon → do NOT
363
+ // silently ride the anonymous wire. Return the login-or-anon choice
364
+ // and stop. The model relays it; the user picks. (Rule 17, enforced.)
365
+ return okResult({
366
+ text:
367
+ "You're not signed in. To publish this I can either:\n" +
368
+ " 1. Sign you in to publish to your grid — run grid_login (opens your browser), then I'll deploy.\n" +
369
+ " 2. Publish it anonymously right now — it goes live immediately with a claim link so you can save it to your account later.\n" +
370
+ "Which would you like? (For anonymous, re-call grid_deploy with anon: true.)",
371
+ structured: { needs_auth: true },
372
+ });
373
+ }
374
+ {
361
375
  const decision = await resolveGridOrAsk(ctx, {
362
376
  token,
363
377
  suppliedGrid: input?.grid,