skip to content
Replays

An MCP Server for Watching and Steering a Gantry Run

Expose one build's status, artifacts, and controls to an agent — confined to that run

Gantry milestones

2 milestones 7 sprints 16 agents

160k peak context

136k median execute

Expose one build's status, artifacts, and controls to an agent — confined to that run

1h 44m total 9m 34s per sprint

8m 42s plan 1h 3m execute 9m 10s review

81 edits 299 commands

claude harness

33M tokens in 341.1k tokens out

$41.65 nominal cost

This job gave an agent a structured way to inspect and operate on a single Gantry run through MCP. The work is visible today as the `src/mcp` server surface, the `gantry mcp` launch command, confined artifact readers, a git-state view of the run worktree, sandboxed shell execution, and a prompt-answering action that later gained a live attach transport.

How this walkthrough is structured

Feature

What did the run build and ship?

Gantry still carries a run-scoped MCP surface for status, artifacts, worktree state, sandboxed commands, and live prompt answers.

Build

How did Gantry structure the work?

The run separated read access from action tools, put run scoping underneath both, and stayed green by letting each sprint inherit one proven contract before adding the next.

Milestone 1

Job Query Interface

5 sprints 0 agents 50m 48s wall time 138k peak context $23.36 nominal cost

The read side remains in the tree as the core `src/mcp` modules and the external `gantry mcp` command. It resolves a run, advertises tools from the manifest, reads durable run artifacts, and reports worktree git state through structured tool results. Later work has moved and expanded some coverage, but the read contract built here is still the base of the MCP server.

The first milestone carried the cold read contract for a Gantry run. Its boundary was clear enough for fresh agents because it postponed every mutating tool and made the resolved run context the shared input for the whole surface. The gate stayed green through the milestone, with no retry or re-plan recorded, so the useful build fact is the layering: path confinement, protocol, artifact readers, git state, then launch.

Run Context Setup

0 agents 9m 34s wall time 128k peak context 39.9k tokens out $3.80 nominal cost

`src/mcp/run.rs` still builds a `RunContext` from the registry's run records, including the worktree and orchestration directory instead of recomputing them. `src/mcp/path_guard.rs` still canonicalizes caller-supplied paths under an allowed root and refuses paths that leave the scoped run. The fixture support added with this foundation has been edited since, but the central guard is still present.

This sprint was asked to carry the security foundation without also carrying protocol or tool behavior. That made it a good memoryless-agent unit: resolve a run using Gantry's registry, preserve the registry paths, and prove a single path guard against traversal, absolute paths, sibling runs, and symlink escape. It passed without recorded repair, and every later file-reading sprint could treat confinement as an already tested primitive.

Protocol and Manifest

0 agents 8m 4s wall time 104k peak context 34.6k tokens out $3.21 nominal cost

The manifest source still lives in `src/mcp/tools.rs`, where every MCP tool has a name, description, and input schema. `src/mcp/server.rs` still dispatches calls from that same tool enum, and `job_status` plus `list_runs` remain registry-backed structured outputs. The current table includes later action tools as well, but its anti-drift role comes from this sprint.

With run context and confinement available, this sprint could focus on the wire interface. It stood up the JSON-RPC server loop, the initialize and tool-list calls, dispatch for tool calls, and the manifest table that defines the tool contract in one place. The only working handlers needed here were the registry-backed status and run-list views, so the protocol spine was tested before the path-taking tools arrived.

Artifact Read Tools

0 agents 11m 26s wall time 136k peak context 46.5k tokens out $5.00 nominal cost

`src/mcp/artifacts.rs` still contains the artifact reader implementations. They reuse Gantry's ledger, plan, and about-card readers where those producers exist, return JSON-shaped results, and keep missing files as ordinary not-found tool output. The server still guards report and log names before calling these readers, so the feature is more than a set of file opens.

