Skip to content

Commit be5da4a

Browse files
v0.9.0 — add create_deploy + 4 deploy management tools (#4)
Agents previously had to read docs to learn the POST /deploy/new multipart endpoint. This adds a first-class tool that takes a base64-encoded gzip tarball and returns a public URL, plus list/get/ redeploy/delete tools so the full deploy lifecycle is reachable from an MCP client. resource_bindings is documented as "agent passes resource tokens; api resolves server-side" — the client never pre-resolves tokens to connection URLs, which would leak secrets into tool params. Tools: 11 → 16. Adds requestMultipart() helper to client.ts.
1 parent b8dcfda commit be5da4a

6 files changed

Lines changed: 633 additions & 10 deletions

File tree

README.md

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ One tool call per resource type, each returning a drop-in connection string:
1515
(backed by DigitalOcean Spaces)
1616
- **Webhook receiver** (`create_webhook`) → public URL that stores every
1717
inbound request
18+
- **Container deployment** (`create_deploy`) → upload a base64 gzip tarball
19+
(Dockerfile + source), get back a public URL in ~30s. Bind any of the
20+
resources above by passing their tokens as `resource_bindings` — the API
21+
resolves tokens to connection URLs server-side.
1822

1923
Every anonymous resource auto-expires in 24h. The provision response carries
2024
a `note` and `upgrade` field — the MCP server surfaces both verbatim so the
@@ -94,7 +98,7 @@ to reach for this MCP, see <https://instanode.dev/agent.html>.
9498

9599
| Variable | Required | Default | Purpose |
96100
|---------------------------|----------|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
97-
| `INSTANODE_TOKEN` | No | — | Bearer JWT minted at <https://instanode.dev/dashboard>. Required for `list_resources`, `claim_token`, `delete_resource`, and `get_api_token`. Unlocks paid-tier limits on every `create_*`. |
101+
| `INSTANODE_TOKEN` | No | — | Bearer JWT minted at <https://instanode.dev/dashboard>. Required for `list_resources`, `claim_token`, `delete_resource`, `get_api_token`, and all deploy tools (`create_deploy`, `list_deployments`, `get_deployment`, `redeploy`, `delete_deployment`). Unlocks paid-tier limits on every `create_*`. |
98102
| `INSTANODE_API_URL` | No | `https://api.instanode.dev` | Override the API base URL. Only set this for local development against a k3s cluster. |
99103
| `INSTANODE_DASHBOARD_URL` | No | `https://instanode.dev` | Override the dashboard host that `claim_resource` builds claim URLs against. Only set this for staging. |
100104

@@ -108,12 +112,69 @@ to reach for this MCP, see <https://instanode.dev/agent.html>.
108112
| `create_queue` | `POST /queue/new` — Provision a NATS JetStream queue (scoped subject namespace). Returns `connection_url` + `note`/`upgrade`. `name` required. |
109113
| `create_storage` | `POST /storage/new` — Provision an S3-compatible bucket prefix (DigitalOcean Spaces). Returns endpoint, access keys, prefix + `note`/`upgrade`. `name` required. |
110114
| `create_webhook` | `POST /webhook/new` — Provision an inbound webhook receiver URL. Returns `receive_url` + `note`/`upgrade`. `name` required. |
115+
| `create_deploy` | `POST /deploy/new` — Upload a base64 gzip tarball (with Dockerfile) and deploy a container. Returns `deploy_id`, `status`, `url`, `build_logs_url`. Requires `INSTANODE_TOKEN`. |
116+
| `list_deployments`| `GET /api/v1/deployments` — List all deployments on the caller's team. Requires `INSTANODE_TOKEN`. |
117+
| `get_deployment` | `GET /api/v1/deployments/:id` — Fetch one deployment (poll until `status="running"`). Requires `INSTANODE_TOKEN`. |
118+
| `redeploy` | `POST /deploy/:id/redeploy` — Rebuild + rolling update an existing deployment. Requires `INSTANODE_TOKEN`. |
119+
| `delete_deployment` | `DELETE /deploy/:id` — Tear down a running deployment. Irreversible. Requires `INSTANODE_TOKEN`. |
111120
| `claim_resource` | Helper — turn an `upgrade_jwt` from any `create_*` response into the dashboard claim URL the user should click. No API call. No auth required. |
112121
| `claim_token` | `POST /api/me/claim` — Programmatic claim: attach an anonymous resource to the authenticated account by its UUID `token`. Requires `INSTANODE_TOKEN`. |
113122
| `list_resources` | `GET /api/me/resources` — List resources on the caller's account. Requires `INSTANODE_TOKEN`. |
114123
| `delete_resource` | `DELETE /api/me/resources/{token}` — Hard-delete a resource you own. Paid tier only. Requires `INSTANODE_TOKEN`. |
115124
| `get_api_token` | `GET /api/me/token` — Mint a fresh 30-day bearer JWT (for rotation). Requires an existing `INSTANODE_TOKEN`. |
116125

126+
### Container deployment (`create_deploy`)
127+
128+
Deploying is a single multipart/form-data POST with a base64-encoded gzip
129+
tarball of the project (Dockerfile + source). The MCP tool handles the
130+
encoding plumbing; the agent's job is just to construct the tarball.
131+
132+
**Building the tarball (any language):**
133+
134+
```python
135+
import base64, subprocess
136+
tar = subprocess.check_output(["tar", "czf", "-", "-C", project_dir, "."])
137+
tarball_base64 = base64.b64encode(tar).decode()
138+
```
139+
140+
```js
141+
import { execFileSync } from "node:child_process";
142+
const tar = execFileSync("tar", ["czf", "-", "-C", projectDir, "."]);
143+
const tarball_base64 = tar.toString("base64");
144+
```
145+
146+
Cap: 50 MB after decode. Honor `.dockerignore` — only ship what
147+
`docker build` needs.
148+
149+
**Binding provisioned resources:**
150+
151+
Provision the resources first with `create_postgres` / `create_cache` / etc.
152+
to get their tokens (UUIDs), then pass the tokens as `resource_bindings`:
153+
154+
```json
155+
{
156+
"tarball_base64": "...",
157+
"name": "my-app",
158+
"port": 8080,
159+
"resource_bindings": {
160+
"DATABASE_URL": "<token from create_postgres>",
161+
"REDIS_URL": "<token from create_cache>"
162+
}
163+
}
164+
```
165+
166+
The agent passes **resource tokens** (not connection URLs); the API
167+
resolves each token to its connection URL server-side at deploy time. The
168+
MCP server never pre-resolves tokens — pre-resolving would round-trip every
169+
binding through `GET /credentials` and embed raw secrets into the tool
170+
params, which the agent host may log.
171+
172+
**Polling:**
173+
174+
`create_deploy` returns `status="building"` immediately. Poll
175+
`get_deployment({ id: deploy_id })` every few seconds until status flips to
176+
`"running"` (typical: ~30s). At that point the `url` field is the live URL.
177+
117178
### How anonymous → claimed works
118179

119180
Every `create_*` tool returns three fields the agent should treat as

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "instanode-mcp",
3-
"version": "0.8.0",
4-
"description": "MCP server for instanode.dev \u2014 lets AI coding agents provision ephemeral Postgres, Redis, MongoDB, NATS queues, S3-compatible object storage, and webhook receivers over HTTPS, with optional bearer-token auth for paid users.",
3+
"version": "0.9.0",
4+
"description": "MCP server for instanode.dev \u2014 lets AI coding agents provision ephemeral Postgres, Redis, MongoDB, NATS queues, S3-compatible object storage, webhook receivers, and deploy containerized apps over HTTPS, with optional bearer-token auth for paid users.",
55
"keywords": [
66
"mcp",
77
"claude",
@@ -15,6 +15,8 @@
1515
"s3",
1616
"object-storage",
1717
"webhook",
18+
"deploy",
19+
"container",
1820
"provisioning",
1921
"ai-agent",
2022
"database"

server.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
"url": "https://github.com/InstaNode-dev/mcp",
77
"source": "github"
88
},
9-
"version": "0.8.0",
9+
"version": "0.9.0",
1010
"websiteUrl": "https://instanode.dev",
1111
"packages": [
1212
{
1313
"registryType": "npm",
1414
"identifier": "instanode-mcp",
15-
"version": "0.8.0",
15+
"version": "0.9.0",
1616
"transport": {
1717
"type": "stdio"
1818
},

0 commit comments

Comments
 (0)