fix(mcp): redeploy in-place — create_deploy {redeploy:true} + tarball on standalone redeploy#34
Merged
Merged
Conversation
… 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 standaloneredeployMCP tool was 100% broken (sent no tarball, api always responded400 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:
create_deploygains optionalredeploy: boolean(default false). Whentrue, the client appendsredeploy=trueto the multipart form onPOST /deploy/new. The api (PRfeat/deploy-new-redeploy-in-place, see dependency below) then updates the existing deployment in place — sameapp_id, same*.deployment.instanode.devURL — instead of minting a fresh one. Omitting the flag preserves legacy "always new" behaviour byte-for-byte on the wire.redeploytool now requirestarball_base64(same shape ascreate_deploy).client.redeploy(id, tarball)POSTs multipart to/deploy/:id/redeploywith a tarball file part — matchesapi/internal/handlers/deploy.go:1245which already required it. Tool description rewritten to stop lying about tarball reuse and to steer agents toward thecreate_deploy({name, redeploy:true})path when they have the name.I chose Option A for the standalone
redeploytool (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 requiredtarball_base64param 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 PRfeat/deploy-new-redeploy-in-placelanding in prod first. That api PR adds aredeployform field handler toPOST /deploy/newthat, whentrue+ a matchingnameexists, 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), theredeploy: trueflag is silently ignored by Fiber's multipart parser — callers see the legacy "always create a new app_id" behaviour with no error. The standaloneredeploytool 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.devbefore flipping the green.Coverage block (rule 17)
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/redeploynow requires multipart tarball, mirroringdeploy.go:1245; existing 4 redeploy tests updated to pass the new required arg).npm run buildclean.client.js100% line / 95.33% branch,index.js99.79% line / 96.53% branch.feat/deploy-new-redeploy-in-placemerges + rolls out:curl https://api.instanode.dev/healthz | jq .commit_idmatches that branch's SHA, then exercisecreate_deploy({name:X, redeploy:true})against a known-existing deployment and confirm the response carries the existingapp_id(rule 14).redeploy({id, tarball_base64})against live api — should accept multipart and return 202.