From 167920dcc837a05ede7d7e4a5da802fb8abfb99b Mon Sep 17 00:00:00 2001 From: Mark Henderson Date: Mon, 27 Apr 2026 14:41:09 -0700 Subject: [PATCH] fix(mcp v2.4.7): defer coolify-proxy restart so it doesn't kill our own request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The post-deploy step that restarts coolify-proxy was running synchronously inside the HTTP request handler. coolify-proxy is the same gateway that's serving the request itself, so the restart killed our outbound response mid-flight — the agent saw curl exit 16 (HTTP/2 framing error) instead of our nicely-formatted result. Switch to a fire-and-forget shell: nohup sh -c '(sleep 3 && docker restart coolify-proxy) ...' & The SSH command returns within ~50ms, we finish the HTTP response, and Traefik re-discovers labels 3s later — same end state as before but without breaking the calling request. Made-with: Cursor --- app/api/mcp/route.ts | 2 +- lib/coolify-compose.ts | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/api/mcp/route.ts b/app/api/mcp/route.ts index 426c2767..d731af23 100644 --- a/app/api/mcp/route.ts +++ b/app/api/mcp/route.ts @@ -92,7 +92,7 @@ const GITEA_API_URL = process.env.GITEA_API_URL ?? 'https://git.vibnai.com'; export async function GET() { return NextResponse.json({ name: 'vibn-mcp', - version: '2.4.6', + version: '2.4.7', authentication: { scheme: 'Bearer', tokenPrefix: 'vibn_sk_', diff --git a/lib/coolify-compose.ts b/lib/coolify-compose.ts index 152a3339..fc93d133 100644 --- a/lib/coolify-compose.ts +++ b/lib/coolify-compose.ts @@ -372,12 +372,28 @@ for c in label_changes: }; } - // ── Step 5: nudge Traefik to re-discover via proxy restart + // ── Step 5: nudge Traefik to re-discover via proxy restart. + // + // CAUTION: coolify-proxy is the same gateway that's currently + // serving this very HTTP request (the agent → vibnai.com call that + // landed in this handler). If we run a synchronous `docker restart + // coolify-proxy`, the connection is killed mid-flight and the agent + // sees a curl error 16 (HTTP/2 framing) instead of our nicely + // formatted result object. We fire-and-forget instead: the SSH + // command returns within ~50ms, we finish the HTTP response, and + // the proxy restarts ~3s later — by which time the response has + // already been delivered and Traefik will re-discover labels for + // any subsequent request. try { - const r = await runOnCoolifyHost(`docker restart coolify-proxy`, { timeoutMs: 30_000 }); + const r = await runOnCoolifyHost( + `nohup sh -c '(sleep 3 && docker restart coolify-proxy) >/tmp/coolify-proxy-restart.log 2>&1' /dev/null 2>&1 &`, + { timeoutMs: 8_000 }, + ); result.steps.proxyRestart = { ok: r.code === 0, - detail: r.code === 0 ? 'restarted' : (r.stderr || r.stdout).trim().slice(-200), + detail: r.code === 0 + ? 'scheduled (background, +3s after response)' + : (r.stderr || r.stdout).trim().slice(-200), }; } catch (e) { result.steps.proxyRestart = {