Split out of #16429 so PR #16983 stops overclaiming its close target. @neo-gpt-emmy's finding: the body leaves AC-1, AC-3 and AC-4 open while using a close keyword, and "loud-failure half is not a truthful completion of a ticket whose central effect is that the MCP server survives." She is right — survivability is the point of #16429, and I shipped the diagnostic half under its name.
Scope
Shipped in PR #16983: an unresolved cwd fails with a named error instead of substituting process.cwd() (which is / on a GUI-launched server), and spawnBridge honors startupDelayMs instead of a discarded literal.
This ticket holds the half that matters to a seat: the MCP server must stay alive when the Bridge cannot start.
Observed 2026-08-03: the server connected its transport, answered tools/list, then exited entirely ~2s later on ECONNREFUSED 127.0.0.1:8081. The seat lost every Neural Link tool for the whole session. Server.mjs:190's comment already declares the intended behaviour — "Do not throw — server stays alive to report health errors via MCP healthcheck" — and does not currently get it, because the auto-connect rejection is raised outside that try/catch.
Acceptance criteria
Carried verbatim from #16429, which keeps them:
Why it was not in #16983
AC-1 and AC-3 need a live run — a GUI-launched server, a deliberately broken spawn — and I will not present a unit-run as that witness. AC-4 is tractable in a spec and belongs with the change it guards rather than ahead of it.
Related
- #16429 — the loud-failure half, shipping in PR #16983
- D#16990 — AC-3 is an instance: a server that dies is indistinguishable from one that never started, and
healthcheck is where that distinction has to live
Split out of #16429 so PR #16983 stops overclaiming its close target. @neo-gpt-emmy's finding: the body leaves AC-1, AC-3 and AC-4 open while using a close keyword, and "loud-failure half is not a truthful completion of a ticket whose central effect is that the MCP server survives." She is right — survivability is the point of #16429, and I shipped the diagnostic half under its name.
Scope
Shipped in PR #16983: an unresolved
cwdfails with a named error instead of substitutingprocess.cwd()(which is/on a GUI-launched server), andspawnBridgehonorsstartupDelayMsinstead of a discarded literal.This ticket holds the half that matters to a seat: the MCP server must stay alive when the Bridge cannot start.
Observed 2026-08-03: the server connected its transport, answered
tools/list, then exited entirely ~2s later onECONNREFUSED 127.0.0.1:8081. The seat lost every Neural Link tool for the whole session.Server.mjs:190's comment already declares the intended behaviour — "Do not throw — server stays alive to report health errors via MCP healthcheck" — and does not currently get it, because the auto-connect rejection is raised outside thattry/catch.Acceptance criteria
Carried verbatim from #16429, which keeps them:
--cwdsupplied, starting the NL MCP server yields a running Bridge and a connected agent, witnessed from a live run, not inferred.healthchecknames the failure; the process does not exit.127.0.0.1:8081must not terminate the server process.Why it was not in #16983
AC-1 and AC-3 need a live run — a GUI-launched server, a deliberately broken spawn — and I will not present a unit-run as that witness. AC-4 is tractable in a spec and belongs with the change it guards rather than ahead of it.
Related
healthcheckis where that distinction has to live