MCP
An MCP-capable agent can call the sandbox's built-in tools directly for file, command, code, and browser work.
Requirements
Connect an MCP client to POST /mcp. Each tool still needs the plane it drives.
Read the available capabilities from capabilities in GET /v2/sandbox.
Read the available capabilities from GET /v1/capabilities.
With AIO_API_KEY set, send the key as Authorization: Bearer <key>; the endpoint is not public and answers 401 without it.
The tool list
Use tools/list to get the current tool list.
The built-in set is compiled into the binary, in that order:
Anything beyond these came from a registered MCP server, so read the list rather than a count. Each entry carries its own JSON Schema:
A complete workflow in four tool calls
The four JSON requests below write the numbers, count the lines, sum them in Python, and read the result back.
All four steps share one filesystem, so the command and code can read the file written in step 1.
1. Write the input file
2. Run a command
3. Run Python code
4. Read the result
Every result has a content list; a failed call sets isError to true. The text inside is what the model reads — the file tool's JSON, the command's output, or the interpreter's stdout. In full, step 1:
sandbox_execute_bash runs in one shared session unless new_session is set, and its result reports the cwd the session ended in. Pass that back on the next call and the agent's idea of the working directory stays in step with the shell's.
When a call fails
There are two failure shapes, depending on whether the tool ran. The requests below show an unknown tool and a missing file:
An unknown tool name, a missing tool name, or an unknown method is a JSON-RPC error. It still arrives on HTTP 200; the error object is what an MCP client parses:
A tool that ran and failed comes back as an ordinary result with isError: true. The text carries the reason, and the file plane passes its structured error straight through:
A missing argument is this second kind, not the first: sandbox_execute_bash without cmd answers isError: true and the text cmd is required. So do browser_gui_screenshot and browser_gui_execute_action with no computer-use worker, browser_get_info with no reachable CDP port, and any call to a registered MCP server that is down.
Aggregating another MCP server
EXTRA_MCP_SERVERS (or --mcp-servers) registers other MCP servers as {"name": {"url": ..., "prefix": ...}}. Their tools join the same catalogue, and a call to one is forwarded and its answer passed back unedited. Any stateless MCP server on loopback will do, so a second daemon is the cheapest way to see it work:
The rules behind that run:
- Only
http://on127.0.0.1,localhostor[::1]is accepted. Remote andcommand(stdio) entries are skipped with a warning at startup. - There is no handshake and no session, one POST per call, so an upstream may start after the daemon and appears on the next
tools/list. - With
prefix, tools are published as<prefix>_<tool>and the prefix comes off again on the way out. Without one, the server's own names must already start with<name>_; the rest are dropped, because nothing would say where to route them. - A built-in name wins a collision, and between two upstreams the first registered one keeps the name.
On the AIO image mcp-server-browser is registered exactly this way, which is where the page-level browser_* navigation tools in that image's list come from.
Connecting a client
Any client that supports streamable-HTTP MCP can connect to http://127.0.0.1:18091/mcp, or to the gateway's /mcp on the prebuilt images. With a key set, send it as a bearer header.
Related
- Agent Calls the Sandbox — the same four steps over REST
- Error Handling — the envelope,
isError, and the status codes - Sandbox Info & Capabilities — the same context through REST
- Migration from 1.x — what became of the 1.x MCP management routes