MCP server β
Your MCP client needs to spawn Avenor runs and monitor them. avenor mcp is the canonical MCP server that gives your client these tools.
It's built into the Go binaryβno Node, Bun, npm, or separate package needed.
avenor mcpTransports β
stdio β
stdio is the default transport and is the best choice for most MCP clients.
avenor mcpExample MCP host configuration:
{
"mcpServers": {
"avenor": {
"command": "avenor",
"args": ["mcp"]
}
}
}If avenor is not on the host's PATH, use the absolute path:
{
"mcpServers": {
"avenor": {
"command": "/path/to/avenor",
"args": ["mcp"]
}
}
}HTTP β
HTTP transport uses MCP Streamable HTTP and is intended for local, long-lived clients.
MCP_AUTH_TOKEN="my-secret" avenor mcp --transport httpBy default it binds to 127.0.0.1:3748. HTTP requires a bearer token, supplied with either MCP_AUTH_TOKEN or --auth-token:
avenor mcp --transport http --addr 127.0.0.1:3748 --auth-token "my-secret"Example MCP host configuration:
{
"mcpServers": {
"avenor": {
"url": "http://127.0.0.1:3748",
"headers": {
"Authorization": "Bearer my-secret"
}
}
}
}The HTTP server rejects non-loopback hosts and non-loopback browser origins. Keep it on loopback unless you are deliberately putting another authenticated local proxy in front of it.
Typical workflow β
When you (an LLM) are using this MCP server to automate work:
avenor_spawn(agent="jockey", repo_dir="/path/to/repo", prompt="fix the tests")
β { "run_id": "...", "label": "...", "supervisor_id": "..." }
avenor_status(run_id="...", view="lifecycle")
β { "status": "running", ... }
avenor_result(run_id="...")
β { "status": "done", "ready": true, "output": "..." }
avenor_events(run_id="...")
β { "events": [ { "type": "...", ... }, ... ] }
avenor_shutdown()
β { "ok": true, "cleaned_up": [...] }- Call
avenor_spawnwith an agent name and repository path. - Use
avenor_statuswithview="lifecycle"when you need progress or pending permission details. - If
pending_permissionis present, callavenor_answer_permissionto respond. - Call
avenor_resultto wait for and retrieve the complete final output. - Call
avenor_eventsonly when you need raw recent history. - Optionally call
avenor_follow_upto continue from a completed run. - Call
avenor_shutdownwhen the MCP session is done.
Supervisor lifecycle β
By default, avenor mcp starts a private child supervisor:
avenor stable --control-socket <socket> --idle-timeout 30mThe socket defaults to ~/.avenor/sockets/avenor-mcp-<pid>.sock. You can override it:
avenor mcp --control-socket ~/.avenor/sockets/avenor-mcp.sockTo connect to an existing supervisor instead of starting one:
avenor stable --control-socket /tmp/avenor-stable.sock
avenor mcp --supervisor-socket /tmp/avenor-stable.sock --no-autostart--supervisor-socket disables autostart. --no-autostart requires --supervisor-socket.
Flags β
| Flag | Default | Description |
|---|---|---|
--transport | stdio | stdio or http |
--addr | 127.0.0.1:3748 | HTTP bind address |
--auth-token | MCP_AUTH_TOKEN | Bearer token required for HTTP |
--control-socket | per-process socket | Socket path for the autostarted child supervisor |
--supervisor-socket | none | Existing supervisor socket to connect to |
--no-autostart | false | Require an existing supervisor |
--idle-timeout | 30m | Idle timeout for the autostarted child supervisor |
Tools β
All tools use the avenor_ prefix and are scoped to this MCP process's supervisor.
avenor_spawn β
Starts a new run.
Required:
agentβ agent to run (e.g.,"jockey","butler")repo_dirβ working directory for the run
Optional:
promptβ initial prompt textprompt_fileβ path to file containing the initial promptlabelβ human-friendly label (defaults torun_id)timeoutβ timeout as seconds or duration (e.g.,"90s","5m","1h")modelβ model to usebackendβ runtime backend (e.g.,"opencode-http","opencode-acp","codex-app-server")server_urlβ server URL for opencode-http backendsupervisor_idβ supervisor socket to use instead of the default
Returns:
{
"run_id": "...",
"label": "...",
"supervisor_id": "..."
}The returned run_id is generated and unique. Pass it to other tools to query or control this run.
avenor_status β
Queries the status of runs. Use this for lifecycle and permission checks, not final output retrieval.
Optional:
run_idβ specific run ID or label to query; omit to list all runsviewβlifecyclefor a compact response orfullfor compatibility (default:full)supervisor_idβ supervisor socket to query (default: the autostarted supervisor)
Returns: One status object if run_id is given, or an array of status objects if omitted.
Status values:
runningβ still executingdoneβ completed successfullyfailedβ ended with an errortimeoutβ exceeded timeoutkilledβ forcefully terminated
When blocked on a permission request, the result includes pending_permission with request_id and options.
avenor_result β
Waits for one run and returns its complete final output without transcript or raw event details.
Required:
run_idβ run ID or label to await
Optional:
waitβ wait for a terminal result (default:true)timeoutβ maximum time to wait, such as30sor5msupervisor_idβ supervisor socket to query
A terminal response has ready: true and includes the complete output when the backend exposed final assistant text. A blocked run returns its pending_permission immediately. If an older or unavailable control endpoint prevents lossless retrieval and a presentation fallback is returned, output_truncated: true and output_event_path make its possible truncation explicit; retry avenor_result or read the durable event path. If the result tool's own timeout expires, it returns the latest state with ready: false and timed_out: true; the underlying run keeps going.
avenor_answer_permission β
Responds to a pending permission request.
Required:
run_idβ run ID or labeloption_idβ which option to select
Optional:
request_idβ specific request ID to answer; if omitted, answers the current pending requestsupervisor_idβ supervisor socket to use
Returns:
{ "ok": true }avenor_events β
Reads historical events from a run's event log.
Required:
run_idβ run ID or label
Optional:
typesβ event types to filter by (e.g.,["phase"])limitβ maximum events to return (default:50)supervisor_idβ supervisor socket to use
Returns:
{ "events": [ ... ] }The event log skips malformed lines and returns the last N matching events.
avenor_follow_up β
Spawns a new run continuing a completed run's session.
This is not a live prompt into the old runtime; it spawns a new runtime that resumes from the prior session's state.
Required:
run_idβ completed run ID or labelmessageβ follow-up prompt text
Optional:
labelβ label for the new run (defaults to<prior-label>-followup)supervisor_idβ supervisor socket to use
Returns:
{
"run_id": "...",
"label": "..."
}avenor_shutdown β
Shuts down the supervisor and cleans up MCP-owned files.
Optional:
supervisor_idβ supervisor socket to shut down (default: the autostarted supervisor)forceβ request kill instead of graceful shutdown (default:false)
Returns:
{
"ok": true,
"cleaned_up": [
"path/to/sentinel/file",
"path/to/event/log"
]
}Registry scope: important limitation β
The Go MCP server keeps an in-memory run registry scoped to the MCP process. This registry maps run_id (generated by this MCP server) to stable runtime IDs, sentinel files, event logs, and other metadata.
This means:
avenor_eventsrequires a run spawned by this MCP process (must be in the registry).avenor_follow_uprequires the prior run to be in this MCP process's registry.- If you spawn a run with one MCP server and then try to query it with another MCP server, it will fail.
Durable cross-process recovery is intentionally out of scope. If you need to connect to an existing supervisor's runs from a different MCP process, use supervisor_id to point at that supervisor's control socket and query by stable runtime IDβbut you won't be able to read events or spawn follow-ups for those runs.