本地AI代理沙盒

一个在Mac上运行隔离Linux虚拟机的本地AI代理沙盒,提供VM级隔离和快速命令执行。

  • by bird
  • Python
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 bird/sandbox-mcp

使用说明

沙盒mcp

本地AI代理沙盒。在Mac上运行独立的Linux虚拟机大约需要60毫秒。没有云成本。通过Virtualization.framework实现VM级隔离。与支持本地stdio服务器(Claude Code、Claude Desktop、Cursor)的MCP客户端配合使用。

这是什么

MCP服务器为AI代理提供沙盒Linux环境,使用 苹果集装箱化 (虚拟化框架)。每个沙箱都是一个真正的虚拟机,而不是一个共享内核的容器,它在大约700毫秒内启动,并通过vsock上的持久shell在大约60毫秒内执行命令。

与云沙盒相比(截至2025年初):

执行延迟 成本 隔离
此(本地) ~60ms 本地硬件 VM(虚拟化框架)
E2B ~150ms+网络 0.18美元/小时 鞭炮微型VM
Daytona ~90ms+网络 基于使用 Docker容器

快速演示

注册后,您的MCP客户端可以直接使用沙盒工具:

Agent: exec(command="uname -a")
→ Linux mcp-sb-abc123 6.12.6 #1 SMP aarch64 Linux

Agent: install(packages="python3 py3-pip")
→ Installed python3 py3-pip (1230ms)

Agent: exec(command="python3 -c 'print(sum(range(1000)))'")
→ 499500

Agent: bg(command="python3 -m http.server 8000")
→ Started [bg-a1b2c3] PID 42

Agent: expose(port=8000)
→ Forwarding localhost:8000 → 'default':8000
  Open http://localhost:8000

冷启动时间约为700ms,后续命令每次约为60ms。

需求

  • 苹果硅Mac(M1+)
  • macOS 15红杉+
  • Python 3.11+
  • 紫外线 (用于包装)

设置

1.安装苹果容器

# Download and install the container CLI
curl -LO https://github.com/apple/containerization/releases/download/v0.9.0/container-v0.9.0.pkg
sudo installer -pkg container-v0.9.0.pkg -target /

# Start the container system (downloads kernel on first run)
container system start

# Verify it works
time container run --rm alpine echo "hello"  # ~700ms cold boot

2.构建开发镜像

包括 Containerfile.mcp-dev 构建一个预装了Python、Node.js、Go、Rust和标准构建工具的Alpine映像:

cd sandbox-mcp
container build -t mcp-dev -f Containerfile.mcp-dev .

3.安装MCP服务器

uv sync

4.向您的MCP客户注册

克劳德代码:

claude mcp add sandbox -- uv --directory /path/to/sandbox-mcp run sandbox-mcp

手册(~/.claude.json):

{
  "mcpServers": {
    "sandbox": {
      "type": "stdio",
      "command": "/path/to/uv",
      "args": ["--directory", "/path/to/sandbox-mcp", "run", "sandbox-mcp"]
    }
  }
}

5.构建优化的内核(可选)

苹果的容器化仓库包括一个精简的Linux内核配置。自己编译并不能有意义地改善执行延迟——~700ms的下限是VM生命周期开销(Virtualization.framework+EXT4+网络+vminitd),而不是内核引导。真正的胜利是让虚拟机保持温暖,并使用持久的shell exec(~60ms)。

也就是说,如果你想要一个更小的内核:

git clone https://github.com/apple/containerization.git
cd containerization/kernel
make                                            # ~3 min on M-series
container system kernel set --binary ./vmlinux
container system stop && container system start

运作原理

Agent ──MCP/stdio──▶ sandbox_mcp_server.py (FastMCP)
                           │
                           ├── SandboxManager
                           │     ├── _sandboxes: dict[name, Sandbox]
                           │     ├── _port_forwards: dict[port, PortForward]
                           │     ├── _sync_jobs: dict[id, SyncJob]
                           │     └── _cleanup_loop (idle TTL + child TTL)
                           │
                           ├── SandboxCtlServer (per-parent UDS listener)
                           │     └── NDJSON over /run/sandbox-ctl.sock
                           │           → spawn, list, exec, destroy, run
                           │
                           └── Sandbox (per-VM)
                                 ├── PersistentShell (container exec -i <name> sh)
                                 ├── _bg_processes: dict[id, Process]
                                 └── _audit_log: deque

延迟细分:

  • 冷启动:~700ms(虚拟化框架+EXT4+网络+vminitd)
  • 温暖的执行官:~60ms(命令通过vsock管道传输到持久shell)
  • 为什么温暖很快:每个沙箱都有一个打开的 container exec -i <name> sh 过程。命令以唯一的结束标记写入stdin,读取输出直到标记出现。每个命令没有进程生成开销。

端口转发

苹果容器v0.9.0 -p 端口发布中断(TCP连接但数据从未流动),VM IP无法从主机路由。端口转发通过asyncio TCP代理工作:

  1. expose 在上启动本地TCP服务器 127.0.0.1:<host_port>
  2. 每个传入连接都会生成 container exec -i <name> nc 127.0.0.1 <container_port>
  3. 数据通过vsock在客户端和nc进程之间双向传输

多沙箱

沙盒已命名(默认值: "default").每个都有独立的卷 /workspace 以及包缓存(apk、pip、npm)。缓存在重置过程中保持不变,以便快速重新安装。沙盒可以通过以下方式按名称相互联系 /etc/hosts 当网络可用时,条目会自动注入。

档案

在中配置每个沙盒名称资源 SANDBOX_PROFILES 在服务器的顶部:

