MCP server
Give an MCP-capable agent its own disposable machine. The MCP server exposes the same create / execute / destroy operations as the REST API, as tools the model can call directly.
What MCP is
The Model Context Protocol is a standard way for an AI application to connect a model to external tools. The client (Claude Code, Claude Desktop, or any other MCP client) starts a server process, discovers the tools it offers, and lets the model call them. Our server is a small stdio process that turns those tool calls into API requests with your key — so the agent gets a sandbox without you writing any integration glue.
Install
The server runs through npx; there is nothing to install ahead of time. It needs
Node.js 18 or newer and an API key from Dashboard → API keys.
Claude Code
claude mcp add sandbox \
--env AAS_API_KEY=aas_sk_your_key_here \
-- npx -y https://sandbox-as-a-service.com/mcp.tgz
Then check it is connected:
claude mcp list
Claude Desktop
Edit the MCP config file
(~/Library/Application Support/Claude/claude_desktop_config.json on macOS,
%APPDATA%\Claude\claude_desktop_config.json on Windows) and restart the app:
{
"mcpServers": {
"sandbox": {
"command": "npx",
"args": ["-y", "https://sandbox-as-a-service.com/mcp.tgz"],
"env": {
"AAS_API_KEY": "aas_sk_your_key_here"
}
}
}
}
Other MCP clients
Any client that can launch a stdio server works. The contract is: run
npx -y https://sandbox-as-a-service.com/mcp.tgz with AAS_API_KEY in the environment. The server reads
the key at startup and exits with an error if it is missing.
AAS_API_KEY=aas_sk_your_key_here npx -y https://sandbox-as-a-service.com/mcp.tgz
Tools
| Tool | Arguments | What it does |
|---|---|---|
create_sandbox | size (small | medium | large, default small), name, timeout_minutes (1–1440, default 15) | Creates a sandbox and returns its id once it is ready. Blocks until then. |
run_command | sandbox_id (required), command (required), timeout_ms, cwd, env | Runs a shell command as the unprivileged sandbox user and returns exit code, stdout and stderr. |
write_file | sandbox_id (required), path (required), content (required), encoding | Writes a file into the sandbox. Content is transferred out of band, so quotes, backticks and binary data survive intact. |
read_file | sandbox_id (required), path (required), encoding | Reads a file back out — how the agent gets at whatever its code produced. |
list_files | sandbox_id (required), path | Lists a directory recursively, with types and sizes. Lets the agent discover what a run produced rather than guessing. |
get_sandbox | sandbox_id (required) | Returns status, size, and the expiry timestamp. |
list_sandboxes | limit, include_deleted | Lists your sandboxes, newest first — useful for finding strays. |
extend_sandbox | sandbox_id (required), additional_minutes (required) | Pushes the expiry out, up to the 1440-minute ceiling, when a job outgrows its timeout. |
destroy_sandbox | sandbox_id (required) | Destroys the sandbox and stops billing for it. |
get_usage | none | Reports the remaining credit balance and recent usage, so the agent can see what it is spending. |
The filesystem tools are what make the difference between an agent that can run a command and an agent that can do a piece of work: it writes a script, runs it, lists the directory to see what appeared, and reads the result back. Before those existed it had to build heredocs by hand, and generated code containing a quote would break the command that was supposed to write it.
The tools enforce exactly the same limits as the REST API — 20 concurrent sandboxes,
the 24 hours lifetime ceiling, 1 MiB of captured output per stream — and surface the same
errors, so an agent that hits quota_exceeded gets a message telling it to destroy a
sandbox first.
Agent workflows
1. Run generated code before trusting it
The most useful thing an agent can do with a sandbox is check its own work. Instead of asking you to run a script it just wrote, it runs it somewhere disposable and reads the traceback.
You: Write a script that de-duplicates this CSV by email, keeping the newest row.
Verify it works on a sample before showing it to me.
Agent: create_sandbox { "name": "csv-dedupe", "timeout_minutes": 15 }
-> sbx_9f2c4a1b8d3e6f0a12
write_file { "sandbox_id": "sbx_...", "path": "sample.csv",
"content": "email,updated_at\n..." }
write_file { "sandbox_id": "sbx_...", "path": "dedupe.py",
"content": "import csv, sys\n..." }
run_command { "sandbox_id": "sbx_...",
"command": "python3 /workspace/dedupe.py sample.csv" }
-> exit_code 1, stderr: KeyError: 'Email'
(fixes the case-sensitivity bug, re-runs)
-> exit_code 0, stdout: 412 rows -> 388 rows
destroy_sandbox { "sandbox_id": "sbx_..." }
2. Reproduce a bug in a clean checkout
"Works on my machine" stops being a question when the agent can build a fresh machine. Nothing from your laptop — no stale cache, no half-installed dependency, no local env var — is in the picture.
You: Issue #412 says the test suite fails on a fresh clone. Confirm it, and find out why.
Agent: create_sandbox { "size": "medium", "timeout_minutes": 60 }
run_command { "command": "git clone --depth 1 https://github.com/acme/widget.git /workspace/w",
"timeout_ms": 180000 }
run_command { "cwd": "/workspace/w",
"command": "python3 -m venv .venv && .venv/bin/pip install -q -e '.[test]'",
"timeout_ms": 300000 }
run_command { "cwd": "/workspace/w",
"command": ".venv/bin/pytest -x -q 2>&1 | tail -c 20000",
"timeout_ms": 600000 }
-> reproduces: the suite assumes a TZ env var that CI sets and a clean box does not
destroy_sandbox { "sandbox_id": "sbx_..." }
3. Try a risky change without touching anything you own
Dependency bumps, migration scripts and "let's see what this does" commands belong on a machine whose worst case is a wasted few cents.
You: Does upgrading to pandas 3 break our ETL? Don't touch my working copy.
Agent: create_sandbox { "size": "medium", "name": "pandas-3-trial", "timeout_minutes": 45 }
run_command { "command": "git clone --depth 1 https://github.com/acme/etl.git /workspace/etl",
"timeout_ms": 180000 }
run_command { "cwd": "/workspace/etl",
"command": "python3 -m venv .venv && .venv/bin/pip install -q -r requirements.txt",
"timeout_ms": 300000 }
run_command { "cwd": "/workspace/etl",
"command": ".venv/bin/pip install -q 'pandas>=3' && .venv/bin/pytest -q 2>&1 | tail -c 20000",
"timeout_ms": 600000 }
-> 3 failures, all in the groupby-apply path; reports the diff needed
destroy_sandbox { "sandbox_id": "sbx_..." }
Operating notes
- Agents forget to clean up. Sandboxes expire on their own, but until then they bill. Ask the agent to destroy sandboxes when it is done, keep
timeout_minutesshort, and runlist_sandboxesoccasionally to catch strays. - Keep the key out of the sandbox.
AAS_API_KEYbelongs in the MCP server's environment, never in anenvpassed torun_command— code inside a sandbox that has your key can spend your balance. - Nothing survives. When the sandbox is destroyed its disk is destroyed. Have the agent copy results out — into its reply, into a git remote, or into your own storage — before it destroys the machine.
- The concurrency limit is shared. 20 sandboxes per account, counting whatever your other integrations are running.