MCP Control Plane for Orcho Runs
The MCP server is a control plane: a thin protocol adapter over focused implementation domains, exposing a run’s durable state as typed capabilities. This page is the design view; the workflow pages show how to drive it.
| Capability | Representative tools | Effect |
|---|---|---|
| act | run_start · run_resume · run_cancel | Drives a subprocess. |
| observe | run_status · run_live_status · run_watch · run_events_summary | Reads evolving state; never mutates. |
| route | run_diagnose · workspace_pending_decisions | Classifies which subject and transition matter next. |
| decision support | handoff_advice · delivery_gate | Projects safe choices without applying them. |
| decide | phase_handoff_decide · delivery_decide | Writes a decision artifact; never spawns. |
| inspect | run_evidence · run_diff | Projects durable artifacts into typed slices. |
| measure | run_metrics | Reads token, duration, phase, and cost-reference facts. |
A captain can move through all seven: act, observe, route, request decision support, decide, inspect, and measure.
Seven capabilities, one lifecycle
Section titled “Seven capabilities, one lifecycle”Run lifecycle and state transitions are deliberately separate concerns.
orcho_run_start, orcho_run_resume, and orcho_run_cancel drive
subprocesses — start spawns a detached process group and returns
immediately. Observation (orcho_run_status, orcho_run_events_tail,
orcho_run_metrics, orcho_run_history) reads the run’s evolving state
and mutates nothing, so it is safe to poll on a tight loop.
Decisions are state transitions, not process actions:
orcho_phase_handoff_decide resolves a run paused on
awaiting_phase_handoff, orcho_delivery_decide resolves a parked
delivery or correction gate, and neither ever spawns a process.
Inspection reads existing artifacts and projects them into typed slices:
orcho_run_evidence for plan, findings, commands, artifacts, and errors;
orcho_run_diff for the captured change. Routing and decision support remain
separate: orcho_run_diagnose classifies the continuation subject, while
orcho_handoff_advice and orcho_delivery_gate explain sanctioned choices.
Control-loop clients use these surfaces instead of raw logs.
Layer split
Section titled “Layer split”The package keeps the MCP wire surface thin and the behavior focused. Adapter layers register with FastMCP and delegate; they contain no business logic. Implementation domains each own a coherent slice.
| Adapter layer | Role |
|---|---|
tools.py | @mcp.tool registration, one-line delegation to domain modules |
resources/ | MCP resource URI handlers; no SDK access, no direct file IO |
schemas/ | Pydantic models that define the MCP wire shape |
instance.py | The shared FastMCP instance every adapter imports |
| Domain | Owns |
|---|---|
services/ | SDK-backed reads, run-projection read-models, error mapping |
observe/ | Event summaries, watch, handoff hints |
run_control/ | Start / resume / cancel / handoff-decision implementation |
inspection/ | Evidence and diff reads |
authoring/ | Plan validation and prompt resolution |
supervisor/ | Subprocess lifecycle: spawn, state IO, recovery, cancel, reap |
Import rules keep the layers apart, and they are enforced by executable
architecture guards, not convention: tools.py must not import the SDK
— handlers delegate to the matching domain; resources/ reads go
through services/, which is the canonical home for SDK access; the
supervisor owns its own state file (mcp_supervisor.json) while
meta.json stays the pipeline’s contract; and domain modules never
import from the adapter layers above them.
The request path
Section titled “The request path”Every request travels the same spine:
A read like orcho_run_status goes through services/ to the SDK,
merges pipeline state with supervisor truth, and returns a Pydantic wire
model — no subprocess, no lock. A spawn like orcho_run_start goes
through run_control/ to the supervisor, which builds argv via the SDK
and launches the pipeline in its own process group before responding.
stdin and stdout are reserved for JSON-RPC frames. No print() is
allowed in handler code paths — a single rogue write to stdout corrupts
the next protocol frame. Logging goes to stderr.
The control boundary
Section titled “The control boundary”Whether the server can mutate a run is a durable, on-disk fact, not a
session guess. A run this server spawned carries mcp_supervisor.json
and is mcp_controllable: resume and handoff decisions proceed. A
foreign or CLI-started run has only meta.json and is inspect_only.
Inspection always works on both. On an inspect_only run the mutation
tools refuse safely — before any spawn or decision write — by raising a
typed InspectOnlyControlError whose payload carries read-only next
steps. orcho_run_diagnose exposes the same classification as typed
control and control_reason fields, so a client can branch before
ever attempting a mutation.
Durable decisions, disposable observers
Section titled “Durable decisions, disposable observers”Phase-handoff decisions are recorded artifacts:
<run_dir>/phase_handoff_decisions/{safe_handoff_id}.json persists who
decided what and why. Replaying the exact same decision payload returns
the persisted record unchanged — retries and double-submits cannot
drift the audit text — while a diverging payload for the same handoff
is a conflict, not a toggle.
Observation is the disposable half: the reliable path is cursor-based
replay from durable run state, so a dropped or timed-out
orcho_run_watch is observer loss, never a run failure. A client
reconnects with its last-seen event cursor and misses nothing.
Current control boundaries
Section titled “Current control boundaries”The public alpha does not claim topology or decision parity across every surface:
orcho_run_live_statusis a bounded mono-run card. Cross runs useorcho_run_status, event summaries, evidence, and sub-run projections.orcho_workspace_pending_decisionscurrently aggregates phase handoffs; it is not yet a universal inbox for every delivery and cross-gate decision.- runs started outside this MCP server are
inspect_only: observation and evidence work, mutation tools refuse before writing state or spawning. - core remains the lifecycle authority. MCP never invents an action that the active payload did not publish.
These are control boundaries, not hidden failures. Clients can inspect them through typed fields and choose the appropriate CLI or MCP-owned subject.
What is deliberately not vocabulary
Section titled “What is deliberately not vocabulary”- Arbitrary pause/unpause. Runs finish, fail, get cancelled, or
pause only when a phase’s declared
handoffpolicy fires. The one declarative pause point isorcho_phase_handoff_decideoverawaiting_phase_handoff. - Generic retry disguised as resume.
orcho_run_resumestarts a fresh subprocess against the existing run directory and checkpoint, respecting the effective profile. Completed checkpoint phases are skipped because they already belong to the same run; correction work and saved-plan continuation remain separate run modes.
Deep reference
Section titled “Deep reference”The canonical engineering docs live with the code:
- docs/run_lifecycle.md
- docs/architecture/mcp_boundaries.md
- docs/architecture/control_state_machine.md
- docs/architecture/anatomy_of_a_request.md