@cloudgrid-io/mcp 0.6.1 → 0.7.0

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/README.md CHANGED
@@ -54,8 +54,11 @@ It speaks MCP over stdio. Point any MCP client at the `cloudgrid-mcp` command.
54
54
 
55
55
  | Tool | Wraps | Notes |
56
56
  |---|---|---|
57
- | `cloudgrid_drop` | `POST /api/v2/drop/auto` | Artifact drop. Anonymous, or owned if signed in. Direct API. |
58
- | `cloudgrid_claim` | `POST /api/v2/anon-claim` | Claim an anonymous drop into the signed-in account. Direct API. |
57
+ | `gridctl_plug` | `POST /api/v2/plug` | The unified create/re-plug verb: create a new entity, or update the SAME entity in place with `target_entity_id` (same URL). Source via local `path` (local edition) or inline `artifact_files` (both). |
58
+ | `gridctl_drop` | `POST /api/v2/plug` | Artifact drop. Anonymous, or owned if signed in. Re-drops in a session update the same drop in place; anonymous drops return an `entity_id` + `owner_token` re-plug/claim handle. |
59
+ | `gridctl_claim` | `POST /api/v2/entities/:id/pickup` | Claim an anonymous drop into the signed-in account (the claim token IS the drop's owner token). Direct API. |
60
+ | `gridctl_fork` | `POST /api/v2/runtimes/:id/fork` | Start a new entity from an existing runtime (lineage recorded). Needs sign-in. |
61
+ | `gridctl_download` | `GET /api/v2/runtimes/:id/source` | Signed 15-minute source-bundle URLs. Needs sign-in. |
59
62
  | `cloudgrid_login` | `GET /auth/login` | Start a CLI-free sign-in; returns a URL to open. Direct API. |
60
63
  | `cloudgrid_login_status` | `GET /auth/status` | Finish the sign-in; saves the token to the shared CLI credentials. |
61
64
  | `cloudgrid_visibility` | `PATCH /api/v2/inspirations/<id>` | Change who can see a drop (private, space, authenticated, org, link). Needs sign-in. Direct API; also in the web edition. |
@@ -70,7 +73,6 @@ also work in the web edition where no CLI exists. `cloudgrid_login` writes the s
70
73
  | Tool | Wraps | Notes |
71
74
  |---|---|---|
72
75
  | `cloudgrid_init` | `cloudgrid init` | Register an app or agent; optionally seed a web service. |
73
- | `cloudgrid_plug` | `cloudgrid plug` | Deploy a directory or URL. |
74
76
  | `cloudgrid_logs` | `cloudgrid logs` | Snapshot of recent logs. Does not stream. Read-only. |
75
77
  | `cloudgrid_share` | `cloudgrid visibility set` | Set visibility, default link. |
76
78
  | `cloudgrid_feedback` | `cloudgrid feedback list` | Read the org feedback feed. Read-only. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudgrid-io/mcp",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "MCP server for CloudGrid. Three editions: a local stdio server (full toolset), a hosted web server (light, CLI-free toolset), and a public docs server (search_cloudgrid_documentation) over MCP Streamable HTTP.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,6 +16,7 @@
16
16
  "start": "node src/index.js",
17
17
  "start:web": "node src/web.js",
18
18
  "smoke": "node test/smoke.mjs",
19
+ "test:plug-wire": "node test/plug-wire.test.mjs",
19
20
  "test:drift-guard": "node test/drift-guard.mjs",
20
21
  "smoke:drop": "node test/smoke-drop.mjs",
21
22
  "smoke:login": "node test/smoke-login.mjs",
@@ -71,10 +71,28 @@ curl -sS -X POST https://api.cloudgrid.io/api/v2/plug \
71
71
  -F "artifact=@./index.html;type=text/html"
72
72
  ```
73
73
 
74
- The response includes `slug` (the live link is `https://guest.cloudgrid.io/<slug>`)
75
- and `claim_url` (sign in within 7 days to keep it). This is what the `cloudgrid-drop`
76
- skill and the `cloudgrid_drop` MCP tool do for you. It is anonymous and serves
77
- inspirations only; a full app needs the signed-in `plug` flow above.
74
+ The response includes `url` (the live link — use it verbatim), `entity_id`,
75
+ `owner_token` (keep both to update the drop later), and `claim_url` (sign in
76
+ before it expires to keep it). This is what the `cloudgrid-drop` skill and the
77
+ `cloudgrid_drop` MCP tool do for you. It is anonymous and serves inspirations
78
+ only; a full app needs the signed-in `plug` flow above.
79
+
80
+ ## Update your drop in place
81
+
82
+ Re-plugging with `target_entity_id` updates the SAME entity — same slug, same URL,
83
+ new content. Iterate on one link instead of minting a new one per revision:
84
+
85
+ ```
86
+ curl -sS -X POST https://api.cloudgrid.io/api/v2/plug \
87
+ -F "target_entity_id=$ENTITY_ID" \
88
+ -F "owner_token=$OWNER_TOKEN" \
89
+ -F "artifact=@./index.html;type=text/html"
90
+ ```
91
+
92
+ Signed in, drop the `owner_token` field and send your auth headers instead. Each
93
+ anonymous edit returns a refreshed `owner_token` (store the new one) and resets
94
+ the drop's expiry. Editing an archived or expired drop returns 409
95
+ `EDIT_REJECTED`; omit `target_entity_id` when you actually want a fresh link.
78
96
 
79
97
  ## Shorter chains
80
98
 
@@ -34,9 +34,13 @@ npx skills add cloudgrid-io/skills
34
34
 
35
35
  ```
36
36
  /plugin marketplace add cloudgrid-io/skills
37
+ /plugin install cloudgrid@cloudgrid-skills
37
38
  ```
38
39
 
39
- The marketplace manifest lives in `.claude-plugin/`.
40
+ The marketplace manifest lives in `.claude-plugin/` (marketplace name:
41
+ `cloudgrid-skills`, plugin name: `cloudgrid`). Installing the plugin bundles the
42
+ skills, the SessionStart orientation hook, and the CloudGrid MCP server — the MCP
43
+ auto-starts when the plugin is enabled, so no separate `claude mcp add` is needed.
40
44
 
41
45
  ### Codex
42
46
 
@@ -14,7 +14,7 @@ allowed-tools: Bash
14
14
 
15
15
  Turn an anonymous drop into an owned one. After an anonymous drop, the user has a
16
16
  `claim_url` (or token) plus the drop's `entity_id`. Once they sign in, claiming
17
- transfers ownership to them and extends the expiry from 7 days to 30. Claiming
17
+ transfers ownership to them and resets the expiry window. Claiming
18
18
  re-homes the drop into the user's grid, so its public URL changes from
19
19
  `guest.cloudgrid.io/<slug>` to `<grid>.cloudgrid.io/<slug>` — share the new link.
20
20
 
@@ -26,11 +26,17 @@ skill (or `cloudgrid login` with the CLI) first.
26
26
  ## What you need
27
27
 
28
28
  Two things: the **entity id** of the anonymous drop (the `entity_id` field the drop
29
- returned), and the **claim token** — the `token` query parameter inside the
30
- `claim_url` the drop returned, e.g. `https://console.cloudgrid.io/claim?token=<TOKEN>`.
29
+ returned), and the **claim token**. The claim token is the drop's `owner_token` —
30
+ the same JWT used for anonymous re-plugs. It also appears as the `token` query
31
+ parameter inside the `claim_url` the drop returned, e.g.
32
+ `https://console.cloudgrid.io/claim?token=<TOKEN>`.
31
33
  A browser that still holds the `cg_anon_session` cookie from the drop can claim
