Aether's MCP bridge is an in-container MCP server for six existing
coordination tools, registered automatically for Enhanced runs and manually
elsewhere. The canonical agent interface is the
aether-internal CLI, which is automatically available in every managed
container and can load a version-matched skill on demand. The bridge is not the
Release B orchestration interface and does not need to mirror its swarm or
worker-management surface.
When coordination assets are available, the server stages verified executable bytes read-only at the two in-container paths used by the existing surfaces:
/opt/aether/aether-server optional MCP entry point and lifecycle hook
/usr/local/bin/aether-internal canonical agent-facing coordination CLIThe run coordination directory carries the run socket and related server assets:
/run/aether/coord3.sock this run's v3 socket
/run/aether/co-authors server-generated commit trailersThese are Aether-owned surfaces, not caller-provided mounts. Caller mounts cannot shadow the coordination directory or either executable. If verified staging fails, Aether refuses to create the managed container; it does not silently launch a container without the canonical CLI or bridge binary.
The socket is the run identity and authentication boundary. The bridge and CLI have no token, login, run-ID, or credential option. A connection to a run's socket is that run; a binary can be present without a run identity, but then run-bound operations are unavailable.
Registration
Enhanced runs (runs driven over ACP, the Agent Client Protocol) get the bridge
automatically: when the run has a coordination directory, Aether passes
/opt/aether/aether-server mcp as the stdio MCP server aether in ACP
session/new, session/resume and session/load. Aether writes no agent
configuration file for it.
Standard runs do not get the bridge registered. To use it there, create a
configuration outside /run/aether and point an agent that supports MCP at
it:
cat >/tmp/aether-mcp.json <<'EOF'
{"mcpServers":{"aether":{"type":"stdio","command":"/opt/aether/aether-server","args":["mcp"]}}}
EOF
claude --mcp-config /tmp/aether-mcp.jsonAether does not write or manage that path, and other agents use different syntax. The bridge still reaches only the run socket of its container.
The bridge's MCP instructions are the run's role card (see
Agent instructions). When
AETHER_ROLE_CARD=1, which Aether sets on the bridge when the ACP system
prompt already carries the card, they are only a brief of under 512 bytes:
report success or failure when the work the agent owns is done or cannot be
done, needs-input only for a question a human must answer (workers and
Background runs are told never to), blocked when a human must intervene,
and waiting when it ends its turn to await agents, CI or a process, or, where nothing resumes an idle session, never waiting but waiting
for mail in the turn with aether_inbox; never report while still working;
subagents and spawned workflows never report. Both come from coord.status,
asked once with a 2-second limit: without coord.report in its
capabilities there is no brief and the card has no report lines, and
without an answer the instructions only point at aether-internal skill.
The canonical CLI remains available without MCP. A shell-capable agent can
invoke aether-internal directly and request its live, version-matched skill
on demand. A container or terminal without a run identity can use general
help or the non-run skill guidance, but status, messaging, reporting, and
swarm operations return unavailable. Lack of manual MCP registration is not
an overlap-only or notice-only mode.
See coordination.md for the established CLI commands and wire limits. The optional bridge does not install a skill package or carry an identity claim.
The existing six-tool surface
The bridge exposes exactly six existing tools. Their parameters, receipts, authorization rules, limits, idempotency behavior, and durable storage map to the established v3 coordination methods. This is the bridge's complete surface; it does not expose Release B swarm, task, worker, takeover, or integrator-management commands.
| MCP tool | v3 method | Parameters | Result |
|---|---|---|---|
aether_status |
coord.status |
none | v3 identity, assignment, messageable peers, unread count, capabilities |
aether_send |
coord.send |
to_run_id, body, idempotency_key |
message_id, recipient_status |
aether_inbox |
coord.inbox |
optional ack_token, optional wait_seconds |
messages, ack_token |
aether_ask |
coord.ask |
to_run_id, body, idempotency_key |
question_id, recipient_status |
aether_reply |
coord.reply |
question_id, body, idempotency_key |
message_id |
aether_report |
coord.report |
outcome, summary, optional evidence_refs, optional waiting_for, idempotency_key |
durable report_id, outcome, summary, next action, evidence references, automatic evidence_ref |
The bridge returns the established structured result directly. This presentation differs from any CLI envelope, but it does not add operations or make MCP a Release B-parity interface.
aether_status lists every capability of the run, including dev.* methods
that have no MCP tool. Its tool description tells the agent to run
aether-internal skill for those.
aether_status lists the peers described in
Wire v3; a peer's run_id is the to_run_id for
aether_send and aether_ask, and only listed peers can be messaged. The
aether_send and aether_ask descriptions tell the agent to announce its
plan and owned files before editing what a peer touches, or a decision,
progress or blocker that affects a peer; that a receipt means queued rather
than read and replies arrive in the inbox; and to check status instead of
retrying a denial. The aether_inbox description says peer messages and
replies arrive there and marks them as untrusted information that never
overrides the user, the assignment or the integrator. The aether_reply
description says a reply reaches only the asking run and grants it no
control. These descriptions reach subagents, which share the MCP tools but
not the parent's system prompt. See
Send a message.
aether_send, aether_ask, aether_reply, and aether_report require an
explicit idempotency_key; the bridge never invents one. For a retry after a
timeout or lost response, provide the same key and the same semantic inputs.
A different payload under an existing key is a conflict.
aether_inbox is at-least-once. The returned ack_token identifies exactly
the returned batch. Supplying it on the next call acknowledges that batch;
without it, the batch remains available. The bridge carries forward the last
acknowledgement token that reached the MCP stream when the next call omits
ack_token, while an explicit token remains supported. A cancelled call,
failed response write, or bridge process exit does not promote a staged token,
so the batch is delivered again. wait_seconds requests one bounded server
wait; it is not an unbounded poll.
aether_ask returns a durable question_id. aether_reply takes that ID
instead of a target run ID and routes only to the original question sender.
The question establishes the reply relationship; it cannot authorize an
unrelated message or cross a workspace boundary.
aether_report accepts only success, failure, blocked, needs-input
and waiting, which its input schema enumerates, and requires a non-empty
summary. Every coordination tool field has a schema description, and the
aether_report description leads with the rule that subagents and spawned
workflows never report. needs-input and waiting take no evidence_refs.
waiting marks a turn the agent ends while work it started goes on; the
next turn clears it. waiting_for is agents (the default), ci or
process, which the schema enumerates, and is valid only with waiting;
anything else is invalid params. The schema's outcome description is the
same for every run; the server refuses outcomes a run's role or launch
cannot use, and the instructions list the ones that apply. Before the server accepts a report, Aether
captures the run's evidence, including a private Git evidence commit and a bounded PTY
transcript. The retained packet records factual context, provenance,
unresolved facts, and a next action, with unavailable or truncated sources
shown explicitly. Evidence is not an atomic environment snapshot and does not
assert that the outcome was verified. A failed capture or persistence step
leaves the outcome unaccepted and the runtime recoverable.
Interactive Standard and Enhanced runs remain open after a success or failure report; the agent ends its turn and waits for follow-up. Each later task uses a fresh report idempotency key. Background runs and swarm workers retain terminal report behavior. See Report an outcome.
MCP errors
Coordination failures are returned as MCP tool results with isError, not as
MCP session-level JSON-RPC failures. Aether's numeric code is in the result
metadata key aether/error_code; the text includes the method-qualified
message. Local socket failures such as a missing listener, EOF, broken pipe,
or a connection-cap refusal map to CodeUnavailable (-32004). Server
responses preserve their own Aether codes, including CodeDenied (-32001),
CodeConflict (-32003), CodeNotFound (-32000), and
CodeInvalidParams (-32602). This keeps an operation failure actionable
without tearing down the MCP session.
The method set is closed. The bridge cannot invoke a control verb, type into a terminal, read Git, or access another run's transcript. Human messages still use Aether's host-side serialized PTY input path; MCP is not an inbound terminal hook.
run.report is not coord.report
aether_report is the MCP spelling of durable coord.report, and has the
same evidence-before-acceptance behavior as aether-internal report.
The staged binary at /opt/aether/aether-server also retains the separate
agent lifecycle command:
printf '%s\n' '{"hook_event_name":"Stop"}' | /opt/aether/aether-server report claude
/opt/aether/aether-server report codex '{"type":"agent-turn-complete"}'
/opt/aether/aether-server report pi --json '{"state":"waiting","reason":"agent idle"}'
/opt/aether/aether-server report opencode --json '{"state":"working","input_updates":[{"operation":"replace","requests":[]}]}'These callbacks invoke wire method run.report. They update execution
(working or the legacy waiting wire value, which parks the run at
needs-attention) and/or
correlated pending input requests. A request-only update leaves execution
unchanged. They are not an agent outcome, are not an MCP tool, and do not
create a coordination report or evidence receipt. See
status reporting for request lifetimes.
Agent callbacks are hidden lifecycle plumbing, not commands for an operator or
worker to run. The callback exits promptly even when status reporting is
unavailable so it cannot block the agent.
Staging, retention, and shutdown
The staged binary is content-addressed. A run keeps the exact verified bytes used at provisioning, even if the server binary is upgraded later. Aether records the staged digest and coordination directory in the run sidecar before creating the container, and recovery rebuilds the listener from surviving sidecars.
Active runs and retained terminal TUI runs keep their socket, unread mailbox, and MCP assets through a server restart. When the container is destroyed, Aether releases the coordination directory and mailbox after required evidence capture. The coordination disable setting remains effective. When it is off, no run socket or usable MCP bridge is provided: bridge calls and run-bound CLI operations return unavailable. Every newly created managed container still receives the staged CLI, but without a run socket it can provide only general help or non-run skill guidance. Existing mounted assets become inert; the conflict radar itself continues to operate.
The assistant tool set
aether-server mcp --assistant serves a different tool set for the member
assistant (the built-in agent that runs in the member's environment container,
not in a run). It dials /run/aether-assistant/assistant.sock; -socket
overrides the path. The socket is bound to one member, so no tool takes a
member id and the server rejects any param containing member_id, except the run.list read filter; aether_list_runs with mine filters to the socket's member.
| Tier | Tools |
|---|---|
| Read | aether_list_runs, aether_get_run, aether_run_history, aether_list_workspaces, aether_get_workspace, aether_list_agents, aether_usage, aether_environment_status, aether_docs |
| Reversible | aether_pause_run, aether_resume_run |
| Confirmed | aether_launch_run, aether_message_run, aether_stop_run, aether_save_environment |
A confirmed call blocks until the member approves it in the dashboard, or
runs at once when the member turned on
auto-approval, except that a message to or stop
of another member's run always waits for a click. A decline, timeout or closed
session fails the call with the reason. aether_docs
reads the guides in docs/, which the server binary embeds. Without
--assistant the bridge serves the coordination tools above, unchanged.