# Runtime Cloud MCP Runtime's MCP server gives an agent every Runtime product as tools, with instructions on first contact, so it needs no wrapper code. MCP and the HTTPS API share authentication, ownership, spending checks and idempotency. ## Add it to your agent One command, no key to copy. Claude Code: ```bash no-run claude mcp add --scope user runtime -- npx -y withruntime mcp ``` Codex: ```bash no-run codex mcp add runtime -- npx -y withruntime mcp ``` or, in `~/.codex/config.toml`: ```toml [mcp_servers.runtime] command = "npx" args = ["-y", "withruntime", "mcp"] ``` Cursor, in `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project), and any other client that takes the same shape: ```json { "mcpServers": { "runtime": { "command": "npx", "args": ["-y", "withruntime", "mcp"] } } } ``` **The first time, one approval connects it.** When this machine is not connected, the server offers one tool, `runtime_connect`: 1. The agent calls it and shows you a link and a code. 2. You approve **Connect agent** in your browser. 3. The agent calls it again, and every Runtime tool appears. The response carries the server's full instructions (limits, cleanup, safe retries). Before it connected, the agent had read only the short version. A client that does not refresh its tools when told shows them after the server or the client restarts. The connection is saved, so it connects immediately. A machine already connected by the CLI (`npx withruntime login`) skips this step. Approve only a connection you started and whose code matches. It can manage resources and spend prepaid credit across your account until you revoke it with `npx withruntime logout` or on the API keys page. The command is a bridge. It forwards MCP messages as they are to the remote server over the saved connection, so no key sits in the agent's configuration. It needs Node 22.12 or later. It loads its one dependency, `undici`, only when a proxy applies. It does not create an account. For CI, `RUNTIME_API_KEY` from a secret manager overrides the saved connection. ## Remote connection Clients that speak MCP over HTTP can skip the bridge. The endpoint is `https://api.withruntime.com/mcp`, over MCP Streamable HTTP. **Sign in through the browser, with no key.** Add the address as a custom connector or remote server, in Claude, ChatGPT, Cursor, VS Code or any client that supports MCP sign-in: 1. The client opens a Runtime page in your browser. 2. You sign in and approve **Connect** for that app. The page shows where the key goes, so check it is the app you are using. 3. The client receives a key of its own and every Runtime tool appears. The key belongs to a new agent named after the app. It can manage resources and spend prepaid credit across your account until you revoke it on the [API keys page](https://withruntime.com/account/keys), where it is listed with the app's name. A client that asks for scope `runtime:read` gets a read-only key. Claude Code can do the same without the bridge: ```bash no-run claude mcp add --transport http --scope user runtime https://api.withruntime.com/mcp ``` Then run `/mcp` in Claude Code and choose to authenticate. **Or send a key.** A server or CI job sends `Authorization: Bearer ` with a key from https://withruntime.com/account/keys, supplied from a secret manager. Never put a key in the URL, a command line, a browser bundle or a configuration you commit. Clients discover sign-in the standard way: a request with no key gets a `401` whose `WWW-Authenticate` header points at `https://api.withruntime.com/.well-known/oauth-protected-resource/mcp`, which names `https://withruntime.com` as the authorization server. It supports OAuth 2.1 with PKCE, dynamic client registration and client metadata documents. For ChatGPT, use `https://api.withruntime.com/mcp?profile=chatgpt`. Its tools keep persistent credentials out of the conversation. Starting or reading a sandbox MCP server returns safe state and scoped preview links. When another client needs the server's gateway token or authorization headers, get them through the website or a local CLI. This profile also leaves out what a ChatGPT request does not need. The audit log, referrals, single sign-on settings and the price comparison are not listed. `runtime_account` returns usage and limits without names, internal identifiers or card details. The ordinary MCP connection keeps its usual credential behavior. **Only the docs?** `https://withruntime.com/mcp` is a separate, public MCP server with no sign-in: it searches and reads these guides (`search_runtime_docs`, `read_runtime_doc`, `list_runtime_docs`) and runs nothing. ## Tools The server returns instructions in its `initialize` response: the quick start, safe retries, and how to report problems. Read them, then inspect tool results rather than assuming a completed tool call means the workload succeeded. The tools describe the interface, but a listed tool is not a promise that its capability is enabled. Check the [products page](./products) for availability. | Tool | What it does | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `runtime_sandboxes_create` | Create a sandbox and wait for readiness; inspect its returned state. `env` sets variables for every command, terminal and SSH session in it | | `runtime_sandboxes_list` | List by state, name or label, or read one by id | | `runtime_sandboxes_manage` | Stop, which keeps its disk, pause, wake, extend; retention, persist, restart a stopped one; update (name, labels, `env`); delete, which stops it, deletes its disk and memory and removes it for good; `switch-image`, which moves it to another image keeping `/workspace` | | `runtime_sandboxes_inspect` | A sandbox's storage, paused storage, lifetime or recovery point | | `runtime_sandboxes_exec` | Run a command and get its exit code and output, or start it in the background | | `runtime_sandboxes_process` | Read, feed, signal or list background processes | | `runtime_sandboxes_files_read`, `runtime_sandboxes_files_write` | Read (whole or by line range) and write files | | `runtime_sandboxes_files_list`, `runtime_sandboxes_files_manage` | List and glob; stat, make, move and remove | | `runtime_sandboxes_files_link` | A link to one file anyone can open with no key, to hand a person in chat: download it (a folder as `.tar.gz`), or upload to it; 1 hour by default, at most 7 days | | `runtime_sandboxes_interpreter_run`, `runtime_sandboxes_interpreter_contexts` | A notebook-style session in Python, JavaScript, TypeScript, R, Java, Bash or Go; charts as images, data frames as tables | | `runtime_sandboxes_files_watch` | Watch a directory for file changes: start, read events after a cursor, list, stop | | `runtime_images_build`, `runtime_images_registries` | Custom images from a recipe, any public or private image, or a Dockerfile, with versions and tags; registry credentials | | `runtime_images` | `list`, `get`, `tag` and `delete` image versions | | `runtime_volumes` | Persistent disks: `create` (with `fromBackup` to restore a backup), `list`, `get`, `delete`; `attach` and `detach` require shared-volume availability, and `resize` requires volume growth to be enabled | | `runtime_volumes_backup` | Back a volume up off its server: `create`, `list`, `get`, `policy` for daily backups, `delete` | | `runtime_sandboxes_fork` | Copies of a sandbox as it is now, with its memory and processes; on its server, or another when it is full | | `runtime_snapshots` | `create` keeps a running or paused sandbox (a running one is paused for the moment it takes and woken again), copied off its server (not with volumes), with `mode: "memory"` or `"disk"`; `list`, `get`, `update` (name, labels), `delete` | | `runtime_sandboxes_mounts` | Your S3, R2 or Google Cloud Storage bucket as a directory: `mount`, `list`, `unmount`; the proxy signs, the sandbox never holds the key | | `runtime_sandboxes_previews` | Share a port at `runtimehost.com`, private by default: `create`, `list`, `rotate`, `delete`; browser access to one sandbox: `session_create`, `session_list`, `session_revoke` | | `runtime_sandboxes_tailscale` | Join a paid sandbox to your tailnet: `up`, `status`, `down` | | `runtime_sandboxes_network` | `get` or `set` a sandbox's network rules | | `runtime_sandboxes_desktop_act`, `runtime_sandboxes_desktop_screenshot` | Drive a desktop in the sandbox | | `runtime_sandboxes_desktop_record` | Record the desktop to MP4: start, stop, list, delete | | `runtime_sandboxes_mcp` | Browse the MCP catalog with `action: "catalog"`, no sandbox id needed; `start`, `get`, `stop` run its servers in a sandbox at URLs your agent connects to | | `runtime_sandboxes_metrics`, `runtime_events_list` | A sandbox's CPU and memory over time; lifecycle events | | `runtime_webhooks_manage`, `runtime_otel_manage` | Webhooks for lifecycle events, and OpenTelemetry export | | `runtime_domains`, `runtime_ports`, `runtime_ips`, `runtime_networks_wireguard`, `runtime_networks_upstream_proxy`, `runtime_networks_private`, `runtime_networks_signed_requests` | Custom domains, public TCP ports, dedicated outbound addresses, the WireGuard tunnel, your own upstream proxy, reaching your sandboxes by name and signing requests as Runtime's; see below | | `runtime_account` | `get` the account, its free usage and credit; `limits` for this key's access and daily spending limit; `referrals` for your link and its credit (you both get up to $1,000); `sso` for single sign-on and SCIM; `compare` for what your sandboxes would cost at a rival, and what you save a month; `emails` for which optional emails your person gets | | `runtime_reservations` | [Book room](./reservations): `create` holds room for many sandboxes over a window, or standing room for a pool until cancelled, confirmed or declined immediately; `update` changes standing room; `list`, `get`, `cancel` | | `runtime_switching_record` | Record the provider you are leaving, before you first add credit; credit added within 30 days of signing up is matched, up to $1,000 in total | | `runtime_audit_list` | The account's audit log: members, keys, credit and security changes, with who and from where | | `runtime_secrets` | Secrets sandboxes use without seeing, a placeholder inside and the value added by the proxy, or given to the machine as its real value (`exposed`): `set`, `list`, `get`, `delete`; and `jobs_put`, `jobs_list`, `jobs_get`, `jobs_rotate`, `jobs_reveal`, `jobs_delete` for the copy a scheduled job puts in its environment | | `runtime_jobs` | [Scheduled jobs](./jobs): a command in a fresh sandbox, once or on a cron schedule: `create`, `list`, `get`, `runs`, `run`, `logs`, `pause`, `resume`, `trigger`, `reschedule`, `update`, `cancel` | | `runtime_feedback` | `submit` a problem or a missing feature; `list` what happened to it | | `runtime_support` | Ask Runtime support: `message`, then `read` the reply | | `runtime_notices` | Account notices: pause expiry, unpaid storage and deletion deadlines | | `runtime_docs_read` | Read any page of these docs | Tool names read `runtime__`, or `runtime_` for a tool that takes an `action`, the product spelled as the CLI spells it. The verbs an agent needs in its first session each have a tool of their own; a product's rarer verbs share one, and its `action` names the verb: `runtime_volumes` with `"action": "get"` reads a volume. Everything that acts on one sandbox is `runtime_sandboxes_*` and takes the sandbox as `id` (the MCP catalog needs none); `runtime_sandboxes_mcp` with `action: "catalog"` needs no `id`, while `start`, `get` and `stop` require it and name the missing field in an `invalid_request` error; images, volumes and snapshots are `runtime_images*`, `runtime_volumes*` and `runtime_snapshots`; what spans products, such as the account, usage, secrets, events, feedback and docs, names no product. Results come back as both text and `structuredContent`. An error is a tool result with `isError`, a code, a hint and a `requestId`. ## Renamed tools On 26 September 2026, 52 tools became 16 that take an `action`, which cut the tool list's context cost for an agent by nearly a quarter. The old names now fail with `not_found`, before any operation runs, and the hint names the grouped tool and its `action`. Change any permission rule, prompt or script that names one, then refresh the tool list. `runtime_sandboxes_mounts` and `runtime_volumes_backup` keep their grouped names and require an `action`; an old call that omits it is refused. | Before | Now | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | | `runtime_domains_add`, `_verify`, `_list`, `_remove` | `runtime_domains` with `add`, `verify`, `list`, `remove` | | `runtime_ports_open`, `_list`, `_close` | `runtime_ports` with `open`, `list`, `close` | | `runtime_ips_list`, `_reserve`, `_release` | `runtime_ips` with `list`, `reserve`, `release` | | `runtime_networks_wireguard_create`, `_get`, `_add_peer`, `_rotate_peer`, `_remove_peer` | `runtime_networks_wireguard` with the same verbs | | `runtime_networks_upstream_proxy_get`, `_set`, `_remove` | `runtime_networks_upstream_proxy` with `get`, `set`, `remove` | | `runtime_networks_private_get`, `_set` | `runtime_networks_private` with `get`, `set` | | `runtime_networks_signed_requests_get`, `_set` | `runtime_networks_signed_requests` with `get`, `set` | | `runtime_sandboxes_network_get`, `_set` | `runtime_sandboxes_network` with `get`, `set` | | `runtime_sandboxes_previews_create`, `_list`, `_rotate`, `_delete` | `runtime_sandboxes_previews` with the same verbs | | `runtime_sandboxes_mount`, `runtime_sandboxes_mounts`, `runtime_sandboxes_unmount` | `runtime_sandboxes_mounts` with `mount`, `list`, `unmount` | | `runtime_images_get`, `_tag`, `_delete` | `runtime_images` with `get`, `tag`, `delete` | | `runtime_volumes_create`, `_get`, `_delete` | `runtime_volumes` with `create`, `get`, `delete` | | `runtime_volumes_backup`, `_backup_get`, `_backup_policy`, `_backup_delete` | `runtime_volumes_backup` with `create`, `get`, `policy`, `delete` | | `runtime_snapshots_create`, `_get`, `_delete` | `runtime_snapshots` with `create`, `get`, `delete` | | `runtime_secrets_set`, `_list`, `_delete` | `runtime_secrets` with `set`, `list`, `delete` | | `runtime_account_get`, `runtime_limits_get`, `runtime_referrals_get`, `runtime_account_sso_get` | `runtime_account` with `get`, `limits`, `referrals`, `sso` | | `runtime_usage_compare` | `runtime_account` with `compare` | | `runtime_support_message`, `_read` | `runtime_support` with `message`, `read` | | `runtime_feedback_submit`, `_list` | `runtime_feedback` with `submit`, `list` | On 24 September 2026 every tool took its product's name, as the CLI spells it, with no aliases: `runtime_exec` became `runtime_sandboxes_exec`, `runtime_sandboxes_create` became `runtime_sandboxes_create`, and so on. A call to one of those names fails, and its error names the call that replaces it. ## A typical session 1. Choose a unique `idempotencyKey` before creating. Call `runtime_sandboxes_create` with that key. Check that the returned state is `running` before executing anything. The free usage is spent first, then prepaid credit. 2. `runtime_sandboxes_files_write`, then `runtime_sandboxes_exec` with `{"id": "", "command": "python3 main.py"}` (or `"command": ["python3", "main.py"]` to run it without a shell). Add `"user": "root"` to run it as root without `sudo` in front. Give each write that accepts `idempotencyKey` its own key; do not add unsupported fields to other tools. Check `exitCode`, `timedOut`, output and truncation flags; tool or HTTP success alone does not prove program success. `runtime_sandboxes_exec` returns `stdoutBytes` and `stderrBytes`, the full size of each stream; `truncated` is `true` when part of the output is not in the result. The result holds the first and last 64 KiB of each stream. Over MCP, output over 16,000 characters in all keeps each stream's beginning and end within its share of the output budget; even a long first line may be shortened. Quotes, backslashes and control characters can shorten it further, because escaped output must also fit the complete serialized response budget. `outputCut` says how many characters of each were cut. When the result includes `processId`, read the existing process with `runtime_sandboxes_process` and `"action": "read"`, using its output cursors. For a future command whose full output you need, save it to a file and read it in parts with `runtime_sandboxes_files_read`. Do not run a command again just to recover output: its changes may already have happened. 3. For a server or a long job, `runtime_sandboxes_exec` with `"background": true`, then `runtime_sandboxes_process` with `"action": "read"` to follow its output. 4. `runtime_sandboxes_manage` with `"action": "delete"` when done, even if a step failed. A stop keeps the disk, billed until it is deleted; delete unless the owner's task needs the sandbox again. Confirm it is gone before reporting cleanup complete. Export needed outputs before deleting. **Retries.** When a tool accepts `idempotencyKey`, choose and record a unique key **before the first call** and pass it explicitly. After a lost reply, reuse that key with identical input. A key the server generated for an omitted field cannot be recovered from a lost reply, so do not repeat that write blindly: read the original resource first. The SDKs keep their own retry key during a call; this guidance is for direct MCP calls. **Errors.** Follow error codes and hints. - Back off with a bounded deadline on `no_capacity`, `busy` or `host_unavailable`, keeping the original write key and input. - Do not keep retrying `fork_unavailable`, `previews_unavailable` or `unavailable`: an operator has switched that capability off. - If a create stops before becoming ready, read that sandbox's `stopReason` and report the failure. Do not call it running or loop over new creates. - For support or feedback, send a sanitized summary and request ID, never credentials or private code and file contents. ## Pause and wake `runtime_sandboxes_manage` with `"action": "pause"` saves files and memory, and `"wake"` restores them. Each sandbox keeps only its latest state, not a history of billed snapshots. A wake never silently substitutes a fresh boot: missing memory images refuse it. A full host can also refuse a wake; the paused data remains and no compute is charged for the failed attempt. See [pricing](./pricing) for paused storage and retention. A paused sandbox also wakes by itself when `runtime_sandboxes_exec`, a file or terminal tool, or a visit to a shared port reaches it, unless it was created with `autoWake: false`. A sandbox pauses itself after 300 seconds with nothing happening in it. A process due on a timer also wakes a sandbox that paused for being idle, unless it has `wakeOnTimers: false`. `"action": "update"` changes `autoWake`, `wakeOnTimers`, `idlePauseSeconds` (60 to 86,400 seconds; 0 is never), `name` and `labels`; `"persist"` keeps a paid sandbox running while credit lasts. `runtime_sandboxes_create` with `name` and `getOrCreate: true` returns the sandbox that already has the name, woken if paused, instead of `name_taken`. ## Domains, TCP ports, addresses and the tunnel They need a kept top-up, and a dedicated address credit; see [networking](./networking). - `runtime_domains` (`add`, `verify`, `list`, `remove`): serve a sandbox's port at your own hostname. - `runtime_ports` (`open`, `list`, `close`): a public TCP port to a sandbox. - `runtime_ips` (`reserve`, `list`, `release`): a dedicated outbound address. - `runtime_networks_wireguard` (`create`, `get`, `add_peer`, `rotate_peer`, `remove_peer`): the WireGuard tunnel. `add_peer` without `publicKey` generates the key pair and returns the private key once, in `config`. - `runtime_networks_upstream_proxy` (`get`, `set`, `remove`): send the sandboxes' outbound connections through your own proxy. - `runtime_networks_private` (`get`, `set`): with `enabled: true`, your sandboxes reach each other at `.sandbox.internal:` over TCP. Needs a kept top-up; free. - `runtime_networks_signed_requests` (`get`, `set`): with `enabled: true`, your sandboxes can sign their HTTP requests as Runtime's agents with Web Bot Auth ([how](./networking#signed-requests)). Needs credit; free.