32
34
  without a token instead.
33
35
 
36
+ Note: every anonymous re-plug (edit) of the drop refreshes the `owner_token` and
37
+ resets the drop's expiry. Always claim with the token from the LATEST drop or
38
+ edit response — an older token may have been superseded.
39
+
34
40
  ## How to run it
35
41
 
36
42
  Claiming is now a "pickup" of the entity into your grid. The entity id goes in the
@@ -4,8 +4,9 @@ name: drop
4
4
  description: |
5
5
  Share an artifact and get a public URL. Use when the user wants to share,
6
6
  publish, send, or deploy an HTML page or file, or wants a link for a friend.
7
- Works with no login (anonymous, 7-day, claimable later) or signed in (published
8
- into the user's org, owned, 30-day). Inspirations only.
7
+ Works with no login (anonymous, claimable later) or signed in (published
8
+ into the user's org, owned). Re-plugging updates the same URL in place.
9
+ Inspirations only.
9
10
  argument-hint: "[file]"
10
11
  allowed-tools: Bash
11
12
  ---
@@ -50,18 +51,19 @@ curl -sS -X POST https://api.cloudgrid.io/api/v2/plug \
50
51
 
51
52
  The response is JSON (HTTP 201 for an anonymous drop). Read these fields:
52
53
 
53
- - `slug` — the entity's public slug. An anonymous inspiration's live link is
54
- `https://guest.cloudgrid.io/<slug>`. The response has no ready-made `url`;
55
- compose it from the slug. (Apps/agents would be `https://<slug>.<grid>.cloudgrid.io`,
56
- but anonymous drops are always inspirations.)
57
- - `claim_url` — the link to sign in and keep it past the 7-day expiry.
54
+ - `url` — the live link, composed by the server. Use it verbatim; never compose a
55
+ URL from the slug yourself.
56
+ - `entity_id` — the durable handle for updating this drop later (see re-plug below).
57
+ - `owner_token` — a JWT proving you made this drop. It lets you re-plug the drop
58
+ anonymously and doubles as the claim token. Its lifetime matches the drop's
59
+ expiry (default 7 days). Persist it together with `entity_id` and `url`.
60
+ - `claim_url` — the link to sign in and keep the drop past its expiry.
58
61
  - `claim_message` — a ready-to-show nudge to sign in and claim.
59
62
 
60
63
  ## If the user is signed in
61
64
 
62
65
  A signed-in user can publish into their own org instead of anonymously — the drop
63
- is owned, lasts 30 days, and needs no claim. Add their token and org to the same
64
- request:
66
+ is owned and needs no claim. Add their token and org to the same request:
65
67
 
66
68
  ```
67
69
  JWT=$(jq -r .jwt ~/.cloudgrid/credentials 2>/dev/null)
@@ -71,30 +73,63 @@ curl -sS -X POST https://api.cloudgrid.io/api/v2/plug \
71
73
  -F "artifact=@/path/to/index.html;type=text/html"
72
74
  ```
73
75
 
74
- A signed-in drop returns HTTP 202 with `slug` + `grid` and no `claim_url` (it is
75
- already owned). Its live link is `https://<grid>.cloudgrid.io/<slug>` for an
76
- inspiration. The org is taken from the `X-CloudGrid-Org` header — there is no
76
+ A signed-in drop returns HTTP 202 with `entity_id`, `url`, `slug` + `grid` and no
77
+ `claim_url` (it is already owned). Use the returned `url` as the live link — do
78
+ not compose it. The org is taken from the `X-CloudGrid-Org` header — there is no
77
79
  `org_slug` form field. If the user is a member of several orgs and the header is
78
80
  missing, the API replies with the list of orgs to choose from. The MCP
79
81
  `cloudgrid_drop` tool does this automatically when credentials are present.
80
82
 
81
- ## One drop = one entity (no in-place re-drop)
83
+ ## Re-plug: update the same URL in place
82
84
 
83
- The unified `/api/v2/plug` endpoint is create-only for this flow: every drop mints
84
- a NEW entity with a NEW URL. There is no `previous_id` / in-place-update path and no
85
- `202 unchanged` no-op — those belonged to the retired `/drop/auto` endpoint. To
86
- publish an update, drop again; you get a fresh link. (To update an existing app in
87
- place, sign in and use `cloudgrid:plug`, which targets the entity by name.)
85
+ `/api/v2/plug` is a unified create-or-update endpoint. The switch is the
86
+ `target_entity_id` form field:
88
87
 
89
- The MCP `cloudgrid_drop` tool accepts a `fresh` flag for backward compatibility,
90
- but it is now a no-op — each drop is already a fresh create.
88
+ - **Absent** → create: a new entity, a new URL.
89
+ - **Present** → re-plug: the SAME entity is updated — same slug, same URL, new
90
+ content. This is how you iterate on one shareable link.
91
+
92
+ Signed in, re-plug with the entity id and your normal auth headers:
93
+
94
+ ```
95
+ curl -sS -X POST https://api.cloudgrid.io/api/v2/plug \
96
+ -H "Authorization: Bearer $JWT" -H "X-CloudGrid-Org: $ORG" \
97
+ -F "target_entity_id=$ENTITY_ID" \
98
+ -F "artifact=@/path/to/index.html;type=text/html"
99
+ ```
100
+
101
+ Anonymously, prove ownership with the `owner_token` the drop returned:
102
+
103
+ ```
104
+ curl -sS -X POST https://api.cloudgrid.io/api/v2/plug \
105
+ -F "target_entity_id=$ENTITY_ID" \
106
+ -F "owner_token=$OWNER_TOKEN" \
107
+ -F "artifact=@/path/to/index.html;type=text/html"
108
+ ```
109
+
110
+ Rules that matter:
111
+
112
+ - `entity_id` + `url` (+ `owner_token` when anonymous) are the durable re-plug
113
+ handle. Persist them after every drop.
114
+ - Every anonymous edit REFRESHES the `owner_token` — store the one from the
115
+ latest response; the old one is superseded. Each edit also resets the drop's
116
+ expiry window.
117
+ - Editing an archived or expired drop returns **409 `EDIT_REJECTED`** — it never
118
+ silently creates a new entity. Drop again (without `target_entity_id`) if the
119
+ user wants a new link.
120
+ - An anonymous edit without a valid `owner_token` returns **401**.
121
+ - Anonymous edits count against the same daily anonymous cap as creates.
122
+ - Only re-plug when the user is iterating on an existing artifact. If they want a
123
+ separate new link, omit `target_entity_id` (the MCP `cloudgrid_drop` tool's
124
+ `fresh` flag does the same: it forces a new entity instead of updating).
91
125
 
92
126
  ## After the drop
93
127
 
94
- Print the composed `url` (e.g. `https://guest.cloudgrid.io/<slug>`) on its own line,
95
- by itself, so it can be copied in one go. Then add one line of context: an anonymous
96
- drop lasts 7 days and can be claimed to keep it; a signed-in drop is already owned.
97
- Do not bury the URL in prose.
128
+ Print the `url` from the response on its own line, by itself, so it can be copied
129
+ in one go. Then add one line of context: an anonymous drop expires (default 7 days,
130
+ reset on every edit) and can be claimed to keep it; a signed-in drop is already
131
+ owned. Do not bury the URL in prose. Keep `entity_id` (and `owner_token` if
132
+ anonymous) so a follow-up "change X" can re-plug the same URL.
98
133
 
99
134
  ## Limits and errors
100
135
 
@@ -25,16 +25,21 @@ behalf: scaffold, deploy, tail logs, share, read feedback. Everything here is fr
25
25
  cloudgrid login
26
26
  ```
27
27
 
28
- 3. Add the skills. In Claude Code (recommended):
28
+ 3. Add the agent-core. In Claude Code (recommended):
29
29
 
30
30
  ```
31
31
  /plugin marketplace add cloudgrid-io/skills
32
- /plugin install cloudgrid
32
+ /plugin install cloudgrid@cloudgrid-skills
33
33
  ```
34
34
 
35
- They show under `/plugin` and `/skills` as `cloudgrid:drop`, `cloudgrid:login`,
36
- … — or just say what you want ("drop this HTML to CloudGrid") and the right one
37
- triggers.
35
+ One install wires up everything: the skills, the SessionStart orientation
36
+ hook, and the CloudGrid MCP server (`gridctl_start`, `gridctl_fetch`, and the
37
+ CLI-wrapping tools). The MCP auto-starts when the plugin is enabled — no
38
+ separate `claude mcp add` needed.
39
+
40
+ The skills show under `/plugin` and `/skills` as `cloudgrid:drop`,
41
+ `cloudgrid:login`, … — or just say what you want ("drop this HTML to
42
+ CloudGrid") and the right one triggers.
38
43
 
39
44
  Or install with the `gh skill` extension:
40
45
 
@@ -82,9 +87,11 @@ walks through it end to end.
82
87
 
83
88
  ## MCP server
84
89
 
85
- The MCP server is published separately as
90
+ The Claude Code plugin above already bundles the MCP server — installing
91
+ `cloudgrid@cloudgrid-skills` starts it automatically. For every other client, the
92
+ MCP server is published separately as
86
93
  [`@cloudgrid-io/mcp`](https://github.com/cloudgrid-io/mcp). It exposes the same
87
- nine actions as MCP tools, for agents that speak the Model Context Protocol.
94
+ actions as MCP tools, for agents that speak the Model Context Protocol.
88
95
  Install it with `npx -y @cloudgrid-io/mcp`, or point a remote-capable client at
89
96
  `https://mcp.cloudgrid.io/mcp`. See [USAGE.md](USAGE.md) for per-client setup.
90
97
 
@@ -128,7 +128,7 @@ You can install both; they do not conflict.
128
128
 
129
129
  | Action | What it does |
130
130
  |---|---|
131
- | drop | Share an artifact, get a public URL. No login needed (anonymous, 7-day) or owned if signed in (30-day). |
131
+ | drop | Share an artifact, get a public URL. No login needed (anonymous, claimable) or owned if signed in. Re-drop with the entity id to update the same URL. |
132
132
  | login | Sign in to CloudGrid, with or without the CLI. |
133
133
  | claim | Claim an anonymous drop into your account; the URL stays the same. |
134
134
  | init | Scaffold a new app or agent. |
@@ -27,5 +27,7 @@ this recipe. Do not ask setup questions first; use sensible defaults and build.
27
27
  A dashboard is an inspiration and deploys synchronously, so you get a URL
28
28
  right away.
29
29
  5. **Return the live share URL.** Give the user the URL that serves the dashboard.
30
+ For revisions, re-deploy with the entity id from the first deploy — it updates
31
+ the same share URL, so the user iterates on one link.
30
32
 
31
33
  Keep the whole flow tight: fetch, fill, deploy, share.
@@ -25,5 +25,7 @@ this recipe. Do not ask setup questions first; use sensible defaults and build.
25
25
  A landing page is an inspiration and deploys synchronously, so you get a URL
26
26
  right away.
27
27
  5. **Return the live share URL.** Give the user the URL that serves the page.
28
+ For revisions, re-deploy with the entity id from the first deploy — it updates
29
+ the same share URL, so the user iterates on one link.
28
30
 
29
31
  Keep the whole flow tight: fetch, fill, deploy, share.
@@ -24,5 +24,7 @@ this recipe. Do not ask setup questions first; use sensible defaults and build.
24
24
  An HTML deck is an inspiration and deploys synchronously, so you get a URL
25
25
  right away.
26
26
  5. **Return the live share URL.** Give the user the URL that serves the deck.
27
+ For revisions, re-deploy with the entity id from the first deploy — it updates
28
+ the same share URL, so the user iterates on one link.
27
29
 
28
30
  Keep the whole flow tight: fetch, fill, deploy, share.
@@ -27,5 +27,7 @@ this recipe. Do not ask setup questions first; use sensible defaults and build.
27
27
  A report is an inspiration and deploys synchronously, so you get a URL right
28
28
  away.
29
29
  5. **Return the live share URL.** Give the user the URL that serves the report.
30
+ For revisions, re-deploy with the entity id from the first deploy — it updates
31
+ the same share URL, so the user iterates on one link.
30
32
 
31
33
  Keep the whole flow tight: fetch, fill, deploy, share.
@@ -27,5 +27,7 @@ build.
27
27
  A web app is an inspiration and deploys synchronously, so you get a URL
28
28
  right away.
29
29
  5. **Return the live share URL.** Give the user the URL that serves the app.
30
+ For revisions, re-deploy with the entity id from the first deploy — it updates
31
+ the same share URL, so the user iterates on one link.
30
32
 
31
33
  Keep the whole flow tight: fetch, adapt, deploy, share.