odu-mcp
SkillAI & modelsodu MCP server launcher — drive CI from a coding agent. `bin/serve` resolves odu via Nix and runs `odu mcp` in the cwd. See the repo README for the tools/resources and override knobs.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the odu-mcp skill
What this skill tells your AI
The instructions your AI receives, as published by juspay/kolu in .agents/skills/odu-mcp/SKILL.md and read by ahel’s review.
The agent face of odu — an MCP stdio server
that re-exposes a live CI run as agent tools (run, node_rerun,
node_cancel, lane_cancel, wait_for_settle, cancel, lease, release) and subscribable resources
(surface://streams/nodes, surface://collections/logs/{id}), so Claude Code /
Codex / opencode / Gemini CLI drive CI with structured calls instead of
scraping terminal output.
lease / release are the agent-held venue layer: hold a free box across
discrete tool calls without re-queuing between runs. lease returns
immediately (held or waiting); re-call or inventory to observe the line.
run reuses held hosts and does not release them on exit.
wait_for_settle defaults to fail-fast: it returns the instant the first node
goes red (fail_fast_tripped: true, settled: false), so the agent drills into
the failure without blocking on the slow lanes — its failed[] is only what's
red so far, and only passed: true (a fully settled run) is a trustworthy green.
A verdict about an observed run is stamped with that run's identity — sha7
always, seq whenever the coordinator reserved an ordinal — so it's clear
which run it describes (seq is null only when none was reserved: a wait
that saw no frame, or the rare case the coordinator couldn't reserve one);
and unposted[] carries full owed GitHub status rows
({context, lastError, attempts}) not yet confirmed (reporting debt never
blocks settle — the test verdict stays the truth).
Called with no run live
it fails loud (an error mirroring odu status, not an empty settled: false),
and an optional expected_sha (prefix-matched against the run's sha7) refuses
loud when the live run's commit doesn't match. A run that is still PROVISIONING
— run returns as soon as the coordinator serves its socket, which is now
before it claims a machine — is a live run: wait_for_settle blocks on it, the
nodes resource shows _ci-setup@<platform> running, and its log resource
carries the runner closure's copying path … progress. A claim that never
succeeds arrives as a red _ci-setup@<platform> verdict rather than as a
run-time error. If the coordinator's socket
closes before it publishes a terminal frame, the verdict comes from the run's
finalized record on disk — never green for a run torn down mid-flight. The
nodes resource carries the same unposted. MCP run tees coordinator
stdout/stderr to .ci/<sha7>/runs/<seq>.log.
A settled node's surface://collections/logs/{id} is the last 64KB of its output
and now reliably ENDS at the recipe's final line: a run that settles on its own
holds its lanes open until every node has finished streaming, because a node's
status and its output travel on different streams and the status one arrives
first — so the recipe summary the agent came for used to be the part that never
made it. Read .ci/<sha7>/<platform>/<node>.log for the whole thing. A lane that stops streaming with output still owed stamps
[odu] log truncated: … into the log, so a drill-in never reads a cut log as a
complete one.
cancel stops the live run and waits until it's torn down; node_cancel stops
one node (ci::fmt@plat) and lane_cancel drops a whole platform while the rest
of the run settles (status cancelled, not errored/failed). run's supersede
cancels a run already live here before starting (the "stop this, run the fixed
commit" move), linger keeps the coordinator serving past settle so a node can
be rerun afterwards, and no_wait fails immediately when every host in a venue
pool is busy (default: wait in line). Together they let the agent loop call off
or replace a run instead of stranding it or hitting "a run is already in
progress".
bin/serve is self-contained — it resolves odu via nix run and serves over
stdio in the consumer's repo (dialing .ci/odu.sock). Set ODU_FLAKE to
override the odu flake-ref (default github:juspay/odu); a repo that
re-exports odu can point it at its own pinned output with ODU_FLAKE=.#odu.
Full docs in the repo README.
This skill primitive exists for APM's deployment convention — it lands
bin/serve at .agents/skills/odu-mcp/bin/serve in the consumer's working
tree (APM's skills-convergence path), which keeps the launcher available even
before apm install runs on a fresh clone. The package is mechanically a
"skill" in APM's primitive vocabulary; semantically it's a tool launcher.
Signals
- GitHub stars
- 78
- Forks
- 12
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
odu-mcp- Source
- github.com/juspay/kolu