Your AI agent's tools run with your permissions. When an MCP server can call
run_commandor write files, a buggy prompt or a malicious instruction can reach your home directory, your SSH keys, and your cloud credentials.mcp-boxputs every MCP server inside a locked-down, read-only, network-isolated Docker sandbox — so the worst a tool can do is scribble inside a folder you chose.
mcp-box is a single, portable Go binary that launches turnkey, immutable, strictly-isolated
container sandboxes for Model Context Protocol (MCP) servers. Nix is used for deterministic image
builds when present, but it is entirely optional — without it, mcp-box pulls identical prebuilt
images straight from GHCR. Docker is the only hard requirement.
# 1. Get the binary (Docker is the only dependency)
curl -sSL https://github.com/lowcache/mcp-box/releases/latest/download/mcp-box-linux-amd64 -o mcp-box
chmod +x mcp-box && mv mcp-box ~/.local/bin/
# 2. Prove the sandbox holds — this write MUST fail
mcp-box run shell --workspace /tmp/demo -- bash -c 'touch /etc/naughty'
# => touch: cannot touch '/etc/naughty': Read-only file system
# 3. Wire it into your AI client (paste the output into claude_desktop_config.json)
mcp-box config sqliteDepending on your installation path, mcp-box has distinct dependency requirements:
- Runtime Boundary (All Users):
- Docker Engine (Must be active and running locally on the host system).
- Local Image Building (Source Flow with Nix):
- Nix (with experimental
flakesandnix-commandenabled).
- Nix (with experimental
- CLI Compilation (Source Flow with Go):
- Go compiler v1.22 or higher (only required if building the executable from source without using Nix).
- Zero-Dependency Fallback Flow:
- None. The pre-compiled CLI binary runs standalone and automatically pulls the pre-built, multi-arch OCI images straight from GHCR into your local Docker daemon.
- Strict Sandboxing:
- Immutable Root (
--read-only): The entire root filesystem is mounted read-only. - Transient State (
--tmpfs): Writable spaces (/tmpand/run) exist solely in RAM and disappear once the container stops. - Zero Capabilities (
--cap-drop=ALL): The running processes have no special Linux kernel capabilities. - No Privilege Escalation (
no-new-privileges:true): Prevents elevation to root inside the sandbox. - Strict Network Policies (
--network none): Servers likesqlite,shell, andfilesystemhave absolutely zero internet access by default. - Scoped Workspaces: Only specifically mounted host directories (
--workspace) are visible to the server at/workspace.
- Immutable Root (
- Correct File Ownership:
- Containers run mapped to your host UID/GID (
-u $(id -u):$(id -g)), ensuring that files written to mounted workspaces are owned by you (notroot) and don't trigger host-side permission errors.
- Containers run mapped to your host UID/GID (
- Painless Integration:
- Built-in configuration generator (
mcp-box config <server>) prints out paste-ready JSON snippets to plug directly intoclaude_desktop_config.jsonor OpenClaw configurations.
- Built-in configuration generator (
- Zero-Dependency Nix Autonomy:
- If Nix is installed, running a sandbox automatically triggers a local rebuild and load of the OCI image.
- If Nix is absent,
mcp-boxautomatically detects this and falls back to pulling pre-built, identical, and secure OCI images directly from the GitHub Container Registry (ghcr.io/lowcache), making Nix entirely optional for the end-user.
graph TD
subgraph Host [Host Environment]
Agent[AI Agent / Claude Desktop] <-->|stdio piping| CLI[mcp-box CLI]
CLI -->|Checks for Nix| NixDetect{Nix Installed?}
NixDetect -->|Yes: Source Flow| NixBuild[nix build .#server]
NixBuild -->|Stream tarball| DockerLoad[docker load]
NixDetect -->|No: Registry Flow| DockerPull[docker pull ghcr.io]
DockerPull -->|Tag locally| DockerLoad
DockerLoad -->|Loads image| Docker[Docker Engine]
end
subgraph Sandbox [Docker Sandbox]
Server[MCP Server]
Tools[Isolated Tools: git, rg, sqlite3, curl]
Workspace[Mounted Workspace: /workspace]
end
Docker -->|spawns with strict isolation| Sandbox
CLI <-->|stdio piping| Server
| Server Name | Language | Included Utilities | Network Mode | Primary Purpose |
|---|---|---|---|---|
sqlite |
Python | sqlite3 CLI, fastmcp SDK |
none |
High-performance, isolated database querying. |
shell |
Python | bash, ripgrep, fd, git, curl, jq, sqlite, tar |
none |
Safe, sandboxed script running and file operations. |
filesystem |
Node.js | ripgrep, fd, git |
none |
Scoped filesystem read/write and code searching. |
fetch |
Node.js | curl |
bridge |
Safe, isolated web fetching and scraping. |
Depending on your host environment, you can install and run mcp-box with three different avenues:
For systems that only have Docker installed:
- Download the compiled CLI binary (pick the asset matching your OS/arch —
linux/darwin,amd64/arm64):curl -sSL https://github.com/lowcache/mcp-box/releases/latest/download/mcp-box-linux-amd64 -o mcp-box chmod +x mcp-box
- Move to PATH (Optional):
mv mcp-box ~/.local/bin/ # Or another folder in your PATH
On first execution, mcp-box will automatically detect the absence of Nix and pull the pre-built OCI images from ghcr.io/lowcache into your local Docker daemon.
For systems running Nix/NixOS:
- Run directly without installing:
nix run github:lowcache/mcp-box -- list
- Install to your user profile:
nix profile install github:lowcache/mcp-box
- Declarative Installation (NixOS / Home Manager):
Add the flake input and package to your configuration:
# flake.nix inputs: inputs.mcp-box.url = "github:lowcache/mcp-box"; # In systemPackages or home.packages: inputs.mcp-box.packages.${pkgs.system}.default
On first execution, mcp-box will build the Go binary and OCI images purely from source and load them directly into your local Docker daemon.
If you want to compile the CLI binary manually without Nix:
- Clone the repository:
git clone https://github.com/lowcache/mcp-box.git cd mcp-box - Compile the binary (the Go module lives in
src/go):cd src/go go build -o ../../mcp-box .
You can now run ./mcp-box directly, which will pull OCI layers from the registry or build locally using Nix based on your host environment.
./mcp-box help
./mcp-box listYou can launch any server interactively to test its behavior and tools:
./mcp-box run sqlite --workspace /tmp/sandbox-db -- --db /workspace/test.dbIf you want to manually rebuild or force-update a Nix-built image:
./mcp-box build sqlitemcp-box config <server> prints a ready-to-paste mcpServers JSON block (with an
absolute path to the binary). The same block works for both Claude Desktop and
Claude Code.
./mcp-box config sqliteClaude Code does not use claude_desktop_config.json. Add the server with one
command — note the nested -- (the first separates claude's flags from the
subprocess; the second is consumed by mcp-box to forward server args):
# user scope (available in every project); drop -s user for the current project only
claude mcp add -s user mcp-box-sqlite -- \
mcp-box run sqlite --workspace /abs/path/to/workspace -- --db /workspace/db.sqliteOr, to commit a shareable config to your repo, drop the mcp-box config JSON block
straight into a project-root .mcp.json — it uses the exact {"mcpServers": …}
shape that config emits.
Verify with claude mcp list.
Paste the config block into claude_desktop_config.json. Its location is
OS-specific:
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
You can audit the sandbox boundary directly by overriding the container command
with -- bash -c '...'. The hardening (read-only root, no network, dropped
capabilities, host UID mapping) applies to any process in the box, so these
checks prove the boundary that wraps the MCP server:
- Read-only filesystem — writes outside
/workspaceare rejected:./mcp-box run shell -- bash -c 'touch /etc/naughty' # => touch: cannot touch '/etc/naughty': Read-only file system (exit 1)
- Network isolation — with the default
--network none, DNS/egress fail:./mcp-box run shell -- bash -c 'curl -I https://google.com' # => curl: (6) Could not resolve host: google.com (exit 6)
- No privilege escalation —
sudois not even present in the image:./mcp-box run shell -- bash -c 'sudo -l' # => bash: line 1: sudo: command not found (exit 127)
- Host UID/GID mapping — the process is you, not root:
./mcp-box run shell -- bash -c 'id' # => uid=<your uid> gid=<your gid> ... (files in /workspace are owned by you)
