Skip to content

fix(mcp): redeploy in-place — create_deploy {redeploy:true} + tarball on standalone redeploy#34

Merged
mastermanas805 merged 1 commit into
masterfrom
fix/mcp-redeploy-in-place
May 30, 2026
Merged

fix(mcp): redeploy in-place — create_deploy {redeploy:true} + tarball on standalone redeploy#34
mastermanas805 merged 1 commit into
masterfrom
fix/mcp-redeploy-in-place

Conversation

@mastermanas805
Copy link
Copy Markdown
Member

Summary

Closes the AGENT-UX trap (see /tmp/deploy-fail-swarm/shared/AGENT-UX.md) where an MCP agent shipping v2 of an existing app ended up with two live deployments and two URLs, and the standalone redeploy MCP tool was 100% broken (sent no tarball, api always responded 400 missing_tarball, tool description falsely claimed "the tarball from the original deploy is reused" — there is no tarball reuse anywhere in the api).

Two fixes in one PR:

  1. create_deploy gains optional redeploy: boolean (default false). When true, the client appends redeploy=true to the multipart form on POST /deploy/new. The api (PR feat/deploy-new-redeploy-in-place, see dependency below) then updates the existing deployment in place — same app_id, same *.deployment.instanode.dev URL — instead of minting a fresh one. Omitting the flag preserves legacy "always new" behaviour byte-for-byte on the wire.
  2. Standalone redeploy tool now requires tarball_base64 (same shape as create_deploy). client.redeploy(id, tarball) POSTs multipart to /deploy/:id/redeploy with a tarball file part — matches api/internal/handlers/deploy.go:1245 which already required it. Tool description rewritten to stop lying about tarball reuse and to steer agents toward the create_deploy({name, redeploy:true}) path when they have the name.

I chose Option A for the standalone redeploy tool (keep it, require a tarball) over Option B (deprecate it). Rationale: agents may already have the tool in their context; deprecating it removes the only id-based update path. Adding a required tarball_base64 param is technically a breaking change but the tool was 100% broken before so no real callers depended on it.

Dependency on the api PR

The create_deploy {redeploy: true} half of this fix depends on api PR feat/deploy-new-redeploy-in-place landing in prod first. That api PR adds a redeploy form field handler to POST /deploy/new that, when true + a matching name exists, replaces the deployment in place.

Until the api PR is in prod (verified via rule-14 build-SHA gate against https://api.instanode.dev/healthz), the redeploy: true flag is silently ignored by Fiber's multipart parser — callers see the legacy "always create a new app_id" behaviour with no error. The standalone redeploy tool fix (Option A) works against today's api with no dependency.

Do NOT merge this MCP PR until the api PR is in prod. I'll re-verify on the live api.instanode.dev before flipping the green.

Coverage block (rule 17)

Symptom:        AGENT-UX path B: redeploy({id}) → 400 missing_tarball
                AGENT-UX path A: create_deploy(same name) → 2 URLs
Enumeration:    rg -F 'redeploy' src/ test/  +  rg -n 'createDeploy|create_deploy'
Sites found:    src/index.ts (redeploy tool, create_deploy tool, file docstring),
                src/client.ts (redeploy method, createDeploy method,
                CreateDeployParams interface), 4 redeploy tests in tools-unit,
                3 tests in client-unit, 3 tests in integration, mock-api
                /deploy/:id/redeploy + /deploy/new handlers, README.md.
Sites touched:  all listed sites (no skips).
Coverage test:  `redeploy-in-place tool handlers (fix/mcp-redeploy-in-place)`
                suite iterates the create_deploy {redeploy:true vs default}
                contract and asserts the standalone redeploy tool sends a
                multipart POST with a tarball part.
Live verified:  AWAITING api PR feat/deploy-new-redeploy-in-place in prod —
                rule 14 build-SHA check against api.instanode.dev/healthz.
                Standalone redeploy tool fix is testable against today's
                api (existing contract).

Test plan

  • npm test — 373/373 pass (added 9 new tests: 6 in client-unit, 3 in integration redeploy regression, 4 in tools-unit; mock-api updated to enforce real api contract — POST /deploy/:id/redeploy now requires multipart tarball, mirroring deploy.go:1245; existing 4 redeploy tests updated to pass the new required arg).
  • npm run build clean.
  • Coverage: client.js 100% line / 95.33% branch, index.js 99.79% line / 96.53% branch.
  • Verify against live api after feat/deploy-new-redeploy-in-place merges + rolls out: curl https://api.instanode.dev/healthz | jq .commit_id matches that branch's SHA, then exercise create_deploy({name:X, redeploy:true}) against a known-existing deployment and confirm the response carries the existing app_id (rule 14).
  • Smoke-test standalone redeploy({id, tarball_base64}) against live api — should accept multipart and return 202.

… on redeploy tool

Closes the AGENT-UX trap (shared/AGENT-UX.md) where shipping v2 of an app via
the MCP left two live deployments + two URLs, and the standalone `redeploy`
tool was 100% broken (sent no tarball, api always 400'd missing_tarball, tool
description falsely claimed "the tarball from the original deploy is reused").

create_deploy: new optional `redeploy: boolean` (default false). When true,
the client appends `redeploy=true` to the multipart form on POST /deploy/new
— the api (PR feat/deploy-new-redeploy-in-place) then updates the existing
deployment in place (same app_id, same URL) instead of minting a fresh one.
Omitting the flag preserves legacy "always new" behaviour byte-for-byte on
the wire. Forward-compatible: on an api that hasn't yet shipped the field,
Fiber's MultipartForm parser silently ignores it, so callers see the legacy
path with no error.

redeploy (standalone tool): now requires `tarball_base64` (same shape as
create_deploy). client.redeploy(id, tarball) POSTs multipart to
/deploy/:id/redeploy with a tarball file part — matches deploy.go:1245
which already required it. Tool description rewritten to stop lying about
tarball reuse and to steer agents toward the create_deploy({name,
redeploy:true}) path when they have the name.

Breaking change for the standalone redeploy tool (added required tarball
param), but the tool was 100% broken before so no real callers depended
on it.

Coverage block (rule 17):
  Symptom:        AGENT-UX path B: redeploy({id}) → 400 missing_tarball
                  AGENT-UX path A: create_deploy(same name) → 2 URLs
  Enumeration:    rg -F 'redeploy' src/ test/  +  rg -n 'createDeploy|create_deploy'
  Sites found:    src/index.ts (redeploy tool, create_deploy tool, file docstring),
                  src/client.ts (redeploy method, createDeploy method,
                  CreateDeployParams interface), 4 tests in tools-unit,
                  3 tests in client-unit, 3 tests in integration, mock-api
                  /deploy/:id/redeploy + /deploy/new handlers, README.md.
  Sites touched:  all listed sites (no skips).
  Coverage test:  redeploy-in-place tool handlers suite — iterates the
                  create_deploy {redeploy:true vs default} contract and
                  asserts the standalone redeploy tool sends a multipart
                  POST with a tarball part.
  Live verified:  awaiting api PR feat/deploy-new-redeploy-in-place in prod
                  (rule 14 build-SHA check) before MCP merge — see PR body.

Tests: 373/373 pass. Coverage: client.js 100% line / 95.33% branch,
index.js 99.79% line / 96.53% branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mastermanas805 mastermanas805 merged commit 4423a61 into master May 30, 2026
9 checks passed
@mastermanas805 mastermanas805 deleted the fix/mcp-redeploy-in-place branch May 30, 2026 13:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant