serve mcp and serve acp
serve mcp exposes each agent as one MCP tool over stdio or streaming HTTP on port 8081, and serve acp speaks the Agent Client Protocol to an editor over stdio.
Your MCP client already calls tools, and your editor already talks to coding agents. Neither of them reads an agent file. serve mcp turns the agent into a tool for the first, and serve acp turns it into an editor agent for the second.
When you finish this section, you can serve an agent as an MCP tool, read its schema, and open an ACP session from an editor.
serve mcp: one agent, one tool
serve mcp: starts an MCP server that serves the agent over the Model Context Protocol, with stdio transport by default. --http switches to streaming HTTP on 127.0.0.1:8081. Without -a, every agent of a team file becomes its own tool, and --tool-name renames the tool when one agent is exposed.
--attach exposes the session of a running TUI, found by pid, address, or session id. --mcp-keepalive works over stdio only, while --auth-token, --insecure-no-auth, and --safety work with --http only. Over HTTP the safety policy defaults to restricted.
The capture ran serve mcp fixtures/agents/pong.yaml --http --listen 127.0.0.1:8081 --tool-name pong, with the file of serve api and serve chat:
…
"method": "initialize",
"params": {
"protocolVersion": "2026-07-28",
…
Content-Type: text/event-stream
…
message
{"jsonrpc":"2.0","id":1,"result":{"capabilities":{"logging":{},"tools":{"listChanged":true}},"protocolVersion":"2025-11-25","serverInfo":{"name":"docker agent","version":"v1.149.0"}}}
…
{"jsonrpc":"2.0","id":2,"result":{"ttlMs":0,"cacheScope":"public","tools":[{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true,…"inputSchema":{…"properties":{"message":{"description":"the message to send to the agent","type":"string"}},"required":["message"],"type":"object"},"name":"pong","outputSchema":{…
…
{"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"{\"response\":\"pong\"}"}],"structuredContent":{"response":"pong"}}}The client asked for revision 2026-07-28, which v1.129.0 added together with a stateless Streamable HTTP transport. The server answered 2025-11-25, so read the version from the result, never from your request. No response carried an Mcp-Session-Id header. Each answer came as one SSE message event, and the notification got 202 Accepted (the capture).
The tool takes one string, message, and returns structuredContent.response, with the same text as a JSON string in content. Its annotations mark it read-only and idempotent, and its title is the agent's description. The tools/call answer came as one event after the whole turn, with no progress notification before it. The kit README adds that the server answered on / as well as /mcp (the capture). The docs register the stdio form in Claude Code with claude mcp add --transport stdio, followed by -- docker agent serve mcp and the agent reference.
serve acp: JSON-RPC lines to an editor
serve acp: a server that talks over stdio, the standard input and output. The editor spawns docker-agent serve acp FILE, writes JSON-RPC requests to its stdin, and reads responses and notifications from its stdout. Sessions persist in <data-dir>/session.db unless -s names another file. A team file works as well, and the docs say its sub-agents need no change for ACP.
>> {"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": 1, …}}
<< {"id": 1, "jsonrpc": "2.0", "result": {"agentCapabilities": {"auth": {"logout": {}}, "loadSession": true, …, "agentInfo": {"name": "docker agent", "title": "docker agent", "version": "v1.149.0"}, …, "protocolVersion": 1}}
>> {"jsonrpc": "2.0", "id": 2, "method": "session/new", "params": {"cwd": "$CAPTURE", "mcpServers": []}}
<< {"jsonrpc": "2.0", "method": "session/update", "params": {"sessionId": "<uuid>", "update": {"availableCommands": [{"description": "Summarize and compact session history", …, "name": "compact"}, {"description": "Display current context token usage and session cost", "name": "usage"}], "sessionUpdate": "available_commands_update"}}}
<< {"id": 2, "jsonrpc": "2.0", "result": {"configOptions": [{"category": "mode", "currentValue": "default", …}], "modes": {…, "currentModeId": "default"}, "sessionId": "<uuid>"}}initialize returns agentCapabilities: loadSession, MCP servers over HTTP and SSE, audio, image, and embedded-context prompts, and the session operations close, delete, list, and resume. It offers one auth method, host-credentials, which v1.144.0 added together with session deletion. Before the session/new result, a session/update notification lists the slash commands. Release v1.143.0 announced /compact, /usage, and /new, and the captured list has no new.
The session starts in mode default, which auto-approves read-only tools and asks for the rest. The mode list adds default to the four values of --safety. A client changes the mode with session/set_config_option or the older session/set_mode. The capture stops at session/new, so it shows no prompt turn over ACP. The docs sketch the host side with a method agent/run and call that code pseudocode. Use the method names of the capture.
For the protocol under serve mcp, read the MCP transports lesson.
Docker Sandboxes (sbx) and Docker Agent (docker-agent) sbx 0.47.0, docker-agent 1.149.0 · bf4169c · 2026-10-07 · Edition 2026.10