Runtime

How to run an MCP server in a sandbox

Call sbx.mcp.start([{ id: "github" }]), wait for sbx.mcp.ready(), and give your agent each server's HTTPS URL and bearer header.

On Runtime a catalog MCP server starts in one call, and its API key never enters the sandbox. A setting that holds a key names a Runtime secret: the server sees only a placeholder, and the egress proxy outside the microVM adds the real value to its HTTPS requests to that secret's own hosts. The catalog shipped on 24 September 2026 with servers for GitHub, Postgres, a Playwright browser, filesystem, fetch, git, time, memory, Notion, Context7, Brave Search, Exa, Firecrawl and Supabase, all MIT or Apache-2.0. A 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while the servers wait for calls (pricing).

Start servers from the catalog

Store the token once as a secret, then start the servers by id:

TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.secrets.set("GITHUB_TOKEN", {  value: process.env.GITHUB_TOKEN ?? "",  hosts: ["api.github.com"],});await using sbx = await runtime.sandboxes.create({ timeoutSeconds: 3600 });await sbx.mcp.start([  { id: "github", secrets: { GITHUB_PERSONAL_ACCESS_TOKEN: "GITHUB_TOKEN" } },  { id: "fetch" },]);const gateway = await sbx.mcp.ready(); // waits until every server is installedfor (const server of gateway.servers) console.log(server.name, server.status, server.url);console.log(gateway.headers); // { Authorization: "Bearer ..." }
Pythonimport osfrom withruntime import Runtimeruntime = Runtime()runtime.secrets.set("GITHUB_TOKEN", value=os.environ.get("GITHUB_TOKEN", ""),                    hosts=["api.github.com"])with runtime.sandboxes.create(timeout_seconds=3600) as sbx:    sbx.mcp.start([        {"id": "github", "secrets": {"GITHUB_PERSONAL_ACCESS_TOKEN": "GITHUB_TOKEN"}},        {"id": "fetch"},    ])    gateway = sbx.mcp.ready()    for server in gateway["servers"]:        print(server["name"], server["url"])    print(gateway["headers"])
Terminalruntime secrets set GITHUB_TOKEN --host api.github.com < token.txtruntime sandbox mcp "${id}" start github fetch --secret github.GITHUB_PERSONAL_ACCESS_TOKEN=GITHUB_TOKENruntime sandbox mcp "${id}"         # state, URLs and the header to sendruntime sandbox mcp "${id}" stop

The CLI's start also prints a claude mcp add line for each server, so Claude Code can use them at once. runtime sandbox mcp catalog (or runtime.mcp.catalog()) lists every server with its licence, pinned version, settings and the hosts it calls.

Connect an agent to the URLs

Each server answers at its own Streamable HTTP URL, reached through a private preview link. Every request also carries the gateway's bearer token. Any MCP client that speaks Streamable HTTP connects with those two values. Under the MCP specification a client sends each message as an HTTP POST to one endpoint and accepts either a JSON answer or an event stream:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.mcp.start([{ id: "time" }]);const gateway = await sbx.mcp.ready();const url = gateway.servers[0]?.url;const reply = await fetch(url!, {  method: "POST",  headers: {    ...gateway.headers,    "content-type": "application/json",    accept: "application/json, text/event-stream",  },  body: JSON.stringify({    jsonrpc: "2.0",    id: 1,    method: "initialize",    params: {      protocolVersion: "2025-06-18",      capabilities: {},      clientInfo: { name: "probe", version: "1.0.0" },    },  }),});console.log(reply.status, reply.headers.get("content-type"));

In practice you hand the URL and header to your agent framework's MCP client rather than writing JSON-RPC by hand.

Run your own stdio server

A server you wrote runs the same way. Upload it and name its command; the gateway turns its stdio into a URL like the catalog's:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.files.upload("./my-mcp", "/workspace/my-mcp");await sbx.exec("pip install -r my-mcp/requirements.txt", { check: true, timeoutMs: 300_000 });await sbx.mcp.start([{ name: "mine", command: ["python3", "my-mcp/server.py"] }]);console.log((await sbx.mcp.ready()).servers);
Pythonfrom withruntime import Sandboxwith Sandbox.create() as sbx:    sbx.files.upload("./my-mcp", "/workspace/my-mcp")    sbx.exec("pip install -r my-mcp/requirements.txt", check=True, timeout_ms=300_000)    sbx.mcp.start([{"name": "mine", "command": ["python3", "my-mcp/server.py"]}])    print(sbx.mcp.ready()["servers"])

The settings

Field What it does
id A catalog server, such as github, fetch or postgres
secrets Maps a setting the server reads to a Runtime secret; the server sees a stand-in
env Plain settings passed as given
options The catalog entry's own options
name and command Your own stdio server, run as the sandbox's user
sbx.mcp.ready() Waits until no server is still installing; status is ready or failed
gateway.headers The Authorization header every request needs
sbx.mcp.stop() Stops the servers; the sandbox keeps running
runtime_sandbox_mcp (MCP) The same catalog and start, for an agent already connected to Runtime's MCP

Mistakes and how Runtime handles them

  • Putting a token in env. It then sits in the sandbox, where any code there can read it. Put it in secrets instead, so a prompt injection that dumps the environment finds a worthless placeholder (secrets).
  • A database password. It is not an HTTPS header, so it cannot be swapped in on the way out; the Postgres server's DATABASE_URI is passed as given.
  • A host the network rules refuse. The servers run behind the sandbox's own rules. A catalog host the rules block comes back as a warning, and the rules are never changed for you.
  • Calling a URL without the header. Every request needs the bearer token as well as the preview link, so a leaked URL alone gets nothing.
  • Confusing two things called MCP. runtime mcp is Runtime's own MCP server, which lets an agent create and drive sandboxes (MCP). The servers on this page run inside one sandbox and serve your agent's tools.

Where this helps

  • An agent in Claude Code or Codex gets GitHub, browser or database tools without running them on your laptop.
  • Untrusted or third-party servers run in a microVM of their own, away from your machine and network (run untrusted LLM code).
  • What is MCP? explains the protocol.

Start

Terminalnpx withruntime sandbox run --trial --keep -- echo ready

New accounts get 50 free sandbox hours, no card. The first run prints a link to approve in your browser.

Sources

Facts on this page were checked on 25 September 2026.