Healthy before active

Turning shared MCP servers into reviewed, age-gated installations that only become active after a real protocol handshake.

The shared agent tooling worked, but its installation did not yet survive the same scrutiny as the rest of the devcontainer. A fresh session could still ask the package runner for whatever release was current, while a failed update could leave the next agent discovering the damage. The fix makes both documentation lookup and browser automation managed tools: reviewed during rebuild, updated cautiously at startup, and activated only after proving they can answer.

An installation is not a health check#

The main decision was whether a successful package command was enough, whether checking a version string covered the risk, or whether the server had to speak its real protocol before becoming active. The protocol won. Each candidate now starts in a staging location and must complete an MCP initialize handshake. Only then does one atomic link make it the active version, so a broken installation or a server that starts but never responds cannot replace the working copy.

flowchart TD
  accTitle: MCP server health-check lifecycle
  accDescr: Package manager installs candidate to staging. Candidate attempts MCP initialize handshake. If handshake succeeds, atomic link makes it the active version. If handshake fails, the previous active version is retained unchanged.
  
  A["Request new version"] --> B["Install to<br/>staging location"]
  B --> C["Attempt MCP<br/>initialize handshake"]
  C -->|Handshake succeeds| D["Atomic link<br/>to active"]
  C -->|Handshake fails| E["Keep previous<br/>active version"]
  D --> F["Agent uses<br/>new version"]
  E --> F
MCP server lifecycle: candidate installed to staging, must complete initialize handshake, then atomically links to active. Failed handshake keeps previous version unchanged.

The update policy also follows the same minimum-release-age rule as the developer CLIs. Rebuilds install versions and integrity hashes that were reviewed with the repository, while startup may advance only to a release old enough to clear the waiting period. This separates two concerns that are easy to mix together: a rebuild must be reproducible, but a long-lived container should still receive updates without taking the newest package immediately.

Test the failure path#

Most of the test suite is about refusing to move forward. It covers an unwritable package cache, a failed install, a candidate that cannot complete the handshake, and both supported cached-browser layouts. The acceptance check then reaches outside the fixtures: rebuild the container, start both servers through each agent configuration, perform a documentation query, and launch the cached browser. A command appearing in a tool list is useful evidence, but it is not the same as a working round trip.

The two MCP servers now have the lifecycle already expected of the developer CLIs, with an extra health boundary appropriate to long-running tools. The next startup can look for a safe update, keep the current version when that attempt fails, and leave the agent session with a server that has already proved it can answer.