boxes-mcp
boxes-mcp
一个本地 Model Context Protocol (MCP) 服务器,使兼容的智能体和开发者工具能够通过 libvirt/virsh 管理 GNOME Boxes 虚拟机。它提供安全、可逆的虚拟机操作、快照、截图、受限的键盘和鼠标输入,以及按能力门控的 SPICE 功能。
该项目特意针对 GNOME Boxes 的 Linux libvirt/QEMU 技术栈。目前不支持 VMware 和 VirtualBox;它们的显示、输入、客户机代理(guest-agent)、剪贴板和拖放 API 具有不同的信任和能力契约,应作为独立的、有证据支持的提供者来添加,而不是从 libvirt 实现中推断。
目录
Related MCP server: kwin-mcp
功能特性
🖥️ 虚拟机生命周期管理 - 启动、停止、重启、挂起和恢复虚拟机
📸 快照操作 - 创建、列出、还原和删除虚拟机快照
🔍 虚拟机发现 - 列出并检查所有虚拟机的详细信息
🔒 安全操作 - 默认保留存储,无破坏性操作
🎯 兼容 GNOME Boxes - 与 GNOME Boxes 虚拟机无缝协作
🖱️ 受控交互 - 截图、允许列表键盘和输入式鼠标工具
🔌 按能力门控的 SPICE - 可选的原生辅助协议,用于 SPICE 输入、剪贴板和传输
⚡ 快速且轻量 - 低开销,直接 virsh 集成
安装
主机先决条件
Ubuntu 22.04/24.04(或兼容的 Linux 发行版)
已安装 libvirt-daemon-system、qemu-kvm
Node.js 18+ 和 npm
用户属于
libvirt和kvm组virsh在PATH中可用于生命周期、截图、键盘和 QMP 回退操作
SPICE 支持的工具额外需要一个 SPICE 显示器、一个客户机 virtio-serial 代理通道,以及正在运行的 spice-vdagent(或等效的客户机代理)。剪贴板支持还依赖于该代理提供的客户机桌面集成。标准的 spice-vdagent 会话组件面向 X11;Wayland/Hyprland 客户机即使包和服务正在运行,剪贴板仍可能报告 capability-missing。仅在主机提供 spice-client-glib、json-glib 和 GLib 开发文件时,才构建可选的原生辅助程序。对于图形 XML 使用 listen type='none' 的 libvirt 域,该辅助程序使用 libvirt 的本地 graphics-FD API;不需要 remote-viewer、virt-viewer 或公共 SPICE URI:
npm run build:spice-helper
BOXES_SPICE_HELPER="$PWD/native/boxes-spice-helper" npm test该辅助程序不会自动安装或自动选择。只能将 BOXES_SPICE_HELPER 设置为从本仓库构建的、经过审查的可执行文件,或实现下述版本化协议的其他进程。
# Install dependencies
sudo apt install -y libvirt-daemon-system qemu-kvm virt-manager
# Add your user to required groups
sudo usermod -aG libvirt,kvm "$USER"
newgrp libvirt从 npm 安装
npm 包包含一个面向本地 MCP 主机的引导式安装程序。它只安装 Node 服务器;libvirt、virsh、QEMU 和可选的 SPICE 开发库仍是主机先决条件。
# Detect installed MCP hosts and configure them
npx -y boxes-mcp@0.1.0 setup
# Or install the command globally
npm install --global boxes-mcp@0.1.0
boxes-mcp setup预览配置而不写入文件:
npx -y boxes-mcp@0.1.0 setup --dry-run当某个主机在 PATH 中无法被发现时,显式配置该主机:
npx -y boxes-mcp@0.1.0 setup --client codex
npx -y boxes-mcp@0.1.0 setup --client claude
npx -y boxes-mcp@0.1.0 setup --client openclaw安装程序能够检测或显式配置 Codex、Claude Code、OpenClaw、Antigravity、Gemini CLI、OpenCode、Cursor、Windsurf、VS Code、Pi、Cline、Zed 和 Goose。使用 --client generic 为另一个支持 stdio 的智能体打印可移植的 JSON 配置:
npx -y boxes-mcp@0.1.0 setup --client generic该 setup 命令只写入选定的 MCP 条目,在修改现有配置前创建一次性 .boxes-mcp.bak 备份,使用原子替换,并且绝不安装操作系统包或更改虚拟机定义。设置完成后,重启已配置的智能体或工具。运行 boxes-mcp doctor 检查 Node、virsh 以及检测到的主机。
可选的主机设置可在设置过程中持久化保存:
npx -y boxes-mcp@0.1.0 setup \
--libvirt-uri qemu:///session \
--input-backend auto \
--spice-helper /absolute/path/to/native/boxes-spice-helper \
--transfer-root /absolute/path/to/approved/files原生 SPICE 辅助程序不打包为通用二进制。在安装主机的 SPICE/libvirt 开发包后,在兼容的 Linux 主机上构建它,然后通过 --spice-helper 或 BOXES_SPICE_HELPER 传递其经过审查的绝对路径。
从源码安装
# Clone the repository for unreleased changes or development
git clone https://github.com/EF-Code/boxes-mcp.git
cd boxes-mcp
# Install dependencies
npm install
# Build the project
npm run build
# Run tests
npm test
# Configure a local checkout with the same guided installer
npm run setup:guided -- --client codex配置
如需手动设置,请将服务器添加到您的 Claude Code 配置(~/.claude.json)中:
{
"mcpServers": {
"boxes": {
"command": "node",
"args": ["/absolute/path/to/boxes-mcp/dist/src/index.js"],
"env": {
"LIBVIRT_URI": "qemu:///system",
"BOXES_INPUT_BACKEND": "auto"
}
}
}
}可用工具
虚拟机管理
工具 | 描述 | 参数 |
| 列出所有虚拟机 | - |
| 获取虚拟机详情 |
|
| 启动虚拟机 |
|
| 关闭虚拟机(优雅关机) |
|
| 重启虚拟机 |
|
| 挂起虚拟机 |
|
| 恢复已挂起的虚拟机 |
|
| 移除虚拟机(保留存储) |
|
| 获取 SPICE/VNC 地址 |
|
快照管理
工具 | 描述 | 参数 |
| 列出虚拟机快照 |
|
| 创建快照 |
|
| 还原到快照 |
|
| 删除快照 |
|
显示与交互
工具 | 描述 | 参数 | |
`boxes.screenshot` | 将运行中域(domain)的显示捕获为 MCP 图像内容 | `nameOrUuid, screen?: number, backend?: auto | libvirt` |
| 通过 virsh 发送一组受限的、位于允许列表中的 Linux 键序列 |
| |
| 发送类型化的移动/按钮/点击/滚动输入 |
| |
| 通过 SPICE 辅助程序对 UTF-8 剪贴板进行显式读写 |
| |
| 实验性的受限传输,外加指针序列和独立证据 |
|
交互工具从不接受 shell 片段、原始 QMP JSON、任意 virsh 标志、客户机命令或任意传输目标。新操作要求域正在运行,并在其后端不可用时返回稳定的能力/错误代码。
可选环境变量
变量 | 默认值 | 用途 |
|
| 每个域操作使用的 libvirt 连接 |
|
| 默认鼠标后端偏好: |
| unset | 实现版本化 SPICE 辅助协议的显式可执行文件 |
|
| 单个辅助请求的最大持续时间 |
| 进程临时目录 | 临时截图的受控父目录 |
|
| 截图负载大小限制 |
| unset | 拖放源文件所需的规范化主机根目录 |
|
| 传输源大小限制 |
|
| UTF-8 剪贴板负载大小限制 |
BOXES_TRANSFER_ROOT 是刻意要求而不是推断的。路径会经过规范化处理,符号链接逃逸、目录和特殊文件都会被拒绝。
boxes.capabilities 报告观察到的状态。仅有配置并不被视为已连接:当需要外部状态探测时,请使用 probeQmp: true 和/或 probeSpice: true。SPICE 剪贴板和传输需要已连接的客户机代理;除非外部查看器工具提供应用级证据,否则 boxes.drag_drop 报告 applicationAccepted: "unknown"。
键盘输入使用单一固定的 Linux virsh 码集。公开键名不区分大小写,并规范化为大写,但在一个有界组合键中每个键只能出现一次。允许列表为:ALT、BACKSPACE、CAPSLOCK、CTRL、DELETE、DIGIT_0 到 DIGIT_9、DOWN、END、ENTER、ESC、ESCAPE、F1 到 F12、HOME、INSERT、LEFT、META、NUMLOCK、PAGEDOWN、PAGEUP、PAUSE、PRINT、RIGHT、SHIFT、SPACE、SUPER、TAB、UP,以及 A 到 Z。客户机键盘布局决定最终字符;键允许列表并不能保证不依赖于该布局的文本。
使用示例
配合 Claude Code 使用
User: "List all my VMs"
Claude: [Uses boxes.list tool]
User: "Start ubuntu-24.04"
Claude: [Uses boxes.start with nameOrUuid="ubuntu-24.04"]
User: "Create a snapshot called 'before-update' for my fedora VM"
Claude: [Uses boxes.snapshots.create]直接使用
# Run the MCP server
LIBVIRT_URI=qemu:///system node dist/src/index.js开发
项目结构
boxes-mcp/
├── src/
│ ├── index.ts # MCP server entry point
│ ├── tools.ts # Side-effect-free tool registry and handler boundary
│ ├── libvirt.ts # virsh operations & parsers
│ ├── virsh.ts # Shared executable and libvirt URI arguments
│ ├── exec.ts # Safe command execution
│ ├── screenshot.ts # Controlled libvirt screenshot capture
│ ├── keyboard.ts # Allowlisted virsh send-key adapter
│ ├── mouse.ts/qmp.ts # Typed mouse actions and QMP fallback
│ ├── spice.ts # Versioned companion-helper protocol client
│ ├── clipboard.ts # Explicit SPICE clipboard orchestration
│ ├── transfer.ts # Confined host-file validation
│ ├── drag-drop.ts # Experimental transfer/input coordination
│ ├── *.test.ts # Unit tests
├── systemd/
│ └── boxes-mcp.service # Systemd user service
├── dist/ # Compiled JavaScript
├── coverage/ # Test coverage reports
├── package.json
├── tsconfig.json
└── vitest.config.ts测试
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Generate coverage report
npm run test:coverage本地测试覆盖率:当前检出(checkout)运行 95 个通过的测试和 9 个默认跳过的门控实时测试。默认套件无需 libvirt 访问即可安全运行。
exec.ts:100% 语句覆盖libvirt.ts:81.3% 语句覆盖,92.85% 分支覆盖交互验证、命令构造、QMP 响应映射、产物清理、辅助程序成帧、能力发现和路径约束测试
使用以下命令运行显式的本地原生辅助进程检查:
npm run test:spice-helper仅在设置全部三个安全变量后运行 disposable-VM 测试套件:
BOXES_INTEGRATION=1 \
BOXES_TEST_VM=an-explicit-disposable-domain \
BOXES_TEST_VM_DISPOSABLE=1 \
npm run test:integration实时套件绝不会选择已列出的虚拟机、更改虚拟机定义或自行停止客户机服务。客户机代理断连覆盖要求操作员在明确可销毁的客户机中手动断开 spice-vdagent,并添加 BOXES_TEST_AGENT_DISCONNECTED=1;绝不要对不可销毁的客户机执行此操作。
默认测试套件是模拟/本地的:它不能证明 QMP、SPICE、剪贴板或拖放功能在真实虚拟机上的可用性。实时测试必须选择加入,并针对一个明确命名的、带快照的一次性虚拟机;交互工具绝不会选择任意第一个列出的域。
构建
# Build TypeScript
npm run build
# Watch mode for development
npm run dev可选的 systemd 用户服务
仓库中附带的单元文件适用于源码检出环境。当服务器由代理的 MCP 配置启动或通过 npm 全局安装时,不需要它。在构建检出后,将其安装为用户服务以实现自动启动:
BOXES_MCP_DIR="$(pwd)"
NODE_BIN="$(command -v node)"
mkdir -p ~/.config/systemd/user
cp systemd/boxes-mcp.service ~/.config/systemd/user/
sed -i \
-e "s|/usr/bin/node|$NODE_BIN|g" \
-e "s|%h/projects/boxes-mcp|$BOXES_MCP_DIR|g" \
~/.config/systemd/user/boxes-mcp.service
systemctl --user daemon-reload
systemctl --user enable --now boxes-mcp
journalctl --user -fu boxes-mcp安全注意事项
✅ 沙箱化执行:使用 Node.js
execFile,带超时和缓冲区限制✅ 无任意命令:仅允许预定义的 virsh 操作
✅ 类型化输入边界:QMP 命令和 SPICE 操作是内部枚举,带经过验证的参数
✅ 有界负载:按键次数、按住时长、坐标、滚动增量、截图、剪贴板和传输均有上限
✅ 路径限制:拖放源在规范化后必须保持在
BOXES_TRANSFER_ROOT之下✅ 存储保留:默认不删除虚拟机存储
✅ LIBVIRT_URI 隔离:尊重环境指定的 libvirt 连接
⚠️ 需要权限:用户必须具有 libvirt 组成员资格
⚠️ 网络暴露:未经额外安全措施,不设计用于远程访问
⚠️ 扩展的控制面:截图和客户机剪贴板数据不可信;将 MCP 服务器保持在本地 stdio 上
⚠️ SPICE 辅助程序信任:辅助可执行文件是明确的主机依赖项,不得记录凭据、剪贴板内容或文件内容
SPICE 辅助程序协议
TypeScript 服务器启动一个持久化的辅助子进程,并通过 stdin 发送换行分隔的版本 1 JSON 请求,按请求 ID 关联响应。辅助程序以显式的可执行文件路径调用,且不包含调用方控制的参数。请求信封的格式如下:
{
"version": 1,
"id": "request-123",
"operation": "clipboard.read",
"domain": "guest-name",
"display": { "uri": "spice://127.0.0.1:5900" },
"arguments": { "selection": "clipboard", "maxBytes": 1048576 }
}支持的操作名称是内部的(status、mouse、clipboard.read、clipboard.write、file.transfer 和 drag-drop)。辅助程序错误映射为稳定的 MCP 错误,如 SPICE_AGENT_DISCONNECTED、SPICE_CAPABILITY_MISSING 或 SPICE_UNAVAILABLE。负载、行数、待处理请求、传输大小、剪贴板字节数和操作时间均有上限。进度事件永远不会完成请求。辅助程序不会记录剪贴板内容、文件内容、SPICE 票据或凭据。
能力矩阵
能力 | Libvirt/virsh | QMP 回退 | SPICE 辅助程序 |
截图 | 通过 | 不使用 | 适配器保留,无辅助程序时不可用 |
键盘 | 通过白名单 | 不使用 | 不使用 |
鼠标 | 不使用 | QMP 发现后类型化 | 仅当辅助程序状态证明通道和几何信息后, |
剪贴板 | 不可用 | 不可用 | 原生辅助程序中的真实代理协议;Wayland/Hyprland 客户机可能报告 |
文件传输 | 不可用 | 不可用 | 原生辅助程序中的真实 SPICE 异步文件复制路径;当客户机代理通告时,可观察到实时传输完成 |
拖放 | 不可用 | 不可用 | 实验性传输 + 指针证据;应用程序接受情况仍未知 |
剪贴板支持依赖于客户机桌面集成。当前的 SPICE 客户机代理面向 X11,因此 Wayland 客户机(如 Hyprland/Omarchy)即使已安装并运行 spice-vdagent,也可能报告 SPICE_CAPABILITY_MISSING。鼠标和文件传输仍可独立工作。
故障排除
未列出任何虚拟机
# Check libvirt URI
virsh -c qemu:///system list --all
virsh -c qemu:///session list --all
# Verify permissions
groups # Should include 'libvirt' and 'kvm'权限被拒绝
# Re-add to groups and re-login
sudo usermod -aG libvirt,kvm "$USER"
# Then logout/login or:
newgrp libvirt虚拟机未显示在 Boxes 中
打开 virt-manager,检查虚拟机使用哪个连接:
系统连接:
qemu:///system用户会话:
qemu:///session
相应地设置 LIBVIRT_URI 环境变量。
SPICE 能力错误
如果 virsh domdisplay 报告 No graphical display found,且域 XML 包含 <graphics type='spice'><listen type='none'/></graphics>,这是有意的 libvirt 配置,没有公共监听器。不要为了获取查看器 URI 而虚构端口或更改虚拟机定义。配置了原生辅助程序后,boxes-mcp 使用内部 spice+libvirt-fd://local 传输,并为每个 SPICE 通道向 libvirt 请求图形 FD。辅助程序必须使用与 MCP 进程相同的 libvirt 连接:
LIBVIRT_URI=qemu:///session npm run build:spice-helper
BOXES_SPICE_HELPER="$PWD/native/boxes-spice-helper" \
LIBVIRT_URI=qemu:///session node dist/src/index.js域必须正在运行,辅助程序必须链接到 libvirt 和 spice-client-glib,并且客户机必须暴露 virtio SPICE 代理通道。已连接的代理仍可能缺少剪贴板能力;使用 probeSpice: true 检查 boxes.capabilities,而不是仅从 XML 推断支持情况。
使用 probeSpice: true 调用 boxes.capabilities 并检查返回的状态:
configured:已配置经过审查的辅助程序和 SPICE 端点,但尚未请求连接证明;connecting:辅助程序观察到不完整的通道集;connected:所需通道已连接;agent-disconnected:客户机代理未连接;capability-missing:后端、通道、辅助程序或客户机能力缺失。
例如,一个已连接且支持文件传输但不通告剪贴板的客户机代理是 capability-missing,而不是 agent-disconnected。要启用剪贴板,客户机必须安装其发行版的 spice-vdagent 服务,在桌面会话中运行,并通过 virtio SPICE 代理通道连接。在 Wayland/Hyprland 桌面上,验证发行版的代理确实支持该合成器;仅服务处于活动状态并不构成证明。实时 Omarchy 客户机安装了 spice-vdagent 0.23.0-1 且用户服务处于活动状态,但记录了 xrandr output ID NOT FOUND 且没有 org.gnome.Mutter.DisplayConfig 的所有者,因此 boxes-mcp 正确返回了 SPICE_CAPABILITY_MISSING。对于当前上游代理,请使用 X11 客户机会话,或提供单独验证过的 Wayland 剪贴板桥。服务器不会自动安装客户机软件包或启动客户机服务。
持久化的 SPICE 客户端也接受中止信号。取消会终止当前辅助进程,确定性地使所有待处理操作失败,并允许下一个请求创建干净的会话;这报告为 OPERATION_CANCELLED。
直接检查主机依赖项和辅助程序,无需向虚拟机发送输入:
pkg-config --modversion spice-client-glib-2.0 json-glib-1.0 gio-unix-2.0
npm run build:spice-helper辅助程序的本地协议测试有意连接到 127.0.0.1:1,并期望类型化的不可用/断开结果。这不是实时的 SPICE 证明。
路线图
通过
virt-install集成创建虚拟机网络管理(
virsh net-list、端口转发)存储池信息(
virsh vol-list)从 OVA/QCOW2 导入虚拟机
远程 libvirt 连接支持
性能指标和监控
贡献
欢迎贡献!请阅读 CONTRIBUTING.md 了解指南。
Fork 仓库
创建功能分支(
git checkout -b feature/amazing-feature)运行测试(
npm test)提交更改(
git commit -m 'Add amazing feature')推送到分支(
git push origin feature/amazing-feature)打开 Pull Request
许可证
本项目采用 MIT 许可证 - 详情请参阅 LICENSE 文件。
致谢
为 Claude Code 构建
集成 libvirt 虚拟化 API
支持
为 Claude Code 社区用 ❤️ 制作
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityAmaintenanceEnables AI assistants to manage virtual machines, sandboxes, and dev environments through VirtualBox, Hyper-V, and Windows Sandbox, supporting VM lifecycle, ISO downloads, networking, and unattended installs.913MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to automate Linux desktop GUI by launching and interacting with Wayland applications in isolated virtual KWin sessions, or connecting to live desktops for collaborative automation.39MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI models to securely query and manage virtual machines and virtualized resources via the libvirt API through the Model Context Protocol.1MIT
- AlicenseNot gradedqualityDmaintenanceEnables management of KVM/QEMU virtual machines on remote libvirt hosts via SSH, with tools for inspection, lifecycle management, snapshots, and cloning.1AGPL 3.0
Related MCP Connectors
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Eyes and hands on real Windows PCs — observe, click, type via Glasswarp API.
Control Unreal Engine to browse assets, import content, and manage levels and sequences. Automate…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/EF-Code/boxes-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server