Superserve Sandbox MCP
officialSecure virtual machines for agents hosted by Superserve
What can you do with Superserve Sandbox MCP?
- Create an isolated sandbox — ask the assistant to spin up a Firecracker microVM with
sandbox_create, optionally attaching secrets and egress rules. - Run shell commands inside a sandbox — execute commands via
sandbox_execand get back stdout, stderr, and exit code (auto-resumes paused sandboxes). - Read and write files in the sandbox — use
sandbox_files_readandsandbox_files_writeto inspect or place files, with automatic parent-directory creation. - Expose a public endpoint from a sandbox — start a server process and call
sandbox_preview_urlto obtain a publicly reachable URL for a listening port. - Audit outbound network traffic — check which hosts a sandbox contacted and whether they were allowed or denied with
sandbox_network_log. - Build and manage custom templates — create a template with specific vCPU/memory/disk or preinstalled software using
sandbox_template_create, then launch sandboxes from it.
Documentation
MCP Server
Create, run, and manage Superserve sandboxes from any MCP client.
The Superserve MCP server (@superserve/mcp) exposes sandbox primitives as Model Context Protocol tools, so any MCP-capable client — Claude, Cursor, VS Code, Windsurf, Codex — can create sandboxes, run commands, read and write files, build templates, broker secrets, and control network access in an isolated Firecracker microVM.
Run it two ways: locally over stdio via npx, or against the hosted endpoint at https://mcp.superserve.ai with no local install. Both authenticate with your SUPERSERVE_API_KEY and target a sandbox per call by ID. It's a thin wrapper over the TypeScript SDK, so the per-sandbox data-plane token never reaches the model.
Quickstart
Add the server to your client (see Install), then ask the agent to "create a sandbox and run python --version in it." The agent calls sandbox_create, then sandbox_exec, and reports the result — no code from you.
You need a Superserve API key — create one on the API key page. There's no global install; npx fetches the server on first use.
Install
Set `SUPERSERVE_API_KEY` in the server's `env` — MCP clients do not inherit it from your shell. Prefer a secret-input prompt over pasting the raw key where your client supports it (see VS Code below). ```bash theme={"theme":{"light":"github-light","dark":"vitesse-dark"}} claude mcp add superserve \ --env SUPERSERVE_API_KEY=ss_live_xxxxxxxxxxxxxxxx \ -- npx -y @superserve/mcp ``` Add to `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/`):```json theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
{
"mcpServers": {
"superserve": {
"command": "npx",
"args": ["-y", "@superserve/mcp"],
"env": { "SUPERSERVE_API_KEY": "ss_live_xxxxxxxxxxxxxxxx" }
}
}
}
```
Add to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):
```json theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
{
"mcpServers": {
"superserve": {
"command": "npx",
"args": ["-y", "@superserve/mcp"],
"env": { "SUPERSERVE_API_KEY": "ss_live_xxxxxxxxxxxxxxxx" }
}
}
}
```
Add to `.vscode/mcp.json`. The `inputs` block prompts for the key instead of storing it in plain text:
```json theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
{
"inputs": [
{
"id": "superserve-key",
"type": "promptString",
"description": "Superserve API key",
"password": true
}
],
"servers": {
"superserve": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@superserve/mcp"],
"env": { "SUPERSERVE_API_KEY": "${input:superserve-key}" }
}
}
}
```
Add to `~/.codeium/windsurf/mcp_config.json`:
```json theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
{
"mcpServers": {
"superserve": {
"command": "npx",
"args": ["-y", "@superserve/mcp"],
"env": { "SUPERSERVE_API_KEY": "ss_live_xxxxxxxxxxxxxxxx" }
}
}
}
```
Add to `~/.codex/config.toml`. `env_vars` forwards `SUPERSERVE_API_KEY` from your environment, so the raw key isn't stored in the config file (export it in your shell first). Codex also reads the server's `instructions` for cross-tool workflow guidance.
```toml theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
[mcp_servers.superserve]
command = "npx"
args = ["-y", "@superserve/mcp"]
env_vars = ["SUPERSERVE_API_KEY"]
```
For the [hosted](#hosted-remote) endpoint, use `url = "https://mcp.superserve.ai"` with `bearer_token_env_var = "SUPERSERVE_API_KEY"`.
Hosted (remote)
Don't want to run anything locally? The hosted endpoint at https://mcp.superserve.ai speaks Streamable HTTP — no npx, no Node. Send your Superserve API key as a bearer token. The endpoint is stateless and account-scoped (your key already maps to your team), and the per-sandbox data-plane token never leaves the server.
```json theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
{
"mcpServers": {
"superserve": {
"url": "https://mcp.superserve.ai",
"headers": { "Authorization": "Bearer ss_live_xxxxxxxxxxxxxxxx" }
}
}
}
```
Add to `.vscode/mcp.json`. The `inputs` block prompts for the key instead of storing it in plain text:
```json theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
{
"inputs": [
{
"id": "superserve-key",
"type": "promptString",
"description": "Superserve API key",
"password": true
}
],
"servers": {
"superserve": {
"type": "http",
"url": "https://mcp.superserve.ai",
"headers": { "Authorization": "Bearer ${input:superserve-key}" }
}
}
}
```
Pass it as a connector in an [Anthropic Messages API](https://docs.anthropic.com/en/docs/agents-and-tools/mcp-connector) request:
```json theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
{
"mcp_servers": [
{
"type": "url",
"name": "superserve",
"url": "https://mcp.superserve.ai",
"authorization_token": "ss_live_xxxxxxxxxxxxxxxx"
}
]
}
```
Same tools and behavior as the local server — the only difference is transport and that the key travels as a bearer header instead of an env var.
Tools
| Tool | What it does |
|---|---|
sandbox_create | Create a new sandbox; returns its id. Active and ready immediately. Accepts secrets and egress rules. |
sandbox_update | Change a sandbox's metadata or egress (allow_out/deny_out) rules after creation. |
sandbox_list | List your sandboxes (active and paused), filterable by metadata. |
sandbox_info | Get one sandbox's status, resources, metadata, network rules, and secret bindings. Read-only. |
sandbox_exec | Run a shell command; returns stdout, stderr, exit code. Auto-resumes a paused sandbox. |
sandbox_files_read | Read a file (UTF-8 text, or base64 for binary). |
sandbox_files_write | Create or overwrite a file. Parent directories are created automatically. |
sandbox_files_list | List a directory's entries (name, type, size, modification time). |
sandbox_files_download_dir | Download a directory as a base64 ZIP (symlinks skipped). Capped at 10 MiB; larger → SDK/CLI. |
sandbox_pause | Pause a sandbox; state is preserved. |
sandbox_resume | Resume a paused sandbox (usually unnecessary — exec auto-resumes). |
sandbox_kill | Permanently delete a sandbox. |
sandbox_preview_url | Build the public URL for a listening port (unauthenticated — anything on that port is internet-exposed). |
sandbox_network_log | Audit a sandbox's outbound connections (host, verdict, bytes). Auto-resumes a paused sandbox. |
sandbox_template_list | List the templates (base images) your team can launch from. |
sandbox_template_create | Build a custom template with a specific vCPU/memory/disk shape or preinstalled software (async — poll for ready). |
secret_list | List bindable team secrets (metadata only — never values). |
sandbox_attach_secret | Bind a stored secret to a running sandbox under an env var. |
sandbox_detach_secret | Remove a secret binding from a sandbox. |
Most tools take a sandbox_id; the exceptions are sandbox_create, sandbox_list, sandbox_template_list, sandbox_template_create, and secret_list. Start with one of those to get an ID, then thread it into later calls. Read-only tools (sandbox_list, sandbox_info, sandbox_files_read, sandbox_files_list, sandbox_files_download_dir, sandbox_preview_url, sandbox_template_list, secret_list) are annotated so clients can skip confirmation prompts; sandbox_kill is annotated destructive.
Example
A typical agent flow for "spin up a sandbox, write a Python script that prints the first primes, and run it":
sandbox_create { name: "primes" }
→ { id: "a1b2c3…", name: "primes", status: "active" }
sandbox_files_write { sandbox_id: "a1b2c3…", path: "/app/primes.py", content: "…" }
→ { path: "/app/primes.py", bytes: 142 }
sandbox_exec { sandbox_id: "a1b2c3…", command: "python /app/primes.py" }
→ { exit_code: 0, stdout: "2 3 5 7 11 13 17 19 23 29", stderr: "" }
When it's done, the agent can sandbox_pause (state preserved, cheaper to keep around) or sandbox_kill (permanent).
Configuration
| Variable | Required | Description |
|---|---|---|
SUPERSERVE_API_KEY | Yes | Your Superserve API key (starts with ss_live_). |
SUPERSERVE_BASE_URL | No | Override the control-plane URL (defaults to https://api.superserve.ai). |
Behavior and limits
- Auto-resume.
sandbox_execand the file tools transparently resume a paused sandbox, so agents never need to callsandbox_resumefirst.sandbox_resumeexists only to warm a sandbox explicitly. - Output is capped for context.
sandbox_exectruncates stdout and stderr to 32 KiB each — a truncated result setstruncated: trueand reports the original byte length.sandbox_files_readrejects files larger than 1 MiB (it does not return partial content); the error tells you to read a slice withsandbox_exec(e.g.head -c) or download the whole file with the SDK/CLI.sandbox_files_writeinline content is capped at 8 MiB. - Default command timeout is 60s, capped at 10 minutes. Override it per call with
timeout_ms. - Egress is controllable.
allow_out(domain patterns or CIDRs) adds allowed destinations;deny_out(CIDRs only) blocks them.allow_outalone does not lock a sandbox down — for a strict allowlist, combine it withdeny_out: ["0.0.0.0/0"](deny all, then allow the listed destinations). Set these onsandbox_createorsandbox_update, and audit what a sandbox actually reached withsandbox_network_log. - Errors are actionable. A failed tool call returns a short message telling the agent what to do next — e.g. "Sandbox quota reached. Pause or kill a sandbox, or retry later." — rather than a raw stack trace, so the agent can self-correct.
Secrets, templates, and ports
Secrets. Don't pass credentials as plaintext env_vars. Instead:
- Create the secret once with the TypeScript SDK (
Secret.create()) or the console — the raw value never travels through the agent or the MCP server, so secret creation is intentionally not an MCP tool. - Discover bindable secrets with
secret_list(metadata only — values never leave the platform). - Bind at creation —
secrets: { ANTHROPIC_API_KEY: "anthropic-prod" }onsandbox_create— or later withsandbox_attach_secret/sandbox_detach_secret.
The sandbox sees a proxy token; the platform swaps in the real credential only for outbound requests to the secret's allowed hosts.
Templates. A sandbox inherits its vCPU/memory/disk from its template and can't override them at sandbox_create time. To get a specific shape (say, a 4 vCPU sandbox) or preinstalled software, build a template with sandbox_template_create, then poll sandbox_template_list until its status is ready before passing it as from_template.
Ports. Start a server in the sandbox (sandbox_exec, e.g. python3 -m http.server 8000), then call sandbox_preview_url to get its public URL. Any process bound to a port is reachable at https://{port}-{id}.sandbox.superserve.ai with no authentication — only expose ports you intend to be public.
Not yet in the MCP surface
The MCP server covers the common agent loop; the table above is the complete v1 tool set. A few SDK capabilities aren't exposed yet — reach for the TypeScript SDK directly for:
- Secret creation —
Secret.create()(the MCP server only binds existing secrets). - Streaming and interactive commands — streaming
run()callbacks andcommands.spawn(stdin, signals, long-running processes). - Large or streaming transfers — directory download is supported up to 10 MiB via
sandbox_files_download_dir; beyond that (and for archive/streaming uploads or single files past the 1 MiB read / 8 MiB inline-write caps), use the SDK/CLI (files.downloadDir, streaming upload). - Billing and provider discovery — usage data and
Provider.list()for secret-provider setup.
These are tracked as follow-ups.
How it works
The server wraps the TypeScript SDK and only ever holds your control-plane SUPERSERVE_API_KEY. Each tool call connects to the target sandbox by ID; the SDK manages the per-sandbox data-plane access token internally and rotates it on resume, so it's never exposed to the model or returned in tool output. Tools are stateless — there's no hidden "current sandbox" — which keeps behavior predictable across multi-turn and parallel tool calls.
Troubleshooting
- Tools don't appear, or the server fails to start. The API key is almost always the cause — MCP clients do not inherit environment variables from your shell. Set
SUPERSERVE_API_KEYin the server'senvblock (see Install), not just in your terminal. Authentication failed. The key is missing or invalid. Production keys start withss_live_; create one on the API key page.- First call is slow.
npxdownloads the package on first use and caches it; later starts are fast. - Requires Node 18+. The local server runs on Node via
npx. (The hosted endpoint has no local runtime requirement.) 401 Unauthorizedfrom the hosted endpoint. The bearer token is missing or isn't a validss_live_key. Send it asAuthorization: Bearer ss_live_…(see Hosted).