microvm编排器mcp
MCP服务器,用于在隔离的microVM Claude实例中协调开发任务的并行执行。
目录
特性
- 并行任务执行:在隔离的NixOS微虚拟机中同时运行多个Claude实例
- 完全代理自主权:克劳德与
--dangerously-skip-permissions无限制发展 - Git隔离:每个任务都在隔离的git存储库克隆中运行,以防止冲突
- 自动合并:任务完成后,提交将被重设基数并合并回您的分支
- Docker/Podman支持:无根Podman,VM内部兼容Docker CLI
- Rosetta 2支持:通过透明翻译在Apple Silicon上运行x86_64二进制文件
- 持久化存储:容器映像和Nix存储通过插槽跨任务缓存
- 多回购支持:注册多个存储库,并从单个服务器对其中任何一个存储库运行任务
- 自动插槽分配:通过repo关联自动分配插槽,以实现缓存重用
建筑
┌───────────────────────────────────────────────────────────────────┐
│ Host (macOS) │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ MCP Server (127.0.0.1:8765) │ │
│ │ • RepoRegistry - CLI-managed repo allowlist │ │
│ │ • SlotManager - automatic slot assignment w/ affinity │ │
│ │ • Orchestrator - manages task lifecycle │ │
│ │ • Event queue - async completion notifications │ │
│ │ • Git isolation - clones target repo per task │ │
│ └────────────────────────┬─────────────────────────────────────┘ │
│ │ spawns via nix-build + vfkit │
│ Registered repos: ▼ │
│ ┌──────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ project-a│ │ MicroVM Slot 1 │ │ MicroVM Slot 2 │ ... │
│ │ project-b│ │ ┌────────────┐ │ │ ┌────────────┐ │ │
│ │ project-c│ │ │ NixOS │ │ │ │ NixOS │ │ │
│ └──────────┘ │ │ Claude Code│ │ │ │ Claude Code│ │ │
│ │ │ │ nix develop│ │ │ │ nix develop│ │ │
│ │ │ │ Podman │ │ │ │ Podman │ │ │
│ └───────►│ └────────────┘ │ │ └────────────┘ │ │
│ clone to │ --skip-perms │ │ --skip-perms │ │
│ /workspace └──────────────────┘ └──────────────────┘ │
│ │
│ Mounts per VM: │
│ • /workspace/repo - isolated git clone of target repo │
│ • /nix/store (RO) - host Nix store │
│ • /nix/.rw-store - writable overlay (sparse, 30GB max) │
│ • /var - persistent slot storage │
│ • /var/lib/containers - Podman image cache │
└───────────────────────────────────────────────────────────────────┘任务生命周期
- 创建:
run_task()解析repo别名,将其克隆到.microvm/tasks//repo/ - 插槽:
SlotManager自动分配一个插槽(更倾向于为同一仓库分配相同的插槽) - 启动:NixOS microVM从安装在以下位置的repo开始
/workspace/repo - 执行:
nix develop加载您的flake,然后Claude Code运行该任务 - 提交:Claude向独立仓库提交更改
- 合并:编排器会自动将提交重设为分支的基础
- 清理:VM关闭,插槽释放,可以删除任务目录
先决条件
- 苹果硅上的macOS (vfkit管理程序要求)
- 启用薄片的Nix:
# Verify flakes are enabled
nix --version # Should show 2.4+
grep experimental-features ~/.config/nix-darwin/nix.conf # Should include "flakes"- nix-darwin与Linux构建器 (用于构建aarch64 linux虚拟机)
- Python 3.13+
- 罗塞塔2号 (可选,用于x86_64二进制支持):
softwareupdate --install-rosetta快速开始
# 1. Register your project (must have flake.nix and be a git repo)
microvm-orchestrator allow /path/to/your/project
# 2. Start the MCP server
microvm-orchestrator serve
# 3. Configure Claude Code (see Installation section)
# 4. In Claude Code, use the MCP tools:
# "Use run_task to add unit tests for the auth module in your-project"目标存储库要求
您的存储库必须包含 flake.nix 根与a devShells.default 输出。 这定义了在microVM内运行的Claude Code的开发环境。
flake.nix示例
{
description = "Project Development Environment";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
in
{
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
# Add your tools here
nodejs_22
bun
jdk21
# etc.
];
shellHook = ''
echo "Development environment loaded"
'';
};
}
);
}运作原理
- 编排者 克隆您的存储库 到一个独立的工作目录
- microVM启动并挂载 克隆仓库 在
/workspace/repo - 任务运行器执行:
nix develop . --command - Nix获取输入,构建devShell,并使用您可用的工具启动Claude
- 克劳德可以修改
flake.nix要添加依赖关系,请执行以下操作nix develop再次 - 更改将提交到克隆,并在任务完成后合并回克隆
动态依赖
Claude可以通过编辑在任务期间添加工具 flake.nix。例如,添加 Claude将添加PostgreSQL客户端工具 pkgs.postgresql 到 buildInputs 并重新进入外壳 nix develop.
安装
安装CLI
使用紫外线(推荐):
uv tool install git+https://github.com/Turee/microvm-orchestrator-mcp使用pipx:
pipx install git+https://github.com/Turee/microvm-orchestrator-mcp来源(用于开发):
git clone https://github.com/Turee/microvm-orchestrator-mcp
cd microvm-orchestrator-mcp
uv sync从源代码运行时,在命令前加上 uv run (例如。 uv run microvm-orchestrator serve).
配置Claude代码
添加到MCP配置(~/.config/claude-code/mcp.json):
{
"microvm": {
"type": "http",
"url": "http://127.0.0.1:8765/mcp"
}
}服务器使用HTTP传输(不是stdio),因此您可以在不重新启动服务器的情况下取消MCP查询,这对长时间运行的VM任务很重要。
注册存储库
在运行任务之前,请通过CLI注册存储库:
# Register a repo (alias defaults to directory name)
microvm-orchestrator allow /path/to/your/project
# Register with a custom alias
microvm-orchestrator allow /path/to/your/project --alias myproject
# Verify registration
microvm-orchestrator list运行服务器
microvm-orchestrator serve服务器正在监听 http://127.0.0.1:8765 并为所有注册的存储库提供服务。
当开始没有 --no-tui,服务器在主线程上启动Textual仪表板:
- 左窗格:实时
Tasks表(状态、插槽、描述) - 右窗格:具有可切换源的流式日志查看器(
VM Log,Claude,Server Log) - 页脚:主动键绑定和快速控制
文本仪表板控件
q退出仪表板/服务器进程Tab切换日志源(VM Log->Claude->Server Log)f切换日志自动跟踪c清除当前日志视口End跳转到最新日志条目t焦点任务表窗格l焦点日志窗格
CLI参考
microvm-orchestrator allow [PATH] [--alias ALIAS]
注册一个存储库以用于microvm任务。
PATH:git存储库的路径(默认:当前目录)--alias,-a:仓库的自定义别名(默认:目录名)
microvm-orchestrator allow /path/to/project
# Registered: project
microvm-orchestrator allow /path/to/project --alias myapp
# Registered: myappmicrovm-orchestrator list
列出所有已注册的存储库。
microvm-orchestrator list
# myapp: /path/to/project
# backend: /path/to/backendmicrovm-orchestrator remove ALIAS
从列表中删除存储库。
microvm-orchestrator remove myapp
# Removed: myappmicrovm-orchestrator serve
启动MCP服务器。为所有已注册的存储库提供服务。
--no-tui:运行headless而不启动Textual仪表板
microvm-orchestrator setup-token
与Claude进行身份验证,并将令牌保存在本地。跑动 claude setup-token 并将得到的令牌写入 ~/.microvm-orchestrator/token 随着 0600 权限。
microvm-orchestrator setup-token
# Running 'claude setup-token' — follow the prompts to authenticate...
# Token saved to /Users/you/.microvm-orchestrator/tokenMCP工具参考
run_task
在隔离的microVM中启动新任务。
run_task(description: str, repo: str) -> {"task_id": str}参数:
| 名称 | 类型 | 描述 |
|---|---|---|
description | str | VM中Claude的完整任务说明。包括所有需要的上下文。 |
repo | str | 存储库别名(通过CLI注册)。使用 list_repos() 查看可用的repos。 |
退货: {"task_id": "abc123"} 或 {"error": "message"}
例子:
run_task(
description="Add unit tests for the auth module. Follow existing test patterns in tests/.",
repo="myproject"
)笔记:
- 如果任务涉及Docker,请在描述中包含“use--network=host”
- 在新插槽上首次运行需要更长的时间(创建nix-store覆盖)
- 插槽是自动分配的,无需指定插槽号
______________________________________________________________________
get_task_info
获取有关任务的信息,包括状态、结果和合并结果。
get_task_info(task_id: str) -> dict退货:
{
"status": "completed",
"result": {
"success": true,
"summary": "Added 5 unit tests...",
"files_changed": ["tests/auth.test.ts"],
"error": null
},
"merge_result": {
"merged": true,
"method": "fast-forward",
"commits": 2,
"conflicts": []
},
"pid": 12345,
"exit_code": 0
}状态值: pending, running, completed, failed
______________________________________________________________________
get_task_logs
获取任务串行控制台日志文件的路径。
get_task_logs(task_id: str) -> {"log_path": str}用途:
# Stream logs in real-time
tail -f
# View full log
cat ______________________________________________________________________
wait_next_event
阻塞,直到任何任务完成或失败。
wait_next_event(timeout_ms: int = 1800000) -> dict参数:
| 名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
timeout_ms | int | 18000000 | 超时(毫秒)(30分钟)。对长时间运行的任务使用较长的值。 |
退货:
{
"type": "completed",
"task_id": "abc123",
"result": { ... },
"merge_result": { ... }
}或者超时: {"timeout": true}
多任务模式:
# Start multiple tasks
run_task("Task A", repo="frontend")
run_task("Task B", repo="backend")
# Wait for each to complete
event1 = wait_next_event(timeout_ms=300000) # 5 min
event2 = wait_next_event(timeout_ms=300000)______________________________________________________________________
清理任务
清理任务目录,并可选择删除git ref。
cleanup_task(task_id: str, delete_ref: bool = False) -> {"success": bool}参数:
| 名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
task_id | str | 必需 | 要清理的任务ID |
delete_ref | bool | false | 同时删除 refs/tasks/ 从git |
______________________________________________________________________
list_repos
列出可用于的已注册存储库 run_task.
list_repos() -> {"repos": [{"alias": str, "path": str, "added": str}, ...]}示例响应:
{
"repos": [
{"alias": "myproject", "path": "/Users/me/projects/myproject", "added": "2025-01-15T10:30:00+00:00"},
{"alias": "backend", "path": "/Users/me/projects/backend", "added": "2025-01-15T10:31:00+00:00"}
]
}______________________________________________________________________
list_tasks
列出所有已注册存储库中的所有任务。
list_tasks() -> {"tasks": [{"task_id": str, "status": str, "description": str, "repo": str}, ...]}______________________________________________________________________
list_slot
显示插槽状态和可用性。
list_slots() -> {"max_slots": int, "active": [...], "available": [int, ...]}示例响应:
{
"max_slots": 10,
"active": [
{"slot": 1, "task_id": "abc123"},
{"slot": 3, "task_id": "def456"}
],
"available": [2, 4, 5, 6, 7, 8, 9, 10]
}并行执行
插槽会自动分配,具有回购关联性。只管打电话 run_task 对于任何已注册的回购—— SlotManager 处理其余部分:
# Run tasks across different repos — slots assigned automatically
run_task(description="Add auth tests", repo="frontend")
run_task(description="Add API endpoint", repo="backend")
run_task(description="Update docs", repo="frontend")
# Wait for results
event1 = wait_next_event(timeout_ms=300000)
event2 = wait_next_event(timeout_ms=300000)
event3 = wait_next_event(timeout_ms=300000)插槽分配是如何工作的:
- 每个仓库都会根据其路径的哈希值(确定性)获得一个“首选”插槽
- 如果首选插槽空闲,则使用它——这将最大限度地提高Nix存储和容器缓存的重用率
- 如果首选插槽繁忙,则使用任何空闲插槽
- 最多10个插槽。如果大家都很忙,
run_task返回错误--等待任务完成或检查list_slots()
插槽存储位置: ~/.microvm-orchestrator/slots//
插槽存储跨任务持续存在,因此容器映像和Nix包被缓存。
文件位置
| 路径 | 描述 |
|---|---|
~/.microvm-orchestrator/allowed-repos.json | 注册仓库列表 |
~/.microvm-orchestrator/slot-assignments.json | 回购到插槽的关联映射 |
~/.microvm-orchestrator/token | API令牌(由创建 setup-token) |
.microvm/tasks// | 任务工作目录 |
.microvm/tasks//task.json | 任务元数据和状态 |
.microvm/tasks//task.md | 原始任务描述 |
.microvm/tasks//repo/ | 隔离的git存储库克隆 |
.microvm/tasks//serial.log | VM控制台输出 |
.microvm/tasks//result.json | Claude的任务结果 |
.microvm/tasks//merge-result.json | Git合并结果 |
.microvm/tasks//claude-stream.jsonl | Claude Code JSON输出流 |
~/.microvm-orchestrator/slots// | 持久插槽存储 |
~/.microvm-orchestrator/slots//var/ | systemd、logs的持久化/var |
~/.microvm-orchestrator/slots//container-storage/ | Podman图像缓存 |
~/.microvm-orchestrator/slots//nix-store.img | 可书写的Nix商店覆盖层 |
结果格式
任务结果(result.json)
{
"success": true,
"summary": "Claude's full explanation of what was done",
"files_changed": ["src/auth.ts", "tests/auth.test.ts"],
"error": null
}合并结果(merge-result.json)
成功:
{
"merged": true,
"method": "fast-forward",
"commits": 2,
"conflicts": []
}冲突:
{
"merged": false,
"reason": "conflicts",
"conflicts": ["src/shared.ts"],
"task_ref": "refs/tasks/"
}手动冲突解决
如果自动合并失败,提交将保留在 refs/tasks/。您可以:
- 使用冲突解决程序代理
- 手动樱桃采摘或重基:
# View task commits
git log refs/tasks/
# Cherry-pick
git cherry-pick refs/tasks/
# Or rebase
git checkout -b temp refs/tasks/
git rebase main
git checkout main
git merge --ff-only temp
git branch -d temp故障排除
常见错误
| 错误 | 原因 | 解决方案 |
|---|---|---|
| “回购'x'未注册” | 回购别名不在列表中 | 运行 microvm-orchestrator allow /path/to/repo |
| “所有10个插槽都忙” | 没有可用插槽 | 等待任务完成或检查 list_slots() |
| “未找到flake.nix” | 目标仓库缺少flake | 添加 flake.nix 随着 devShells.default |
| “找不到API键” | 缺少环境变量 | 集 ANTHROPIC_API_KEY 或奔跑 microvm-orchestrator setup-token |
| “nix构建失败” | 缺陷评估错误 | 运行 nix flake check 在您的repo中 |
| “网络未就绪” | VM无法访问互联网 | 检查主机网络连接 |
| 任务超时 | 长时间运行的任务 | 增加 timeout_ms 在 wait_next_event |
| “不支持x86_64-linux” | 缺少Rosetta | 运行 softwareupdate --install-rosetta |
调试提示
检查任务状态:
cat .microvm/tasks//task.json | jq .status查看Claude的输出:
tail -100 .microvm/tasks//serial.log实时流日志:
tail -f .microvm/tasks//serial.log检查任务结果:
cat .microvm/tasks//result.json | jq .检查合并结果:
cat .microvm/tasks//merge-result.json | jq .查看Claude的流输出:
cat .microvm/tasks//claude-stream.jsonl | jq -s .注: claude-stream.jsonl 可能包含一些非JSON序言行(例如 nix develop 设置输出),然后JSON事件开始。要仅检查JSON事件,请执行以下操作:
grep -E '^\{' .microvm/tasks//claude-stream.jsonl | jq -s .VM启动问题
- 第一次开机很慢:创建Nix存储覆盖(约30GB稀疏文件)需要时间
- Rosetta错误:安装
softwareupdate --install-rosetta - 构建失败:检查
nix flake check在您的目标回购上
性能和限制
| 度量 | 值 |
|---|---|
| 每个插槽的第一个任务 | 1-2分钟(创建Nix商店覆盖) |
| 后续任务 | 30-60秒(VM启动+任务执行) |
| 每个插槽的存储空间 | ~2-5GB实际值(最大30GB,稀疏文件) |
| 虚拟机资源 | 4个vCPU,4 GB RAM(硬编码) |
| 平台 | 仅限macOS苹果硅(vfkit) |
| 最大并行插槽 | 10(受主机RAM限制,每个VM 4 GB) |
存储注意事项:The nix-store.img 是一个稀疏文件,它报告30GB,但只使用实际磁盘空间来写入数据(典型值约为2GB)。
安全考虑
- 完全代理自主权:虚拟机运行Claude
--dangerously-skip-permissions无限制发展 - API密钥处理:令牌存储在
~/.microvm-orchestrator/token随着0600权限;写入VM临时文件,读取一次,然后删除 - 网络接入:虚拟机对npm、API调用等具有完全的互联网访问权限。
- Git隔离:任务在克隆上工作,从不直接修改原始仓库
- 硬件隔离:通过vfkit管理程序完成VM隔离
- Repo对抗主义者:只能使用明确注册的存储库
发展
看 代理商.md 获取发展指南和贡献信息。
# Run tests
uv run pytest
# Run with coverage
uv run pytest --cov许可证
麻省理工学院
