MCP server

An MCP sandbox your agent can provision for itself

Connect an MCP-compatible agent to a hosted server and it gains four tools: create a disposable Linux VM, run shell commands in it, extend it, destroy it. No Docker daemon on the developer's machine, no integration code, and no risk of a generated command landing on the filesystem you actually work in.

Why MCP changes the integration, not just the transport

Without MCP, giving an agent a sandbox means writing the tool definition, the dispatch code, the argument validation, the result formatting and the lifecycle handling — in your application, per agent framework. With MCP, the tool definitions come from the server. The agent discovers them, calls them, and gets structured results back, and the code you would have written does not exist.

The more interesting shift is who owns the sandbox. When an agent can call create_sandbox itself, the workspace becomes something it manages as part of solving the task, in the same way it manages a plan or a file. You are no longer pre-provisioning an environment and hoping it matches what the task turns out to need.

Configuration

Point your client at the server and give it a key. The tools appear on the next session.

{
  "mcpServers": {
    "sandbox": {
      "type": "http",
      "url": "https://sandbox-as-a-service.com/mcp",
      "headers": {
        "Authorization": "Bearer aas_sk_3f9c2a7b1e4d8065af23c1"
      }
    }
  }
}
create_sandbox(size?, timeout_minutes?)
  -> { id, status, size, expires_at }
  Provision a dedicated VM. size is one of small | medium | large.
  timeout_minutes defaults to 15, maximum 1440 (24 hours).

exec(sandbox_id, command, timeout_ms?, cwd?, env?)
  -> { stdout, stderr, exit_code, duration_ms, truncated }
  Run one shell command as an unprivileged user. State persists between
  calls: files written by one command are there for the next.

extend_sandbox(sandbox_id, additional_minutes)
  -> { id, expires_at }
  Push the expiry out for a job that is running longer than planned.

destroy_sandbox(sandbox_id)
  -> { id, status }
  Destroy the machine and stop billing immediately.
# What the transcript looks like when the agent drives it

> Check whether this repo's test suite passes on Node 22.

  create_sandbox(size="small", timeout_minutes=30)
    -> { "id": "sbx_8f2c19a4", "status": "running" }

  exec(sbx_8f2c19a4, "git clone --depth 1 https://github.com/acme/widget .")
    -> exit_code 0

  exec(sbx_8f2c19a4, "node --version && npm ci", timeout_ms=300000)
    -> exit_code 0, stdout "v22.11.0 ..."

  exec(sbx_8f2c19a4, "npm test 2>&1 | tail -n 40", timeout_ms=180000)
    -> exit_code 1, stdout "2 failing ... TypeError: ..."

  destroy_sandbox(sbx_8f2c19a4)

Two tests fail on Node 22, both in date parsing — details below.

Operating it sensibly

One key per client

Keys are created in the dashboard and displayed once. Issue a separate one for each machine or agent so a compromised laptop costs you one revocation rather than a rotation across everything you own.

Set the lifetime deliberately

An agent asked to pick a timeout will usually pick generously. If you care about spend, create the sandbox yourself with the lifetime you want and expose only exec to the agent, or keep the default short and let it call extend_sandbox when it genuinely needs more.

Keep secrets out of the environment

The agent chooses the commands, so anything in the sandbox environment is reachable by any command it writes — including one it was manipulated into writing. Pass task-scoped, short-lived values in the env of the single call that needs them.

Watch the balance, not the clock

GET /v1/usage reports the current balance. Because sandboxes cannot outlive their timeout and cannot exceed the concurrency limit, the worst case for an unattended agent is bounded — but it is bounded by your prepaid credit, so keep the float small.

Questions

What is the advantage over a local Docker-based MCP sandbox?

Three practical ones. It works on machines without Docker, including a coworker's laptop and any hosted agent runtime. The isolation boundary is a separate machine rather than a container on the same kernel as your work, so a mistake cannot touch your filesystem or your local network. And nothing accumulates locally — no images, no dangling volumes, no daemon to keep running. The trade is a network round trip per command and a cost per second of runtime.

Which tools does the server expose?

The same operations as the REST API: create a sandbox, execute a shell command in it, extend its lifetime, and destroy it. Keeping the tool surface small is intentional — every tool definition consumes context on every turn, and a shell command already expresses everything a specialised tool would.

Does the agent manage the sandbox lifecycle itself?

It can, and it will sometimes get it wrong — agents forget to destroy things. That is why the timeout is the real guarantee: a sandbox the agent abandons is destroyed when it expires, at most 24 hours later, and the 20-sandbox concurrency limit stops a confused agent from creating dozens. You can also create the sandbox yourself and give the agent only the exec tool.

How is the connection authenticated?

With the same API key as the REST API, passed as a bearer token in the client configuration. Keys are created in the dashboard and shown once. Use a separate key per client so you can revoke one without disrupting the others, and treat the key as a credential that grants spending on your account.

Which clients work with it?

Any MCP client that supports remote servers over HTTP — Claude Code, Claude Desktop and the other MCP-compatible agent runtimes. MCP is a protocol rather than a vendor integration, so there is nothing client-specific in the server.

Can I use both MCP and the REST API on the same sandbox?

Yes. Both are views onto the same resources under the same account, so a sandbox created through the REST API can be driven by an MCP client and vice versa. That is useful for supervision: your orchestrator creates the machine with the lifetime and size it wants, and the agent only executes inside it.

Connect your agent

Create a key, paste one config block, and your agent has a machine of its own.