diff --git a/README.md b/README.md index b046dee..042dc86 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ to reach for this MCP, see . | `create_queue` | `POST /queue/new` — Provision a NATS JetStream queue (scoped subject namespace). Returns `connection_url` + `note`/`upgrade`. `name` required. | | `create_storage` | `POST /storage/new` — Provision an S3-compatible bucket prefix (DigitalOcean Spaces). Returns endpoint, access keys, prefix + `note`/`upgrade`. `name` required. | | `create_webhook` | `POST /webhook/new` — Provision an inbound webhook receiver URL. Returns `receive_url` + `note`/`upgrade`. `name` required. | -| `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`. | +| `create_deploy` | `POST /deploy/new` — Upload a base64 gzip tarball (with Dockerfile) and deploy a container. Returns `deploy_id`, `status`, `url`, `build_logs_url`. `name` required. Requires `INSTANODE_TOKEN`. | | `list_deployments`| `GET /api/v1/deployments` — List all deployments on the caller's team. Requires `INSTANODE_TOKEN`. | | `get_deployment` | `GET /api/v1/deployments/:id` — Fetch one deployment (poll until `status="running"`). Requires `INSTANODE_TOKEN`. | | `redeploy` | `POST /deploy/:id/redeploy` — Rebuild + rolling update an existing deployment. Requires `INSTANODE_TOKEN`. | @@ -144,7 +144,9 @@ const tarball_base64 = tar.toString("base64"); ``` Cap: 50 MB after decode. Honor `.dockerignore` — only ship what -`docker build` needs. +`docker build` needs. The `name` field is required (1–64 chars, +letters/numbers/spaces/dashes) — it's the human-readable label shown +on the dashboard. **Binding provisioned resources:** diff --git a/package-lock.json b/package-lock.json index 5bf539f..7b7f461 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "instanode-mcp", - "version": "0.10.1", + "version": "0.11.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "instanode-mcp", - "version": "0.10.1", + "version": "0.11.0", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.10.2" @@ -389,7 +389,6 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -594,7 +593,6 @@ "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.12.tgz", "integrity": "sha512-p1JfQMKaceuCbpJKAPKVqyqviZdS0eUxH9v82oWo1kb9xjQ5wA6iP3FNVAPDFlz5/p7d45lO+BpSk1tuSZMF4Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=16.9.0" } @@ -1165,7 +1163,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 755121e..9a08b6a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "instanode-mcp", - "version": "0.10.1", + "version": "0.11.0", "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.", "keywords": [ "mcp", diff --git a/server.json b/server.json index 7d2ad99..b645de9 100644 --- a/server.json +++ b/server.json @@ -6,13 +6,13 @@ "url": "https://github.com/InstaNode-dev/mcp", "source": "github" }, - "version": "0.10.1", + "version": "0.11.0", "websiteUrl": "https://instanode.dev", "packages": [ { "registryType": "npm", "identifier": "instanode-mcp", - "version": "0.10.1", + "version": "0.11.0", "transport": { "type": "stdio" }, diff --git a/src/client.ts b/src/client.ts index 7182381..466e99d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -204,8 +204,8 @@ export interface DeployDeleteResult { export interface CreateDeployParams { /** Base64-encoded gzip tarball (with Dockerfile + source). <50 MB after decode. */ tarball_base64: string; - /** Optional friendly name. */ - name?: string; + /** Human-readable name shown on the dashboard. Required (1-64 chars). */ + name: string; /** Container HTTP port. Default 8080. */ port?: number; /** Deploy env scope: production / staging / development. Default "production". */ @@ -360,7 +360,7 @@ export class InstantClient { private headers(): Record { const h: Record = { "Content-Type": "application/json", - "User-Agent": "instanode-mcp/0.10.1", + "User-Agent": "instanode-mcp/0.11.0", }; const tok = this.bearerToken(); if (tok) { @@ -375,7 +375,7 @@ export class InstantClient { */ private authHeaders(): Record { const h: Record = { - "User-Agent": "instanode-mcp/0.10.1", + "User-Agent": "instanode-mcp/0.11.0", }; const tok = this.bearerToken(); if (tok) { @@ -647,7 +647,8 @@ export class InstantClient { const blob = new Blob([tarball], { type: "application/gzip" }); form.append("tarball", blob, "app.tar.gz"); - if (params.name) form.append("name", params.name); + // `name` is a required field on POST /deploy/new — always sent. + form.append("name", params.name); if (typeof params.port === "number") form.append("port", String(params.port)); if (params.env) form.append("env", params.env); diff --git a/src/index.ts b/src/index.ts index 6f1b834..6418f63 100644 --- a/src/index.ts +++ b/src/index.ts @@ -710,6 +710,8 @@ vault is per-team, per-env; rotate without redeploying). 'env_vars' and 'resource_bindings' are merged before being sent to the API; on collision, 'resource_bindings' wins. +The 'name' field is required (the human-readable label shown on the dashboard). + Private deploys: set 'private: true' and pass 'allowed_ips' (IPs or CIDR blocks) to restrict access at the Ingress. Pro tier or higher is required — hobby tier returns 402 with an agent_action prompting the user to upgrade. @@ -726,8 +728,9 @@ Requires INSTANODE_TOKEN (anonymous tier cannot deploy).`, .string() .min(1) .max(64) - .optional() - .describe("Optional friendly label (1–64 chars). Defaults to a server-generated slug."), + .describe( + "Human-readable name for this resource, 1-64 chars, letters/numbers/spaces/dashes — shown in the dashboard. Required." + ), port: z .number() .int()