This sprint filled the read surface that actually touches run files, so its boundary depended on the guard from the opening sprint. The brief named ledger, plan, sprint roster, report, history, and log readers, with bounded tail behavior and clean not-found results. It passed cleanly, which fits the cut: the agent was adding handlers behind an existing protocol and routing every untrusted name through the same confinement mechanism.

Git State Tool

0 agents 7m 47s wall time 138k peak context 30.3k tokens out $3.85 nominal cost

`worktree_info` is still a registered MCP tool implemented in `src/mcp/server.rs`. It reports the resolved run's worktree path and branch, porcelain status, recent commits, and a bounded diff against main, and returns a structured no-worktree result when the checkout is absent. The implementation has been edited since, but the capability remains visible in the server.

This sprint was isolated because `worktree_info` reads live git state rather than static orchestration files. The agent's task was narrow: report the run worktree path, branch, status, recent commits, and a bounded diff, while handling a merged run whose worktree is gone. No red gate is recorded, and the single-purpose git fixture kept this live-state tool separate from the artifact-reader tests.

Launch and Docs

0 agents 7m 8s wall time 112k peak context 20.9k tokens out $3.86 nominal cost

`gantry mcp <name>` still starts the stdio MCP server from the command surface. Documentation now lives in the agent and CLI docs rather than only the original README text, and the end-to-end coverage now sits under the integration test tree instead of the older standalone test file the job introduced. The launch surface itself remains the external way to attach an MCP client to a run.

The last read-surface sprint connected the library server to the command line. Because the protocol and tools were already tested in-process, the fresh agent could stay focused on resolving a run name, keeping protocol output on stdout, documenting attachment, and proving the launched binary with an end-to-end handshake. The sprint passed without repair and closed the milestone against a real process rather than only a library call.

Milestone 2

Execution and Verification

2 sprints 0 agents 37m 47s wall time 160k peak context $17.48 nominal cost

The MCP surface now includes action tools as part of the same manifest as the read tools. `run_bash` executes in the resolved worktree under Gantry's containment policy, and `answer_prompt` targets a live engine when one is attached. Later transport work made standalone live attachment real, but this milestone supplied the action contract and the initial attach seam.

The second milestone added action tools after the read surface had already fixed scope, manifest, and dispatch conventions. That order mattered because the risky work was not about inventing another server; it was about giving existing server tools controlled ways to execute commands or reach a live engine. Both sprints stayed green, with no recovery or re-plan recorded, and the briefs kept the action surface tied to existing Gantry containment and command-channel behavior.

Sandboxed Bash Execution

0 agents 16m 35s wall time 160k peak context 59.9k tokens out $6.59 nominal cost

`src/mcp/action.rs` still implements `run_bash` around the engine sandbox policy and worktree helper. The result includes captured stdout, stderr, exit status, timeout state, sandbox state, and escaped-write findings, so clients can inspect both command output and containment failures. The tool remains in the manifest and dispatch path beside the read tools.

This sprint carried the most dangerous new capability and kept it tractable by reusing Gantry's agent sandbox instead of designing a separate command runner. Its brief required the command to run in the resolved worktree, capture output and exit status, respect a timeout, and apply the same escaped-write backstop used for agent stages. The sprint passed cleanly, so the run record shows the sandbox boundary was proven as a focused addition rather than repaired after integration.

Run Control Actions

0 agents 14m 48s wall time 159k peak context 55.6k tokens out $7.64 nominal cost

`answer_prompt` is still registered as an MCP action and is implemented through `src/mcp/attach.rs` and the server dispatch. The current tree goes beyond the sprint's original absent-live default: standalone `gantry mcp` can attach to a live owner over the same transport used by other front ends, while non-live runs still fail the action cleanly. The prompt-answering path therefore survived as both an external MCP capability and part of the in-process assistant host.

The final sprint added run-control without pretending a dead run could be controlled. Its brief grounded the work in Gantry's existing command channel and required an optional live-engine handle, with tool-level failure when no engine was attached and no mutation of durable artifacts. It also passed without retry, helped by limiting the action set to prompt answering rather than a broad control API.