SANDBOX_PROFILES = {
    "ml": {"cpus": 4, "memory": "2G"},
    "build": {"cpus": 4, "memory": "1G"},
    "nested": {"cpus": 2, "memory": "1G", "virtualization": True},
}

这 virtualization 标志启用嵌套虚拟化(--virtualization).苹果容器不支持GPU/Metal passthrough——内核有 CONFIG_DRM_VIRTIO_GPU 禁用,Swift框架不使用 VZVirtioGraphicsDeviceConfiguration.

儿童沙盒

沙盒可以生成子沙盒,由以下方式控制 SPAWN_POLICIES 在服务器的顶部。策略定义了每个父级的限制:最大并发子级、生命周期生成计数、CPU/内存预算、允许的映像和TTL。未列出的沙盒名称无法生成。

子级是轻量级的——它们跳过缓存卷,获得自己的隔离工作区。当TTL到期或其父级重置/销毁时,它们会自动销毁。

设置 child_can_spawn: True 在一项政策中,允许孩子们生育自己的孩子(孙子孙女),深度可达 _MAX_SPAWN_GENERATION (默认值2)。孙子策略是自动派生的——并发/预算限制减半,没有进一步的子生成。树范围的预算检查确保无论生成深度如何,根沙盒的CPU/内存包络都不会被超过。默认情况下,此选项处于关闭状态,不建议用于大多数用例。

API容器(sandbox-ctl)

当沙箱具有生成策略时 inject_ctl: True (默认),服务器装载UDS套接字 sandbox-ctl 将二进制文件导入VM。集 inject_ctl: False 对于VM子启动中不需要的沙盒,跳过注入。然后,在VM内运行的代码可以生成/管理兄弟容器:

sandbox-ctl ping                                          # verify connection
sandbox-ctl spawn --image mcp-dev --cpus 1 --memory 256M  # create child
sandbox-ctl list                                           # show children
sandbox-ctl exec <child> -- echo hello                     # run in child
sandbox-ctl destroy <child>                                # tear down
sandbox-ctl run -- echo test                               # ephemeral: spawn + exec + destroy

通信通过安装的套接字使用NDJSON(/run/sandbox-ctl.sock).主机端 SandboxCtlServer 处理请求并委派给 SandboxManager.

状态持久性

沙盒到容器的映射保存到 ~/.local/state/sandbox-mcp/state.json (模式v2)。重新启动时,服务器将重新连接到上一个会话中仍在运行的任何容器。过期的孩子在重新连接时会被清理。

工具(35)

核心

工具 说明
exec 运行shell命令(~60ms)
python 执行Python代码
write_file 将文件写入沙盒
read_file 从沙盒中读取文件
batch_write 在一次传输中写入多个文件
install 通过apk安装软件包
env 管理持久环境变量

过程管理

工具 说明
bg 在后台运行命令
logs 读取后台进程的输出
kill 终止后台进程

沙盒生命周期

工具 说明
status 显示池和沙盒信息
health 在所有沙盒中快速检查活动性/磁盘/内存
stats 显示一个沙盒的CPU/内存/磁盘使用情况
reset 销毁并重新创建(干净状态)
list_all 列出所有活动沙盒
destroy 永久杀死沙盒
clone 将正在运行的沙盒克隆为新名称
history 显示最近的命令审核日志

文件传输

工具 说明
upload 将文件从主机复制到沙盒
download 将文件从沙盒复制到主机
git_clone 克隆一个git仓库(带有可选的身份验证令牌)
sync_start 监视并实时同步主机目录
sync_stop 停止正在运行的同步作业

快照和图像

工具 说明
snapshot 将沙盒状态保存为可重用映像
restore 从已保存的快照启动
list_snapshots 列出可用快照
delete_snapshot 删除已保存的快照映像
build_image 从Containerfile构建容器映像
images 列出所有可用的容器图像

网络

工具 说明
expose 将沙盒端口转发到localhost(TCP代理)
unexpose 阻止端口前进
network_info 显示沙盒之间的IP和连接

儿童沙盒

工具 说明
spawn 在父母的指导下创建一个儿童沙盒
children 列出父级的子沙盒
destroy_child 销毁儿童沙盒

文件

文件 描述
sandbox_mcp_server.py 沙盒类、沙盒管理器、MCP工具定义
cmd/sandbox-ctl/ 用于生成兄弟沙盒的容器内CLI(Go)
pyproject.toml 紫外线/孵化包装,入口点 sandbox-mcp
Containerfile.mcp-dev Alpine 3.23开发镜像,包含Python、Node、Go和Rust
tests/ pytest测试套件

定制

在顶部编辑常量 sandbox_mcp_server.py:

常量 默认值 描述
DEFAULT_IMAGE "mcp-dev" 新沙盒的容器映像
SANDBOX_CPUS 2 每个沙盒的默认CPU核心
SANDBOX_MEMORY "512M" 每个沙盒的默认内存
IDLE_TTL 1800 自动销毁空闲沙盒前的几秒钟
DEFAULT_TIMEOUT 30 默认命令超时时间(秒)
MAX_OUTPUT 50000 每个命令的最大输出字节数
SPAWN_POLICIES {"default": {...}} 每个沙盒的子生成限制和权限
_MAX_SPAWN_GENERATION 2 最大产卵深度(根→ 孩子→ 孙子)

测试

uv run pytest tests/ -v

持续集成

测试通过GitHub Actions在Python 3.11、3.12和3.13上运行。预推:

uv run pytest tests/ -q && python3 -m compileall sandbox_mcp_server.py tests