> ## Documentation Index
> Fetch the complete documentation index at: https://docs.superserve.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 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](https://modelcontextprotocol.io) 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](/sdk-reference/sandbox), so the per-sandbox data-plane token never reaches the model.

## Quickstart

Add the server to your client (see [Install](#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](/api-key) page. There's no global install; `npx` fetches the server on first use.

## Install

<Note>
  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).
</Note>

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
    claude mcp add superserve \
      --env SUPERSERVE_API_KEY=ss_live_xxxxxxxxxxxxxxxx \
      -- npx -y @superserve/mcp
    ```
  </Tab>

  <Tab title="Claude Desktop">
    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" }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Cursor">
    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" }
        }
      }
    }
    ```
  </Tab>

  <Tab title="VS Code">
    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}" }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Windsurf">
    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" }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Codex">
    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"`.
  </Tab>
</Tabs>

## Hosted (remote)

Don't want to run anything locally? The hosted endpoint at `https://mcp.superserve.ai` speaks [Streamable HTTP](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports) — 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.

<Note>
  Bearer auth works in any client that lets you set a request header — Claude
  Code, Cursor, VS Code, and the Anthropic Messages API connector. Claude.ai,
  Claude Desktop's Custom Connector UI, and ChatGPT developer mode don't offer a
  static-bearer / custom-header field (they expect OAuth), which the hosted
  endpoint doesn't support yet — use the [local](#install) install there.
</Note>

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
    claude mcp add --transport http superserve https://mcp.superserve.ai \
      --header "Authorization: Bearer ss_live_xxxxxxxxxxxxxxxx"
    ```
  </Tab>

  <Tab title="Cursor">
    Add to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):

    ```json theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
    {
      "mcpServers": {
        "superserve": {
          "url": "https://mcp.superserve.ai",
          "headers": { "Authorization": "Bearer ss_live_xxxxxxxxxxxxxxxx" }
        }
      }
    }
    ```
  </Tab>

  <Tab title="VS Code">
    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}" }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Messages API">
    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"
        }
      ]
    }
    ```
  </Tab>
</Tabs>

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"*:

```text theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
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_exec` and the file tools transparently resume a paused sandbox, so agents never need to call `sandbox_resume` first. `sandbox_resume` exists only to warm a sandbox explicitly.
* **Output is capped for context.** `sandbox_exec` truncates stdout and stderr to 32 KiB each — a truncated result sets `truncated: true` and reports the original byte length. `sandbox_files_read` **rejects** files larger than 1 MiB (it does not return partial content); the error tells you to read a slice with `sandbox_exec` (e.g. `head -c`) or download the whole file with the SDK/CLI. `sandbox_files_write` inline 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_out` alone does **not** lock a sandbox down — for a strict allowlist, combine it with `deny_out: ["0.0.0.0/0"]` (deny all, then allow the listed destinations). Set these on `sandbox_create` or `sandbox_update`, and audit what a sandbox actually reached with `sandbox_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:

1. Create the secret once with the [TypeScript SDK](/sdk-reference/sandbox) (`Secret.create()`) or the [console](/secrets/overview) — the raw value never travels through the agent or the MCP server, so **secret creation is intentionally not an MCP tool**.
2. Discover bindable secrets with `secret_list` (metadata only — values never leave the platform).
3. Bind at creation — `secrets: { ANTHROPIC_API_KEY: "anthropic-prod" }` on `sandbox_create` — or later with `sandbox_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](/sdk-reference/sandbox) directly for:

* **Secret creation** — `Secret.create()` (the MCP server only *binds* existing secrets).
* **Streaming and interactive commands** — streaming `run()` callbacks and `commands.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](/sdk-reference/sandbox) 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_KEY` in the server's `env` block (see [Install](#install)), not just in your terminal.
* **`Authentication failed`.** The key is missing or invalid. Production keys start with `ss_live_`; create one on the [API key](/api-key) page.
* **First call is slow.** `npx` downloads 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](#hosted-remote) endpoint has no local runtime requirement.)
* **`401 Unauthorized` from the hosted endpoint.** The bearer token is missing or isn't a valid `ss_live_` key. Send it as `Authorization: Bearer ss_live_…` (see [Hosted](#hosted-remote)).

## Related

<CardGroup cols={2}>
  <Card title="Sandbox lifecycle" href="/sandbox/lifecycle">
    Pause, resume, and delete sandboxes.
  </Card>

  <Card title="Run commands" href="/commands/overview">
    Exec, streaming, cwd, env, and timeouts.
  </Card>

  <Card title="Secrets" href="/secrets/overview">
    Broker provider keys without exposing them to the sandbox.
  </Card>

  <Card title="TypeScript SDK" href="/sdk-reference/sandbox">
    The library the MCP server wraps.
  </Card>
</CardGroup>
