workbench-sandbox
Provides tools for managing Kubernetes resources to create isolated sandbox runtimes: creates pods, services, and ingresses; runs commands and background processes; writes and reads files in a per-user durable home; exposes ports as authenticated apps; and cleans up expired runtimes via a TTL reaper.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@workbench-sandboxcreate a sandbox, run my app on port 3000, and expose it"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
workbench-sandbox
Gives agent-built apps an address, an identity and a durable home.
An MCP server for Kubernetes. An agent calls a handful of tools and gets an isolated runtime it can write files in, run commands in, start a process in, and publish an app from at its own authenticated URL. The user's files live in a durable home that outlives any runtime.
It is the runtime half of workbench, a spike about letting an agent build the frame and then
step aside while people fill it in.
%%{init: {"theme":"base","themeVariables":{"fontFamily":"Poppins, ui-sans-serif, system-ui, sans-serif","fontSize":"15px","primaryColor":"#ecebf7","primaryBorderColor":"#3d3f73","primaryTextColor":"#2b2c52","lineColor":"#3d3f73","secondaryColor":"#fdeee6","tertiaryColor":"#f7f6fb","clusterBkg":"#faf9fc","clusterBorder":"#cfcbe0","actorBkg":"#ecebf7","actorBorder":"#3d3f73","actorTextColor":"#2b2c52","actorLineColor":"#9a98b8","signalColor":"#3d3f73","signalTextColor":"#2b2c52","noteBkgColor":"#fdeee6","noteBorderColor":"#e0693a","noteTextColor":"#2b2c52"}}}%%
flowchart LR
agent(["Agent"]) -- "MCP" --> srv["workbench-sandbox<br/>MCP server"]
srv -- "creates" --> proc
subgraph rt["Isolated runtime · one pod per session"]
proc["Your processes"]
gw["App gateway · Caddy<br/>app.sandbox.domain<br/>token per request"]
home["/home/sandbox"]
proc --- gw
end
home <-- "sync" --> vol[("Durable home<br/>PVC or S3 prefix, per user")]
srv -. "TTL reaper removes expired runtimes<br/>homes are kept" .-> rt
classDef ctl fill:#ecebf7,stroke:#3d3f73,stroke-width:2px,color:#2b2c52;
classDef data fill:#fdeee6,stroke:#e0693a,stroke-width:2px,color:#2b2c52;
class agent,srv ctl;
class proc,gw,home,vol data;What it does
Isolation | each session gets its own pod; with gVisor ( |
Addressable apps |
|
Auth per request |
|
Durable home | a per-user volume mounted as the home directory: a PersistentVolumeClaim, or an S3 bucket prefix synced by rclone with short-lived credentials scoped to that user's prefix |
Cleanup | a background reaper deletes expired runtimes and sweeps orphaned services, ingresses and secrets |
Related MCP server: paddock
Quick start (laptop)
Prerequisites: Docker, minikube, kubectl, make. About 6 GB of RAM for the cluster.
./scripts/local-up.sh # minikube (containerd) + ingress + gVisor + both images + deploy
minikube tunnel # separate terminal; binds port 80 so *.sandbox.localhost reaches the cluster
curl -i http://mcp.sandbox.localhost/healthz # HTTP 200Prefer to see each step? The script is just this:
minikube start --driver=docker --container-runtime=containerd --cpus=4 --memory=6144
minikube addons enable ingress
minikube addons enable gvisor # optional isolation layer
make build build-sandbox # docker build + load into minikube
make deploy-local # namespace, RBAC, server, ingressNo gVisor? Run ./scripts/local-up.sh --no-gvisor, or set RUNTIME_CLASS= (empty) on the deployment to use the
cluster default runtime.
The full-stack guide, including the agent and the UI, is in the workbench repository:
docs/getting-started.md.
Talking to it
The server speaks MCP over Streamable HTTP at /mcp. Identity is a header on the connection, not an argument,
so a model can never pick whose home it is touching:
Header | Meaning |
| the tenant. Its home volume ( |
| optional, recorded on the runtime |
Tool reference
Tool | Parameters | What it does |
|
| Starts a runtime with the user's home mounted. Returns |
|
| Runs a bash command; returns stdout, stderr and the return code |
|
| Starts a long-running process detached from the exec session; returns its pid |
|
| Publishes a port at |
|
| List or remove published apps |
|
| Text or base64, size-capped (5 MiB by default), confined to the home directory |
|
| List or delete |
|
| The token and apps, for trusted gateways only (not for models) |
|
| Pod phase and metadata, with the token redacted |
|
| Deletes the pod, service and ingress. The user's home is kept |
Configuration
Environment variables (a .env is read too).
Variable | Default | Meaning |
|
| where runtimes and the server live |
|
| apps are served at |
|
| pod runtime class; empty means the cluster default |
|
| image every runtime starts from |
|
|
|
|
| for the PVC backend |
|
| runtime lifetime |
|
| per-runtime caps |
|
|
|
|
| how often expired runtimes are swept |
| S3 backend: where the bucket is | |
| admin credentials, used only by this server | |
|
| how often a runtime syncs its home |
Home storage
Backend | What it is |
| one PersistentVolumeClaim per user, mounted directly |
| a bucket prefix per user, kept in sync with the runtime's home by an rclone sidecar |
With s3, a runtime never receives the admin credentials. For each runtime the server mints short-lived
(STS) credentials whose policy is limited to users/<user_id>/*, so a runtime cannot read another user's
prefix. Two runtimes for the same user sync into the same prefix: newer files win and nothing is deleted when the
sync has to fall back to a merge. An S3 example is in deploy/k8s/examples/ (RustFS or MinIO work).
Repository layout
src/sandbox_mcp/
server.py, app.py FastMCP server, lifespan, reaper startup
config.py settings
tools/ the MCP tools
k8s/ pods, services, ingresses, exec, annotations
caddy/ renders the per-runtime gateway config
routing.py route table (kept in a pod annotation) and hot reload
storage/ pvc and s3 adapters (scoped credentials, sync sidecar)
reaper.py TTL cleanup
docker/ Dockerfile.mcp (server), Dockerfile.sandbox-base (the runtime image)
deploy/k8s/ namespace, RBAC, deployment, ingress; examples/ for S3
scripts/local-up.sh laptop bootstrap
tests/ unit tests (no cluster)Tests
uv sync --extra dev
uv run pytest -q # unit tests, no cluster neededSecurity notes
The runtime image installs packages from the internet on demand and runtimes have open egress by default. Add a
NetworkPolicyfor anything beyond a laptop.The sandbox token is returned by
create_sandbox. Gateways should keep it server-side and strip it from anything a model reads.This is a spike. Read the code and the RBAC before pointing it at a real cluster.
License
Apache-2.0. See LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Persistent cloud workspaces for AI agents: run commands, edit files, use git and a browser.
Give your agent a persistent workspace: files, a code sandbox and a public URL to publish to.
Persistent Linux computers for AI agents: desktop, signed-in browser, vault, apps and shell.
A private persistent computer: files and a bash shell that survive between runs.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to operate a persistent Linux sandbox in the cloud, running commands, managing files, using Git, and publishing artifacts through a Streamable HTTP MCP endpoint.-
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to work in a persistent, isolated Linux workspace with file management, Bash execution, SSH/SFTP access, and durable storage while keeping workloads contained from the host and private networks.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to safely run bounded, sandboxed tasks on remote machines with persistent state and reviewable artifacts.Apache 2.0
- FlicenseNot gradedqualityBmaintenanceEnables AI coding agents to run shell commands, spawn persistent background tasks, and read/write files inside isolated remote container sandboxes on a VPS. It also provides project workspace listing, task attach/kill controls, and a searchable knowledge graph for memory continuity across sessions.-