@cloudgrid-io/mcp 0.20.48 → 0.20.49
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 +1 -1
- package/src/corpus/cli-reference.md +1 -1
- package/src/corpus/playbook.md +1 -1
- package/src/corpus/skill-share.md +10 -4
- package/src/tools/constants.js +11 -3
- package/src/tools/deploy.js +106 -43
- package/src/tools/register.js +13 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudgrid-io/mcp",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.49",
|
|
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": {
|
|
@@ -90,7 +90,7 @@ grid grid
|
|
|
90
90
|
| `logs [name]` | Stream entity logs |
|
|
91
91
|
| `open [name]` | Open the entity URL in the browser |
|
|
92
92
|
| `info [name]` / `builds [name]` | Entity metadata; recent deploys |
|
|
93
|
-
| `visibility set <slug> <mode>` | private \|
|
|
93
|
+
| `visibility set <slug> <mode>` | private \| grid \| link — or the axes: `--inside <private\|spaces\|grid> --outside <none\|link\|public>` (+ `--require-signin`, `--space <slug>`) |
|
|
94
94
|
| `rollback` / `versions` | Roll back to a prior deploy; list/tag minted versions |
|
|
95
95
|
| `env` / `secrets` | Manage runtime env vars and secrets (secret values are never printed) |
|
|
96
96
|
| `grid` / `list` | List what's on your hub / org |
|
package/src/corpus/playbook.md
CHANGED
|
@@ -7,7 +7,7 @@ Operating rules:
|
|
|
7
7
|
3b. No grid yet (first-time signed-in user): grid_plug returns needs_grid_create when the account has no grid, and a plug can fail with 403 NO_ACTIVE_ORG. Do NOT send the user to the console — suggest a short slug (3-40 lowercase letters/digits/hyphens, starting with a letter), confirm it with the user (it is permanent and appears in URLs), call grid_create_grid, then re-call grid_plug with grid: <slug>.
|
|
8
8
|
3c. A failed runtime build never loses the work: the source was uploaded before the build ran and lives on the entity. Read the build log (grid_check_deploy) and fix; if it cannot be fixed from this session (hosted, no filesystem), hand the user their files — grid_get_app_source returns a source zip link (source_download_url), and `npx -y @cloudgrid-io/cli@latest pull <grid>/<slug>` downloads the project AND links the folder so the next plug updates the SAME entity locally. Offer one of these instead of abandoning the build or starting over.
|
|
9
9
|
4. Load specifics on demand. Use grid_get_template({kind, name}) to pull the exact workflow, template, or example you need (kind ∈ workflow|template|example|rule|troubleshooting|doc).
|
|
10
|
-
5. Always return the live share URL at the end — that is the deliverable. On a NEW plug, then ASK the user who should be able to open it — private (only you),
|
|
10
|
+
5. Always return the live share URL at the end — that is the deliverable. On a NEW plug, then ASK the user who should be able to open it — private (only you), your grid, or anyone with the link (optionally sign-in required, or search-indexed for public findability; selected spaces via inside: spaces) — and set their choice with grid_visibility. 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. Note the model: visibility is two axes — inside the grid (private | spaces | grid) and outside it (none | link | public); the old 'authenticated' mode is retired (it equals a sign-in-required link) and 'org' is gone (use grid).
|
|
11
11
|
6. Brainstorm first (lightly) for a real app, then minimize questions. For a substantial runtime app, take ONE lightweight beat before generating/plugging: 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.
|
|
12
12
|
7. 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.
|
|
13
13
|
8. 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_plug. As a backstop, grid_plug hard-gates this: an authed create with >1 grid and no chosen grid returns needs_grid (the picker) instead of plugging; 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.
|
|
@@ -40,11 +40,17 @@ The command prints the outlet URL. Hand that URL to the user.
|
|
|
40
40
|
|
|
41
41
|
`grid visibility set <slug> <mode>` accepts:
|
|
42
42
|
|
|
43
|
-
- `link` — anyone with the URL can open it. Use this for sharing.
|
|
43
|
+
- `link` — anyone with the URL can open it. Use this for sharing. Add
|
|
44
|
+
`--require-signin` for signed-in accounts only, `--indexed` to be findable by
|
|
45
|
+
search engines.
|
|
44
46
|
- `private` — only the owner.
|
|
45
|
-
- `
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
- `grid` — everyone in the grid.
|
|
48
|
+
|
|
49
|
+
Finer control uses the two axes instead of a mode:
|
|
50
|
+
`grid visibility set <slug> --inside <private|spaces|grid> --outside <none|link|public> [--space <slug>...] [--require-signin]`
|
|
51
|
+
(`--outside public` = anyone, search-indexed. `authenticated` is retired — it
|
|
52
|
+
equals `--inside private --outside link --require-signin`; `org` is gone — use
|
|
53
|
+
`grid`.)
|
|
48
54
|
|
|
49
55
|
Default to `link` when the user says "share" or "make it public". Confirm before
|
|
50
56
|
using a wider mode than they asked for.
|
package/src/tools/constants.js
CHANGED
|
@@ -29,12 +29,20 @@ export const ANON_HTML_MAX_BYTES = 2_000_000;
|
|
|
29
29
|
export const AUTHED_HTML_MAX_BYTES = 25_000_000;
|
|
30
30
|
export const CONSOLE_URL = "https://console.cloudgrid.io/";
|
|
31
31
|
|
|
32
|
+
// Display labels for visibility values (two-axis model). The OPTIONS list is what
|
|
33
|
+
// the post-plug ask offers; the LABELS map also keeps legacy keys (org,
|
|
34
|
+
// authenticated, space) so an entity's CURRENT stored value still renders — do
|
|
35
|
+
// not offer those as choices.
|
|
36
|
+
export const VISIBILITY_OPTIONS = ["private", "grid", "link"];
|
|
32
37
|
export const VISIBILITY_LABELS = {
|
|
33
38
|
private: "Only you",
|
|
34
|
-
|
|
35
|
-
authenticated: "Anyone signed in",
|
|
36
|
-
space: "A space",
|
|
39
|
+
grid: "Everyone in your grid",
|
|
37
40
|
link: "Anyone with the link",
|
|
41
|
+
// display-only (legacy stored values / axis renderings):
|
|
42
|
+
org: "Everyone in your grid",
|
|
43
|
+
authenticated: "Anyone with the link, sign-in required",
|
|
44
|
+
space: "Selected spaces",
|
|
45
|
+
public: "Anyone, findable by search",
|
|
38
46
|
};
|
|
39
47
|
|
|
40
48
|
// ── Widget resources (ChatGPT Apps SDK, web edition only) ────────────────────
|
package/src/tools/deploy.js
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
AUTHED_HTML_MAX_BYTES,
|
|
14
14
|
CONSOLE_URL,
|
|
15
15
|
VISIBILITY_LABELS,
|
|
16
|
+
VISIBILITY_OPTIONS,
|
|
16
17
|
APPS_WIDGETS_ENABLED,
|
|
17
18
|
GRID_PICKER_URI,
|
|
18
19
|
PLUG_UPLOAD_TIMEOUT_MS,
|
|
@@ -316,8 +317,8 @@ const GUEST_ORG_SLUG = "guest";
|
|
|
316
317
|
// `<slug>--<grid>.cloudgrid.io`), so it must never be the primary source:
|
|
317
318
|
// - inspiration (HTML drops): path-based at the org apex
|
|
318
319
|
// https://<grid>.cloudgrid.io/<slug>
|
|
319
|
-
// - runtime (app/agent):
|
|
320
|
-
// https://<slug
|
|
320
|
+
// - runtime (app/agent): subdomain
|
|
321
|
+
// https://<slug>.<grid>.cloudgrid.io
|
|
321
322
|
// Anonymous drops are grid-less in the response (`grid: null`); they live under
|
|
322
323
|
// the Guest Org, so the apex slug is the constant `guest`.
|
|
323
324
|
function composePlugUrl(data) {
|
|
@@ -326,11 +327,7 @@ function composePlugUrl(data) {
|
|
|
326
327
|
const grid = data?.grid || GUEST_ORG_SLUG;
|
|
327
328
|
const kind = data?.detection?.kind;
|
|
328
329
|
if (kind === "app" || kind === "agent") {
|
|
329
|
-
|
|
330
|
-
// (double-dash), NOT the legacy nested `<slug>.<grid>` form — the latter
|
|
331
|
-
// 404s on every current grid. Still fallback-only; the server's `data.url`
|
|
332
|
-
// remains the primary source (resolvePlugUrl).
|
|
333
|
-
return `https://${slug}--${grid}.cloudgrid.io`;
|
|
330
|
+
return `https://${slug}.${grid}.cloudgrid.io`;
|
|
334
331
|
}
|
|
335
332
|
// inspiration (and any unknown/static kind) — path-based at the org apex.
|
|
336
333
|
return `https://${grid}.cloudgrid.io/${slug}`;
|
|
@@ -1750,14 +1747,14 @@ export async function runPlug(ctx, input, deps = {}) {
|
|
|
1750
1747
|
const current = typeof data.visibility === "string" ? data.visibility : null;
|
|
1751
1748
|
structured.console_url = CONSOLE_URL;
|
|
1752
1749
|
if (current) structured.current_visibility = current;
|
|
1753
|
-
structured.visibility_options =
|
|
1750
|
+
structured.visibility_options = VISIBILITY_OPTIONS.map((v) => ({ value: v, label: VISIBILITY_LABELS[v] }));
|
|
1754
1751
|
lines.push(`Manage all your apps in your grid: ${CONSOLE_URL}`);
|
|
1755
1752
|
lines.push(
|
|
1756
1753
|
`Now ASK the user who should be able to open this${current ? ` (currently ${VISIBILITY_LABELS[current] ?? current})` : ""}, then set their choice with grid_visibility — do not decide it for them. Options: ${
|
|
1757
|
-
|
|
1758
|
-
.map((
|
|
1754
|
+
VISIBILITY_OPTIONS
|
|
1755
|
+
.map((v) => `${v} (${VISIBILITY_LABELS[v]})`)
|
|
1759
1756
|
.join("; ")
|
|
1760
|
-
}.`,
|
|
1757
|
+
}. Finer control: a sign-in-required link (require_signin), search-indexed (indexed), or selected spaces (inside: spaces).`,
|
|
1761
1758
|
);
|
|
1762
1759
|
}
|
|
1763
1760
|
return { text: lines.join("\n"), structured };
|
|
@@ -1848,7 +1845,7 @@ export async function runPickup(ctx, { id, into_org_slug, name, source_version_i
|
|
|
1848
1845
|
// direct API — works on the hosted edition where the CLI-wrapping share tool is
|
|
1849
1846
|
// unavailable. Kind-aware routing (see below). Defaults to the drop made in this
|
|
1850
1847
|
// session, so "make it private" needs no ids.
|
|
1851
|
-
export async function runVisibility(ctx, { target, visibility, kind, org }) {
|
|
1848
|
+
export async function runVisibility(ctx, { target, visibility, inside, outside, require_signin, spaces, indexed, kind, org }) {
|
|
1852
1849
|
const token = await ctx.getToken();
|
|
1853
1850
|
if (!token) {
|
|
1854
1851
|
throw new Error("Changing visibility needs an owner. Run grid_login first.");
|
|
@@ -1865,32 +1862,78 @@ export async function runVisibility(ctx, { target, visibility, kind, org }) {
|
|
|
1865
1862
|
headers["X-CloudGrid-Org"] = orgSlug;
|
|
1866
1863
|
}
|
|
1867
1864
|
|
|
1868
|
-
// Two visibility
|
|
1869
|
-
//
|
|
1870
|
-
//
|
|
1871
|
-
//
|
|
1872
|
-
//
|
|
1873
|
-
//
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1865
|
+
// ── Two-axis visibility model ──────────────────────────────────────
|
|
1866
|
+
// A scope is two independent axes:
|
|
1867
|
+
// inside (share_scope): private | spaces | grid — who in the grid sees it
|
|
1868
|
+
// outside (external_access): none | link | public — reach beyond the grid
|
|
1869
|
+
// require_signin: link only — the link needs a signed-in CloudGrid account
|
|
1870
|
+
// Legacy positional modes (private|grid|link) still ride the { visibility }
|
|
1871
|
+
// body; `authenticated` is RETIRED as a first-class mode and maps to the axis
|
|
1872
|
+
// body it equals (private + link + require_signin); `org` is rejected;
|
|
1873
|
+
// `public` as a mode is an alias of `link` (the axis value `public` is the
|
|
1874
|
+
// indexed one); `space` maps to inside: spaces and needs the `spaces` list.
|
|
1875
|
+
const normSpaces = [...new Set((spaces || []).map((s) => String(s).trim().toLowerCase()).filter(Boolean))];
|
|
1876
|
+
const useAxes = inside !== undefined || outside !== undefined;
|
|
1877
|
+
let body;
|
|
1878
|
+
let requested; // for the result text when the response is sparse
|
|
1879
|
+
if (useAxes) {
|
|
1880
|
+
if (visibility) throw new Error("Pass either `visibility` or the `inside`/`outside` axes, not both.");
|
|
1881
|
+
if (!inside || !outside) {
|
|
1882
|
+
throw new Error("Both axes are required: inside (private|spaces|grid) and outside (none|link|public).");
|
|
1883
|
+
}
|
|
1884
|
+
if (inside === "spaces" && normSpaces.length === 0) {
|
|
1885
|
+
throw new Error("inside: spaces needs at least one space slug in `spaces`.");
|
|
1886
|
+
}
|
|
1887
|
+
if (inside !== "spaces" && normSpaces.length > 0) {
|
|
1888
|
+
throw new Error("`spaces` only applies with inside: spaces.");
|
|
1889
|
+
}
|
|
1890
|
+
if (require_signin === true && outside !== "link") {
|
|
1891
|
+
throw new Error("require_signin only applies when outside is link.");
|
|
1892
|
+
}
|
|
1893
|
+
body = {
|
|
1894
|
+
share_scope: inside,
|
|
1895
|
+
external_access: outside,
|
|
1896
|
+
...(require_signin === true ? { require_signin: true } : {}),
|
|
1897
|
+
...(inside === "spaces" ? { visibility_spaces: normSpaces } : {}),
|
|
1898
|
+
};
|
|
1899
|
+
requested = `inside: ${inside}${inside === "spaces" ? ` (${normSpaces.join(", ")})` : ""}, outside: ${outside}${require_signin === true ? " (sign-in required)" : ""}`;
|
|
1900
|
+
} else {
|
|
1901
|
+
let mode = String(visibility || "").trim().toLowerCase();
|
|
1902
|
+
if (!mode) throw new Error("Pass a visibility mode (private | grid | link), or the inside/outside axes.");
|
|
1903
|
+
if (mode === "org") {
|
|
1904
|
+
throw new Error("'org' visibility is deprecated. Use 'grid' (everyone in the grid).");
|
|
1905
|
+
}
|
|
1906
|
+
if (mode === "public") mode = "link"; // alias; `indexed: true` governs search-indexing
|
|
1907
|
+
if (mode === "authenticated") {
|
|
1908
|
+
// Retired as a first-class mode — the axis body it equals.
|
|
1909
|
+
body = { share_scope: "private", external_access: "link", require_signin: true };
|
|
1910
|
+
requested = "link with sign-in required (the retired 'authenticated')";
|
|
1911
|
+
} else if (mode === "space") {
|
|
1912
|
+
if (normSpaces.length === 0) {
|
|
1913
|
+
throw new Error("'space' visibility needs the `spaces` list (which space slugs can see it) — or use inside: spaces with outside: none.");
|
|
1914
|
+
}
|
|
1915
|
+
body = { share_scope: "spaces", external_access: "none", visibility_spaces: normSpaces };
|
|
1916
|
+
requested = `selected spaces (${normSpaces.join(", ")})`;
|
|
1917
|
+
} else if (mode === "private" || mode === "grid" || mode === "link") {
|
|
1918
|
+
body = { visibility: mode };
|
|
1919
|
+
if (mode === "grid" && normSpaces.length > 0) body.visibility_spaces = normSpaces;
|
|
1920
|
+
if (mode === "link") body.link_indexed = indexed === true;
|
|
1921
|
+
requested = mode + (mode === "link" && indexed === true ? " (search-indexed)" : "");
|
|
1922
|
+
} else {
|
|
1923
|
+
throw new Error(`Unknown visibility '${visibility}'. Use private | grid | link (public = link alias), or the inside/outside axes.`);
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1877
1926
|
|
|
1878
1927
|
const k = kind || ctx.state.lastDrop?.kind || null;
|
|
1879
1928
|
const isRuntimeKind = k === "app" || k === "agent";
|
|
1880
1929
|
|
|
1881
|
-
|
|
1882
|
-
throw new Error(
|
|
1883
|
-
"'space' visibility isn't available for runtime apps/agents. Use grid, authenticated, private, or link.",
|
|
1884
|
-
);
|
|
1885
|
-
}
|
|
1886
|
-
|
|
1887
|
-
const patch = async (pathName, value) => {
|
|
1930
|
+
const patch = async (pathName) => {
|
|
1888
1931
|
let res;
|
|
1889
1932
|
try {
|
|
1890
1933
|
res = await fetch(`${API_BASE}${pathName}`, {
|
|
1891
1934
|
method: "PATCH",
|
|
1892
1935
|
headers,
|
|
1893
|
-
body: JSON.stringify(
|
|
1936
|
+
body: JSON.stringify(body),
|
|
1894
1937
|
});
|
|
1895
1938
|
} catch (err) {
|
|
1896
1939
|
throw new Error(`Could not reach CloudGrid at ${API_BASE}: ${err.message}`);
|
|
@@ -1901,33 +1944,53 @@ export async function runVisibility(ctx, { target, visibility, kind, org }) {
|
|
|
1901
1944
|
return { res, data, raw };
|
|
1902
1945
|
};
|
|
1903
1946
|
|
|
1947
|
+
// BOTH realms now take the same realm-scoped visibility PATCH with the
|
|
1948
|
+
// same body vocabulary: /api/v2/entities/:id/visibility (runtimes) and
|
|
1949
|
+
// /api/v2/inspirations/:id/visibility (inspirations).
|
|
1904
1950
|
const runtimePath = `/api/v2/entities/${encodeURIComponent(id)}/visibility`;
|
|
1905
|
-
const inspirationPath = `/api/v2/inspirations/${encodeURIComponent(id)}`;
|
|
1951
|
+
const inspirationPath = `/api/v2/inspirations/${encodeURIComponent(id)}/visibility`;
|
|
1906
1952
|
|
|
1907
|
-
// Route order
|
|
1908
|
-
// to the
|
|
1909
|
-
//
|
|
1910
|
-
// inspiration route on a not-found (mirrors runPickup).
|
|
1953
|
+
// Route order: a known runtime kind goes straight to the entities route; a
|
|
1954
|
+
// known inspiration to the inspiration route; unknown tries runtime first and
|
|
1955
|
+
// falls back on a not-found (mirrors runPickup).
|
|
1911
1956
|
let order;
|
|
1912
|
-
if (
|
|
1913
|
-
else if (isRuntimeKind) order = ["runtime"];
|
|
1957
|
+
if (isRuntimeKind) order = ["runtime"];
|
|
1914
1958
|
else if (k === "inspiration") order = ["inspiration"];
|
|
1915
1959
|
else order = ["runtime", "inspiration"];
|
|
1916
1960
|
|
|
1917
1961
|
let last;
|
|
1918
1962
|
for (let i = 0; i < order.length; i++) {
|
|
1919
1963
|
const route = order[i];
|
|
1920
|
-
last = route === "runtime"
|
|
1921
|
-
? await patch(runtimePath, runtimeValue)
|
|
1922
|
-
: await patch(inspirationPath, inspirationValue);
|
|
1964
|
+
last = await patch(route === "runtime" ? runtimePath : inspirationPath);
|
|
1923
1965
|
if (last.res.ok) {
|
|
1924
|
-
const
|
|
1925
|
-
|
|
1966
|
+
const d = last.data || {};
|
|
1967
|
+
// Prefer the server's stored axes (stored axes are authoritative on
|
|
1968
|
+
// the wire); fall back to what we asked for.
|
|
1969
|
+
const lines = [];
|
|
1970
|
+
if (d.share_scope || d.external_access) {
|
|
1971
|
+
const insideLine =
|
|
1972
|
+
d.share_scope === "private" ? "only the owner" :
|
|
1973
|
+
d.share_scope === "spaces" ? `selected spaces${Array.isArray(d.visibility_spaces) && d.visibility_spaces.length ? ` (${d.visibility_spaces.join(", ")})` : ""}` :
|
|
1974
|
+
d.share_scope === "grid" ? "everyone in the grid" : d.share_scope;
|
|
1975
|
+
const outsideLine =
|
|
1976
|
+
d.external_access === "none" ? "no one outside the grid" :
|
|
1977
|
+
d.external_access === "link" ? `anyone with the link${d.require_signin ? " (signed-in accounts only)" : ""}${d.link_indexed ? ", search-indexed" : ""}` :
|
|
1978
|
+
d.external_access === "public" ? "anyone, findable by search engines" : d.external_access;
|
|
1979
|
+
lines.push(`Visibility set — inside the grid: ${insideLine}; outside: ${outsideLine}.`);
|
|
1980
|
+
} else {
|
|
1981
|
+
lines.push(`Visibility is now ${d.visibility || requested}.`);
|
|
1982
|
+
}
|
|
1983
|
+
if (d.url) lines.push(d.url);
|
|
1926
1984
|
return {
|
|
1927
1985
|
text: lines.join("\n"),
|
|
1928
1986
|
structured: {
|
|
1929
|
-
visibility:
|
|
1930
|
-
...(
|
|
1987
|
+
visibility: d.visibility || (useAxes ? undefined : String(visibility || "").trim().toLowerCase() || undefined),
|
|
1988
|
+
...(d.share_scope ? { share_scope: d.share_scope } : {}),
|
|
1989
|
+
...(d.external_access ? { external_access: d.external_access } : {}),
|
|
1990
|
+
...(d.require_signin !== undefined ? { require_signin: d.require_signin === true } : {}),
|
|
1991
|
+
...(Array.isArray(d.visibility_spaces) ? { visibility_spaces: d.visibility_spaces } : {}),
|
|
1992
|
+
...(d.link_indexed !== undefined ? { link_indexed: d.link_indexed === true } : {}),
|
|
1993
|
+
...(d.url ? { url: d.url } : {}),
|
|
1931
1994
|
},
|
|
1932
1995
|
};
|
|
1933
1996
|
}
|
package/src/tools/register.js
CHANGED
|
@@ -659,15 +659,25 @@ export function registerTools(server, ctx) {
|
|
|
659
659
|
reg(
|
|
660
660
|
"grid_visibility",
|
|
661
661
|
{
|
|
662
|
-
description: "Change who can see a CloudGrid inspiration OR runtime app/agent: private
|
|
662
|
+
description: "Change who can see a CloudGrid inspiration OR runtime app/agent. Simple modes: private (only the user), grid (everyone in their grid), link (anyone with the URL — add indexed: true to be findable by search engines). Finer control via the TWO AXES instead: inside (who in the grid: private | spaces | grid) and outside (reach beyond it: none | link | public), with require_signin for a members-only link and `spaces` for selected spaces. 'authenticated' is retired (it maps to a sign-in-required link); 'org' is gone — use grid. Use when the user wants to make something private, restrict who sees it, or open it up — including right after a drop, with no target id needed. Kind-aware routing across both surfaces. Defaults to the drop made in this session. Requires sign-in. Calls the API directly.",
|
|
663
663
|
inputSchema: {
|
|
664
|
-
visibility: z.enum(["private", "
|
|
664
|
+
visibility: z.enum(["private", "grid", "link", "public", "authenticated", "space"]).optional().describe("Simple mode: private | grid | link ('public' is an alias of link — pass indexed: true for search-findable; 'authenticated' is the retired alias for a sign-in-required link; 'space' needs the `spaces` list). Pass either this OR the inside/outside axes."),
|
|
665
|
+
inside: z.enum(["private", "spaces", "grid"]).optional().describe("Axis 1 — who in the grid can see it: private (only the user), spaces (selected spaces — pass `spaces`), or grid (everyone in the grid). Use together with `outside`, instead of `visibility`."),
|
|
666
|
+
outside: z.enum(["none", "link", "public"]).optional().describe("Axis 2 — reach beyond the grid: none, link (anyone with the link; add require_signin: true for signed-in accounts only), or public (anyone, and findable by search engines)."),
|
|
667
|
+
require_signin: z.boolean().optional().describe("With outside: link (or visibility: link) — the link requires a signed-in CloudGrid account."),
|
|
668
|
+
spaces: z.array(z.string()).optional().describe("Space slugs, for inside: spaces (or the legacy space/grid modes)."),
|
|
669
|
+
indexed: z.boolean().optional().describe("With visibility: link — make the page search-engine indexable."),
|
|
665
670
|
target: z.string().optional().describe("Entity id. Defaults to this session's last drop."),
|
|
666
671
|
kind: z.enum(["inspiration", "app", "agent"]).optional().describe("Entity kind. Omit to auto-detect from this session's last drop (falls back to trying the runtime surface, then the inspiration surface)."),
|
|
667
672
|
org: z.string().optional().describe("Grid of the entity. Defaults to the active grid."),
|
|
668
673
|
},
|
|
669
674
|
outputSchema: {
|
|
670
|
-
visibility: z.string().describe("The
|
|
675
|
+
visibility: z.string().optional().describe("The legacy mode that was set, when a simple mode was used."),
|
|
676
|
+
share_scope: z.string().optional().describe("Stored axis: who in the grid (private | spaces | grid)."),
|
|
677
|
+
external_access: z.string().optional().describe("Stored axis: reach beyond the grid (none | link | public)."),
|
|
678
|
+
require_signin: z.boolean().optional().describe("Whether the link requires sign-in."),
|
|
679
|
+
visibility_spaces: z.array(z.string()).optional().describe("The space slugs, when share_scope is spaces."),
|
|
680
|
+
link_indexed: z.boolean().optional().describe("Whether the link is search-indexed."),
|
|
671
681
|
url: z.string().optional().describe("URL of the entity, if returned."),
|
|
672
682
|
},
|
|
673
683
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|