MCP servers are powerful - they give Claude Desktop or other AI assistants access to your filesystem, databases, APIs, and more. But that power comes with risk. Every MCP server runs with your full user permissions. A bug or malicious MCP package could read your SSH keys, AWS credentials, or browser cookies.
When you add an MCP server to Claude Desktop, you're running arbitrary code on your machine. That filesystem server? It can see everything your user can see. That database tool? It has access to your entire home directory. Most of us just... trust it. We copy the config from the README and hope for the best, because we want immediate results.
The Traditional Container Approach
Some security-conscious users already run MCP servers in containers using Docker, or other container runtimes. Here's what that looks like:
{ "mcpServers": { "sqlite": { "command": "docker", "args": [ "run", "-i", "--rm", "-v", "/home/michael/data:/data", "-v", "/home/michael/.cache/uv:/home/mcp/.cache/uv", "-e", "HOME=/home/mcp", "--user", "1000:1000", "ghcr.io/serverlessdna/mcp-python:latest", "uvx", "mcp-server-sqlite", "--db-path", "/data/mydb.sqlite" ] } } }
That's 12 lines of Docker arguments you need to get right and it looks nothing like the example configuration the MCP server provider gives you. Volume mounts, user permissions, environment variables, image tags. Miss one flag and it fails silently or breaks in subtle ways.
Most people look at that and think "I'll just run it natively".
What if you could run MCP servers in complete isolation, with access only to what you explicitly allow - and configure them exactly as their READMEs document?
Most MCP server documentation shows something like this:
{ "mcpServers": { "sqlite": { "command": "uvx", "args": ["mcp-server-sqlite", "--db-path", "~/data/mydb.sqlite"] } } }
With run-mcp, your config is almost the same:
{ "mcpServers": { "sqlite": { "command": "run-mcp", "args": ["uvx", "mcp-server-sqlite", "--db-path", "/data/mydb.sqlite"], "env": { "MCP_MOUNT": "~/data:/data" } } } }
One word changes. Replace uvx or npx with run-mcp, add the original command as the first argument, and declare what the server can access. That's it.
Three approaches, compared:
| Approach | Lines of Config | Container Isolation | Complexity |
|---|---|---|---|
| Native (uvx/npx) | 4 | ❌ None | Low |
| Raw Docker | 12+ | ✅ Full | High |
| run-mcp | 5 | ✅ Full | Low |
The server runs in a container with zero access to your host - unless you explicitly grant it through a registered mount using the MCP_MOUNT environment variable as shown in the example.
What Changes
| Without run-mcp | With run-mcp |
|---|---|
| Server sees entire home directory | Server sees only what you mount |
Server can read ~/.aws, ~/.ssh | No access unless you add it |
| Malicious package = full compromise | Malicious package = contained |
| Servers share your environment | Each server gets isolated storage |
The security model flips from "access everything by default" to "access nothing by default."
How It Works
- Replace the command -
uvxbecomesrun-mcp uvx,npxbecomesrun-mcp npx - Mount what you need -
MCP_MOUNT=~/data:/datagrants explicit access. - Credentials are opt-in - Add
~/.aws:/home/mcp/.aws:roonly when the server needs AWS access and provides read-only access.
No Docker knowledge required. No Dockerfile. No docker-compose. Just a single binary that handles everything across all platforms (Windows, macOS, Linux).
Real Examples
Filesystem Server (Read-Only Access)
{ "mcpServers": { "filesystem": { "command": "run-mcp", "args": ["npx", "@modelcontextprotocol/server-filesystem", "/docs"], "env": { "MCP_MOUNT": "~/Documents:/docs:ro" } } } }
The server can only read your Documents folder. Nothing else.
AWS Server (With Credentials)
{ "mcpServers": { "aws-api": { "command": "run-mcp", "args": ["uvx", "awslabs.aws-api-mcp-server"], "env": { "MCP_MOUNT": "~/.aws:/home/mcp/.aws:ro", "AWS_REGION": "us-east-1" } } } }
The server gets read-only access to your AWS credentials. Nothing else on your system is visible.
Memory Server (No Host Access)
{ "mcpServers": { "memory": { "command": "run-mcp", "args": ["npx", "@modelcontextprotocol/server-memory"] } } }
No MCP_MOUNT means no host filesystem access at all. The server gets an isolated home directory that persists between runs - but it's completely sandboxed using standard volume features of container runtimes.
No Runtime Dependencies
Don't have Node.js 22 installed? Python 3.12? Doesn't matter.
run-mcp auto-detects your container runtime - Docker, Podman - and runs the appropriate container. Your machine stays clean. No version conflicts. No global package pollution.
Getting Started
Install the binary:
# Linux (amd64) curl -fsSL https://github.com/serverless-dna/run-mcp/releases/latest/download/run-mcp-linux-amd64 \ -o ~/.local/bin/run-mcp && chmod +x ~/.local/bin/run-mcp # macOS (Apple Silicon) curl -fsSL https://github.com/serverless-dna/run-mcp/releases/latest/download/run-mcp-darwin-arm64 \ -o ~/.local/bin/run-mcp && chmod +x ~/.local/bin/run-mcp # macOS (Intel) curl -fsSL https://github.com/serverless-dna/run-mcp/releases/latest/download/run-mcp-darwin-amd64 \ -o ~/.local/bin/run-mcp && chmod +x ~/.local/bin/run-mcp
# Windows (PowerShell) New-Item -ItemType Directory -Force -Path ~\.local\bin | Out-Null Invoke-WebRequest -Uri https://github.com/serverless-dna/run-mcp/releases/latest/download/run-mcp-windows-amd64.exe -OutFile ~\.local\bin\run-mcp.exe
Note: Ensure ~/.local/bin is in your PATH, or use the full path to run-mcp in your Claude Desktop config.
Update your Claude Desktop config and you are done.
The Security Boundary That Should Have Been There
Every MCP server you run is code executing on your machine with your permissions. The MCP protocol is powerful, but it shipped without a security model for the host system.
run-mcp adds that missing layer. Same simple configs. Same MCP servers. Now with isolation by default.
Links:
Questions or feedback? Open an issue or find me on LinkedIn.

