DEV Community

Cover image for The night four MCP servers started acting like one system
Stephen Phillips
Stephen Phillips

Posted on • Originally published at happymonkey.ai

The night four MCP servers started acting like one system

Last weekend I watched an agent workflow do something I had been waiting to see outside a demo.

Hermes needed to hand a detailed review to another coding agent, start a fairly heavy Codex job, avoid overloading the local server, and leave enough evidence for me to check what happened afterwards.

It did not call one giant "run the swarm" function. It used four small MCP services in sequence.

That was the interesting part.

The run

The project was an evidence-first book-writing system. Hermes had reviewed its claim and citation engine and found a list of engineering problems that needed a coding pass.

The trace looked roughly like this:

find the development agent
send the review to its durable mailbox
confirm that the message arrived
create a durable implementation task
request capacity for the Codex workload
start Codex after the lease is admitted
append working and completion events
verify the resulting code and tests
Enter fullscreen mode Exit fullscreen mode

The resource request declared an estimated 2.2 GB of memory and CPU weight 45. Resource Sentinel admitted it under a time-limited lease. Hermes then launched Codex and recorded the process against the same durable task.

The task history later contained submitted, working and completed events, plus artifact references and verification notes. One completion event recorded 18 passing tests, clean lint modes, compile checks and an independent review.

The workflow was imperfect. More edge cases appeared later and reopened the work. That is a feature, not an embarrassment: durable state made it possible to preserve the real history instead of flattening everything into a cheerful "done" message.

Four MCP servers, four jobs

1. Agent Communication MCP

Agent Communication MCP owns agent identities, cards, durable messages, task records, lifecycle events and artifact references.

Hermes used it to find the development agent, deliver the review, verify the mailbox, create the implementation task and record progress.

The review therefore survived beyond one Slack message or model context window. Another agent could retrieve the same instructions later.

2. Resource Sentinel MCP

Resource Sentinel MCP handles local telemetry and admission control.

A workload supplies an estimated memory requirement, CPU priority and lease duration. The server admits it or queues it according to deterministic host policy. Expiring leases prevent abandoned jobs from holding capacity forever.

Resource Sentinel does not run arbitrary shell commands. It decides whether work may start. Hermes and the coding CLI still own execution.

That boundary matters. A resource monitor should not quietly become a remote command runner.

3. Agent Coordination MCP

Agent Coordination MCP is a narrow control plane for discovering installed CLI agents, inspecting file-based project boards and recording assignments.

The project files remain the source of truth. Codex and other CLIs keep their own sandbox and approval behaviour. The MCP layer records intent and ownership rather than pretending every coding agent has an identical lifecycle.

4. Launcher Project Registry

Launcher Project Registry maps project slugs to local paths, ports, URLs, technology stacks, MCP commands and project context.

Its role was smaller in this run, but still useful. It also exposed a real gap: the book project did not yet have a registry slug, so the task fell back to an absolute local path.

That is exactly the kind of weakness an operational trace should reveal.

Why separate servers worked better

The stack worked because no server tried to own the whole workflow.

Each one returned structured state that Hermes could use in the next decision:

agent = communication.find_agent("dev-agent")
message = communication.send_review(agent, findings)

slot = resources.request_execution_slot(
    workload="codex-review-fixes",
    estimated_memory_mb=2200,
    cpu_weight=45,
)

if slot.status == "admitted":
    task = communication.submit_task(agent, instructions)
    process = launch_codex(task)
    communication.append_event(task, "working", process.reference)
Enter fullscreen mode Exit fullscreen mode

That snippet is illustrative rather than a copy of the actual implementation, but the contract shape is the point.

The orchestrator did not need hidden knowledge of every service. It read tool descriptions, called one bounded operation, inspected the result and chose the next tool.

This was not "agent swarm intelligence"

It is tempting to describe any multi-agent trace as spontaneous collaboration. I do not think that helps.

MCP did not make the coding output correct. The agents did not vote their way to truth. The reliable parts were ordinary engineering controls:

  • durable task and message IDs;
  • explicit state transitions;
  • expiring resource leases;
  • project-owned artifacts;
  • deterministic tests and lint gates;
  • independent review that could reopen the work.

The coding agent still needed supervision. A later review found flaws in backup retention and API validation in a related repository. Those findings were fixed, tested and pushed instead of being waved away because an earlier agent had declared success.

Design rules I would reuse

Keep each MCP server narrow

A mailbox server should not edit repositories. A resource server should not execute caller-supplied commands. A registry should resolve project context without becoming a secrets store.

Smaller contracts make failures easier to locate and permissions easier to reason about.

Make state durable before adding more agents

Adding a second model is easy. Preserving task ownership, evidence, artifacts and failure history is harder and more useful.

If a handoff only exists in chat history, it is not much of a handoff.

Treat host capacity as policy

Local agents share memory, CPU, databases and inference services. Starting every available CLI at once can make all of them slower or take down the services they need.

Admission control belongs in the orchestration path, before process launch.

Verification must be able to reverse "done"

A completion event is a claim. Tests, source checks and independent review decide whether that claim holds up.

The system should preserve a clean way to move from completed back to working when new evidence appears.

What comes next

The immediate work is practical:

  • register projects that still fall back to absolute paths;
  • make lease renewal and release visible beside task history;
  • improve recovery for interrupted processes and stale tasks;
  • put agent, task and resource state in one control-centre view;
  • keep tightening the policy around what an agent may call complete.

This stack is still early, and the coordination server is explicitly experimental. But it has now handled useful work on a real project with a trace that survived the agents involved.

That is a better milestone than another polished swarm demo.


The original case study, including sanitized screenshots, is on HappyMonkey.ai.

The four projects are open source:

Top comments (1)

Collapse
 
mads_hansen_27b33ebfee4c9 profile image
Mads Hansen

The narrow-service boundaries are convincing. The hard part now moves to the gaps between them. There are several failure windows: a lease is admitted but task creation fails; Codex starts but the “working” event is not recorded; completion is appended but the lease is never released. I would give the whole run one correlation ID, make every transition idempotent, persist intended cross-service actions in an orchestration journal/outbox, and run a reconciler that compares task state, process liveness, and lease state. Then recovery is deterministic rather than another agent guessing which partial state is true. A useful invariant might be: every live process has exactly one active task and lease, and every terminal task has neither.