Sandboxing MCP Servers: Containers, Least Privilege, and Process Isolation
A stdio MCP server runs as a child process of your MCP client, with the same filesystem and network access as the user account that runs it. For most well-audited servers that is fine. For anything that executes code, drives a browser, or wraps a high-stakes service, sandbox it. This guide covers the four sandboxing patterns that actually work and when to use each.
The threat model in one paragraph
An MCP server you install is code that runs on your machine, executed by your shell, with your file permissions and your network access. If the server is malicious, buggy, or compromised upstream, it can do anything you can do — read your SSH keys, exfiltrate your browser cookies, push a commit, send an email. Sandboxing is the difference between "the MCP can touch one directory and one HTTPS endpoint" and "the MCP can touch everything I can touch." For most installs, the difference is worth the setup time.
The four patterns, ranked by friction
Pattern 1 — Dedicated Unix user
Create a user account that owns nothing except the MCP's working directory. No shell, no SSH access, no membership in your default groups. Run the MCP as that user via `sudo -u mcpuser` in your client's command config or via a systemd unit with User=mcpuser. The MCP can read only what you explicitly grant.
When you want a 15-minute setup that already covers 80% of stdio MCPs.
Pattern 2 — Container with read-only root
A Docker or Podman container with the root filesystem mounted read-only, a tmpfs at /tmp, and only the directories the MCP needs bind-mounted. Add a network policy that allows egress to the upstream service and nothing else. Restart the container between sessions to clear state.
When you want filesystem and network isolation plus a clean teardown story.
Pattern 3 — Dedicated sandbox runtime (E2B, Firecracker)
A purpose-built sandbox like E2B runs each MCP session inside a microVM with no host filesystem access, fresh network namespace, and aggressive teardown. The model can write to its own scratch filesystem, exec code, and read its own outputs — but it cannot see anything outside the sandbox.
When the MCP runs arbitrary model-generated code (code interpreter, shell execution).
Pattern 4 — Remote MCP behind a thin proxy
Host the MCP server on a dedicated VM or container in a network you control. Put a thin auth proxy in front of it. Your client talks JSON-RPC over HTTPS to the proxy, which terminates auth and forwards. The MCP cannot touch your laptop's filesystem because it is not on your laptop.
When you operate the MCP for a team or want to share one install across multiple users.
A concrete example: sandboxing Puppeteer
The Puppeteer MCP spawns Chromium. Chromium has its own internal sandbox, but it still needs filesystem access for the browser profile, network access for the pages it loads, and ideally no access to your home directory. A reasonable wrapper:
# /etc/systemd/system/mcp-puppeteer.service [Service] Type=simple User=mcppuppeteer Group=mcppuppeteer ReadWritePaths=/var/lib/mcp-puppeteer ProtectHome=true PrivateTmp=true NoNewPrivileges=true RestrictAddressFamilies=AF_INET AF_INET6 SystemCallFilter=@system-service ~@privileged @resources ExecStart=/usr/local/bin/mcp-puppeteer # In your MCP client config, point at the service via a thin shim # that proxies stdio to the service's socket.
The systemd hardening flags (`ProtectHome`, `PrivateTmp`, `NoNewPrivileges`, `RestrictAddressFamilies`) close the most common holes: the MCP cannot read your home directory, gets a private /tmp, cannot escalate privileges, and is limited to TCP/IP. Add `SystemCallFilter` to block syscalls the MCP does not need and you have a tight box around a piece of code that drives a real browser.
What sandboxing does not solve
Sandboxing protects the host. It does not protect the upstream service the MCP talks to. If your sandboxed GitHub MCP has a personal access token with full-org scope, a compromise of the sandbox still has access to your org via the token. Sandboxing and credential scoping are complementary, not substitutes — and credential scoping is usually the higher-leverage move because tokens are reusable, while host access is one-shot.
Sandboxing also does not stop prompt injection. A perfectly sandboxed MCP that takes instructions from a malicious web page can still send those instructions to the model, which can still call other unsandboxed MCPs. Defense in depth: sandbox the things that need it, scope credentials narrowly, and require user confirmation on destructive tool calls.
Frequently asked questions
Why sandbox an MCP server?
A stdio MCP server runs as a subprocess of your MCP client, which means it has the same filesystem and network access as the user account that runs the client. If the server is compromised — or just buggy — the blast radius is your whole user account. Sandboxing reduces that blast radius to whatever the sandbox exposes, which can be just one directory and one network endpoint.
Do I need to sandbox every MCP?
No. The official Filesystem, Git, GitHub, and SQLite MCPs from Anthropic are well-audited and widely used; running them unsandboxed is reasonable for individual developers. Sandbox anything that executes code (E2B, Puppeteer, Playwright, custom shell MCPs), anything pulled from a less-trusted source, and anything that wraps a payments or PII service.
What is the cheapest viable sandbox setup?
A dedicated Unix user account that owns nothing except the MCP's working directory. The MCP runs under that user via `sudo -u mcpuser` or systemd User=. The user has no shell, no SSH keys, no access to your home directory. Setup time: 15 minutes. Blast radius: whatever you explicitly mounted.
When should I use containers (Docker, Podman) for MCPs?
When you want filesystem isolation plus network egress controls plus easy rebuilds. A container with a read-only root filesystem, an explicit /tmp mount, and a NetworkPolicy that allows only the upstream service is a strong default. The trade-off is start-up latency and a bit more config.
When should I use a dedicated sandbox runtime like E2B?
When the MCP runs arbitrary code generated by the model — code execution is the canonical example. E2B-style sandboxes give you full process isolation, no host filesystem access, and clean tear-down between sessions. The latency is higher (cold start a few seconds), but the security boundary is much stronger than a local container.
How do I sandbox browser-automation MCPs like Puppeteer or Playwright?
Run them in a container with no host filesystem mounts (the browser does not need them), a strict network egress policy (allow only the domains you intend to scrape), and headless mode. For Playwright specifically, prefer the official Microsoft container images — they ship with the correct browser binaries and known-good sandbox flags.
Can I sandbox remote MCPs the same way as local stdio MCPs?
Remote MCPs are already sandboxed in the sense that they run on a separate host — your client only talks JSON-RPC over HTTP. The interesting sandboxing for remote MCPs is on the server side: the server operator is responsible for isolating their own dependencies, scoping access tokens narrowly, and rate-limiting per-token.
Related: MCP Security overview · Prompt injection defenses
More guides
Fundamentals
What Is MCP? A Plain-English Guide to Model Context Protocol
6 min read
Setup Guide
Best MCPs for Cursor in 2026 (Ranked + Setup)
8 min read
Setup Guide
Best MCPs for Claude Desktop in 2026 (Ranked + Setup)
9 min read
Setup Guide
Best MCPs for Claude Code in 2026 (Ranked + Setup)
8 min read
Setup Guide
Best MCPs for Windsurf in 2026 (Cascade-Ready Setup)
8 min read
Setup Guide
Best MCPs for VS Code in 2026 (Agent Mode + .vscode/mcp.json)
8 min read
Strategy
MCP Registry vs Curated Directory: Which Should You Use?
5 min read
Setup Guide
Best MCPs for ChatGPT: The Apps and Connectors Worth Installing
9 min read
Tutorial
How to Add an MCP Server to ChatGPT (Developer Mode + Apps Directory)
7 min read
Security
MCP Security: What to Know Before You Install
9 min read
Role Guide
Best MCPs for Marketers in 2026 (SEO, Email, Analytics)
8 min read
Strategy
Remote vs Local MCP Servers: When to Use Each
7 min read
Fundamentals
MCP vs Function Calling: What’s the Difference?
6 min read
Comparison
MCP Directories Compared: Top MCPs vs mcp.so vs PulseMCP vs mcp.directory
8 min read
Security
MCP Prompt Injection: How Tool-Calling Agents Get Hijacked
8 min read
Security
OAuth 2.1 for MCP: What the Spec Standardised and What You Need to Know
8 min read
Security
Rotating MCP Credentials: A Practical Guide for Leaks, Expiry, and Routine Hygiene
7 min read
Security
Least-Privilege Scoping for MCPs: How to Grant the Smallest Useful Permission
7 min read
Setup Guide
Best MCP Servers for Databases in 2026 (Ranked + Setup)
10 min read
Setup Guide
Best MCP Servers for Research in 2026 (Search, Scrape, Synthesize)
9 min read
Setup Guide
Best MCP Servers for Design-to-Code in 2026 (Figma → React)
9 min read
Setup Guide
Best MCP Servers for Domains in 2026 (Registrars + DNS)
9 min read
Tutorial
How to Buy a Domain From Claude (Cloudflare MCP, Step by Step)
6 min read
Tutorial
How to Search for Domains With an AI Agent (Cross-Registrar Workflow)
7 min read