@cloudgrid-io/mcp 0.20.38 → 0.20.39

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.38",
3
+ "version": "0.20.39",
4
4
  "description": "MCP access to CloudGrid — the live runtime environment where the user's apps run WITH the infrastructure they need out of the box: managed MongoDB, Redis (cache/queues/pub-sub), a pgvector store, persistent disk, and built-in AI with no API keys, in any language or stack, no Docker or Kubernetes to manage. Brainstorm, build, plug, and improve apps, games, dashboards, and tools; instant single-page publishes and full runtime-app deploys with a live URL — for developers and non-technical users. Three editions: local stdio (full toolset), hosted web (light, CLI-free), and a public docs-search server.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -83,7 +83,7 @@ export async function resolveGridOrAsk(ctx, { token, suppliedGrid, edition }, de
83
83
  if (a.render_ready !== b.render_ready) return b.render_ready ? 1 : -1;
84
84
  return 0;
85
85
  });
86
- const lines = ["Which grid should this be published to?"];
86
+ const lines = ["Which grid should this be plugged into?"];
87
87
  for (const o of annotated) {
88
88
  const tags = [];
89
89
  if (o.is_active) tags.push("your active grid");
@@ -787,7 +787,7 @@ async function expandZipToProject(zipPath, inlineHtml) {
787
787
  const hasInlineHtml = typeof inlineHtml === "string" && inlineHtml.length > 0;
788
788
  if (hasInlineHtml && hasManifest) {
789
789
  throw new Error(
790
- "The zip already contains a cloudgrid.yaml project — deploy it as-is (drop the `html` param), " +
790
+ "The zip already contains a cloudgrid.yaml project — plug it as-is (drop the `html` param), " +
791
791
  "or re-plug the entity and edit its files instead.",
792
792
  );
793
793
  }
@@ -895,7 +895,7 @@ async function plugZipProjectViaCli(ctx, { projectDir, name }, input, deps = {})
895
895
  const url = parseCliPlugUrl(stdout);
896
896
  if (!url) {
897
897
  throw new Error(
898
- `The zip project deployed via the CLI but no live URL was found in its output.\n${stdout.slice(0, 500)}`,
898
+ `The zip project was plugged via the CLI but no live URL was found in its output.\n${stdout.slice(0, 500)}`,
899
899
  );
900
900
  }
901
901
  return {
@@ -996,7 +996,7 @@ export function errorGuidance({ status, code, edition, isEdit, isAnon, signedIn
996
996
  }
997
997
  // 409 EDIT_REJECTED — an in-place re-plug the server won't take.
998
998
  if (status === 409) {
999
- return "The entity cannot be updated right now (a deploy is in progress, or it is archived/expired/claimed). An explicit re-plug never silently creates; retry later, or omit target_entity_id to create a new entity.";
999
+ return "The entity cannot be updated right now (a plug is in progress, or it is archived/expired/claimed). An explicit re-plug never silently creates; retry later, or omit target_entity_id to create a new entity.";
1000
1000
  }
1001
1001
  // 401 on an edit — the credential didn't authorize this entity.
1002
1002
  if (status === 401) {
@@ -1005,7 +1005,7 @@ export function errorGuidance({ status, code, edition, isEdit, isAnon, signedIn
1005
1005
  : "Not signed in. Ask the user: sign in (grid_login) to publish to their grid, OR publish anonymously now (re-call grid_plug with anon: true) - it goes live immediately with a claim_url + owner_token to claim into their account later. Do not silently fail; offer both.";
1006
1006
  }
1007
1007
  if (status === 403) {
1008
- return "You lack the role to plug this target. To re-plug someone else's entity, pick it up first (grid_edit_existing_app / grid_claim_anonymous_deploy).";
1008
+ return "You lack the role to plug this target. To re-plug someone else's entity, pull it first (grid_pull), or make your own copy (grid_pickup).";
1009
1009
  }
1010
1010
  // ── Consent-gated report offer (Task 34) ──────────────────────────────────
1011
1011
  // GENUINE bugs only: a build/deploy failure, any 5xx, INTERNAL_ERROR, or an
@@ -1152,11 +1152,11 @@ export async function runPlug(ctx, input, deps = {}) {
1152
1152
  if (target_entity_id || (slug && grid)) {
1153
1153
  throw new Error(
1154
1154
  "Re-plugging an existing entity from a zip is not supported yet — pick up the app " +
1155
- "(grid_edit_existing_app) and re-plug the folder, or deploy the zip as a new entity.",
1155
+ "(grid_edit_existing_app) and re-plug the folder, or plug the zip as a new entity.",
1156
1156
  );
1157
1157
  }
1158
1158
  if (anon) {
1159
- throw new Error("A zip deploy creates a static app and needs sign-in — it cannot be anonymous.");
1159
+ throw new Error("A zip plug creates a static app and needs sign-in — it cannot be anonymous.");
1160
1160
  }
1161
1161
  const expanded = await expandZipToProject(srcPath, hasHtml ? html : null);
1162
1162
  if (expanded.singleHtml) {
@@ -1371,9 +1371,9 @@ export async function runPlug(ctx, input, deps = {}) {
1371
1371
  } catch (err) {
1372
1372
  if (err?.name === "AbortError" || err?.name === "TimeoutError") {
1373
1373
  throw new Error(
1374
- `The deploy request timed out after ${Math.round(uploadTimeoutMs / 1000)}s. ` +
1375
- `The build may still be running on CloudGrid — check the deploy status ` +
1376
- `(poll_url / grid_status, or your grid) before deploying again, so you don't create a duplicate.`,
1374
+ `The plug request timed out after ${Math.round(uploadTimeoutMs / 1000)}s. ` +
1375
+ `The build may still be running on CloudGrid — check the build status ` +
1376
+ `(poll_url / grid_status, or your grid) before plugging again, so you don't create a duplicate.`,
1377
1377
  );
1378
1378
  }
1379
1379
  throw new Error(`Could not reach CloudGrid at ${API_BASE}: ${err.message}`);
@@ -1558,7 +1558,7 @@ export async function runPlug(ctx, input, deps = {}) {
1558
1558
  : "npx -y @cloudgrid-io/cli plug";
1559
1559
  cliSteer =
1560
1560
  "Heads-up: this went in INLINE. For a multi-file app the disk-based CLI is more reliable (lockfiles/binaries can't truncate), but it must run where the CLI is already signed in — a terminal or Claude Code that has done `grid login` once. Do NOT try `grid login` inside a chat sandbox: its login poll is long-lived and the sandbox is ephemeral, so it won't stick. " +
1561
- `If you had to leave any files out to make this inline deploy safe, tell the user — offer the complete deploy from Claude Code or a terminal (\`${replug}\`), or confirm they accept the reduced version. Do not drop files silently.`;
1561
+ `If you had to leave any files out to make this inline plug safe, tell the user — offer the complete plug from Claude Code or a terminal (\`${replug}\`), or confirm they accept the reduced version. Do not drop files silently.`;
1562
1562
  }
1563
1563
  }
1564
1564
 
@@ -1566,8 +1566,8 @@ export async function runPlug(ctx, input, deps = {}) {
1566
1566
  if (isBuilding) {
1567
1567
  lines.push(
1568
1568
  isEdit
1569
- ? `Building (async): ${url} — the update is deploying, not live yet.`
1570
- : `Building (async): ${url} — the deploy is in progress, not live yet.`,
1569
+ ? `Building (async): ${url} — the update is plugging, not live yet.`
1570
+ : `Building (async): ${url} — the plug is in progress, not live yet.`,
1571
1571
  );
1572
1572
  // Point at a tool that exists on THIS edition. grid_status is CLI-wrapping,
1573
1573
  // local-only — telling a hosted (ChatGPT/claude.ai) model to "run
@@ -1584,7 +1584,7 @@ export async function runPlug(ctx, input, deps = {}) {
1584
1584
  lines.push(`Updated in place: ${url}`);
1585
1585
  } else if (isInspirationCreate) {
1586
1586
  // Authed inspiration create — owned by the caller. Wording mirrors the drop verb.
1587
- lines.push(ctx.edition === "web" ? `Your app is live: ${url}` : `Published to your grid: ${url}`);
1587
+ lines.push(ctx.edition === "web" ? `Your app is live: ${url}` : `Plugged into your grid: ${url}`);
1588
1588
  if (ctx.edition !== "web") lines.push("Owned by you.");
1589
1589
  } else {
1590
1590
  lines.push(`Live: ${url}`);
@@ -1940,7 +1940,7 @@ export async function runCheckDeploy(ctx, { poll_url, grid } = {}) {
1940
1940
  });
1941
1941
  if (!target) {
1942
1942
  throw new Error(
1943
- "No build to check. Pass poll_url from a grid_plug result, or deploy something first in this session. (Instant inspiration deploys are live on return and have no build to poll.)",
1943
+ "No build to check. Pass poll_url from a grid_plug result, or plug something first in this session. (Instant inspiration plugs are live on return and have no build to poll.)",
1944
1944
  );
1945
1945
  }
1946
1946
  const verdict = await fetchDeployTrace(ctx, { pollUrl: target, grid: gridSlug });
@@ -1953,7 +1953,7 @@ export async function runCheckDeploy(ctx, { poll_url, grid } = {}) {
1953
1953
  }
1954
1954
  if (verdict.status === "failed") {
1955
1955
  return {
1956
- text: `The build FAILED: ${verdict.error || "no reason reported"}. The URL is not live — do not give it to the user as working. Fix the app (or re-deploy) and try again.` +
1956
+ text: `The build FAILED: ${verdict.error || "no reason reported"}. The URL is not live — do not give it to the user as working. Fix the app (or re-plug) and try again.` +
1957
1957
  formatFailureDetail(verdict),
1958
1958
  structured: {
1959
1959
  status: "failed",
@@ -104,7 +104,7 @@ export function registerTools(server, ctx) {
104
104
  }));
105
105
 
106
106
  server.registerResource("cloudgrid-org-picker", GRID_PICKER_URI, {
107
- description: "Grid picker card — lets the user choose which grid to publish into.",
107
+ description: "Grid picker card — lets the user choose which grid to plug into.",
108
108
  mimeType: "text/html;profile=mcp-app",
109
109
  }, async () => ({
110
110
  contents: [{
@@ -194,7 +194,7 @@ export function registerTools(server, ctx) {
194
194
  // acknowledgement.
195
195
  regTool(
196
196
  "grid_note",
197
- "Optionally leave a one-paragraph summary of what you built this session and why. Call it BEFORE a deploy, or in a session that ends without one — a successful deploy has already posted the QA log, so pass grid_plug's session_note instead. Recorded for CloudGrid QA. No side effects.",
197
+ "Optionally leave a one-paragraph summary of what you built this session and why. Call it BEFORE a plug, or in a session that ends without one — a successful plug has already posted the QA log, so pass grid_plug's session_note instead. Recorded for CloudGrid QA. No side effects.",
198
198
  { summary: z.string().describe("A short plain-language summary of what was built and why.") },
199
199
  { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
200
200
  async (input) => {
@@ -229,7 +229,7 @@ export function registerTools(server, ctx) {
229
229
  path: z.string().optional().describe(
230
230
  "Local edition: path to the entity folder, a single file, or a .zip ARCHIVE to upload. " +
231
231
  "A folder is read recursively, honoring .gitignore/.cloudgridignore (plus .git/node_modules " +
232
- "always skipped). A .zip is extracted and deployed: with its own cloudgrid.yaml it deploys " +
232
+ "always skipped). A .zip is extracted and plugged: with its own cloudgrid.yaml it plugs " +
233
233
  "as that project; otherwise it becomes a static app (all files served). Use this for " +
234
234
  "\"deploy this zip\" / \"gallery from these zipped images\" requests. Mutually exclusive with " +
235
235
  "`html` and `artifact_files` — EXCEPT `html` + a .zip of assets: the html becomes index.html " +
@@ -251,7 +251,7 @@ export function registerTools(server, ctx) {
251
251
  "On re-plug, a name: change is a warning only; it never renames the entity or moves the URL.",
252
252
  ),
253
253
  target_entity_id: z.string().optional().describe(
254
- "Present → RE-PLUG: update this exact entity in place (same entity_id, slug, URL, deploy history). " +
254
+ "Present → RE-PLUG: update this exact entity in place (same entity_id, slug, URL, plug history). " +
255
255
  "Absent → CREATE a new entity. This is the durable handle a previous plug returned — persist it. " +
256
256
  "Re-plugging an anonymously-created drop needs its owner_token instead of sign-in.",
257
257
  ),
@@ -279,7 +279,7 @@ export function registerTools(server, ctx) {
279
279
  "target_entity_id). Re-minted on every anonymous edit; always persist the newest one from the result.",
280
280
  ),
281
281
  confirm_new_app: z.boolean().optional().describe(
282
- "Set true to confirm deploying a source that already contains a cloudgrid.yaml as a NEW runtime app. " +
282
+ "Set true to confirm plugging a source that already contains a cloudgrid.yaml as a NEW runtime app. " +
283
283
  "On a create, if the source has a cloudgrid.yaml and this is not set, grid_plug returns needs_confirmation " +
284
284
  "so you can ask the user first (or use target_entity_id to re-plug an existing entity).",
285
285
  ),
@@ -288,7 +288,7 @@ export function registerTools(server, ctx) {
288
288
  "include it by default; omit only if the user asked not to share it.",
289
289
  ),
290
290
  session_note: z.string().optional().describe(
291
- "One short paragraph on what you built and why. Recorded for CloudGrid QA alongside the deploy.",
291
+ "One short paragraph on what you built and why. Recorded for CloudGrid QA alongside the plug.",
292
292
  ),
293
293
  };
294
294
 
@@ -44,7 +44,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;b
44
44
  var html =
45
45
  '<div class="card">' +
46
46
  '<div class="title">Choose a grid</div>' +
47
- '<div class="subtitle">Which grid should this be published to?</div>' +
47
+ '<div class="subtitle">Which grid should this be plugged into?</div>' +
48
48
  '<div class="orgs">';
49
49
  for (var i = 0; i < items.length; i++) {
50
50
  var org = items[i];
@@ -66,7 +66,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;b
66
66
  var all = document.querySelectorAll(".org-btn");
67
67
  for (var k = 0; k < all.length; k++) all[k].classList.add("loading");
68
68
  var statusEl = document.getElementById("status");
69
- if (statusEl) statusEl.textContent = "Publishing\u2026";
69
+ if (statusEl) statusEl.textContent = "Plugging\u2026";
70
70
  if (!window.openai || !window.openai.callTool) return;
71
71
  var input = (window.openai && window.openai.toolInput) || {};
72
72
  var args = {};
@@ -79,7 +79,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;b
79
79
  // The host will render the new result with the live-result card.
80
80
  }).catch(function () {
81
81
  for (var m = 0; m < all.length; m++) all[m].classList.remove("loading");
82
- if (statusEl) statusEl.textContent = "Failed to publish";
82
+ if (statusEl) statusEl.textContent = "Failed to plug";
83
83
  });
84
84
  });
85
85
  })(buttons[j]);