MCP QEMU VM控制
安全地让你的AI完全访问计算机。 让Claude(或任何兼容MCP的LLM)看到您的屏幕,移动鼠标,在键盘上键入,并运行命令——所有这些都在一个隔离的QEMU虚拟机内。非常适合人工智能驱动的自动化、测试和计算机使用实验,而不会危及您的主机系统。
用于通过SSH控制QEMU虚拟机的模型上下文协议(MCP)服务器。此服务器使LLM能够通过鼠标/键盘控制、屏幕截图和SSH命令执行与VM交互。
目录
特性
- 鼠标控制 -移动光标并单击按钮
- 键盘输入 -键入文本并发送组合键
- 动作批处理 -在一次调用中执行UI操作序列
- 截图 -捕获和检索虚拟机屏幕截图
- SSH命令执行 -在VM上运行shell命令
- 文件传输 -通过SFTP上传和下载文件
- 项目管理 -将输出与日志、结果和建议一起组织到项目文件夹中
- 咨询系统 -保存和检索未来LLM会话的提示
先决条件
主机系统
- Python 3.12+
uv(推荐)或pip- 带libvirt的QEMU/KVM
- virt管理器(可选,用于GUI管理)
VM要求
- Linux与X11桌面环境
- SSH服务器已启用
- 所需软件包:
openssh,xdotool,scrot,xrandr,xinput
QEMU/libvirt设置
1.安装虚拟化软件包
拱门/曼加洛:
sudo pacman -S qemu-full libvirt virt-manager dnsmasq iptables-nftDebian/Ubuntu:
sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients virt-manager bridge-utilsFedora:
sudo dnf install @virtualization2.配置libvirt
# Enable and start libvirtd
sudo systemctl enable --now libvirtd
# Add your user to libvirt group
sudo usermod -aG libvirt $USER
# Log out and back in, then verify
groups # should show 'libvirt'3.设置默认网络
libvirt提供默认NAT网络(192.168.122.0/24)VM用于与主机通信:
# Check network status
virsh -c qemu:///system net-list --all
# If 'default' is not active, start it
virsh -c qemu:///system net-start default
# Enable autostart
virsh -c qemu:///system net-autostart default默认网络配置:
- 桥梁:
virbr0 - 主机IP:
192.168.122.1 - DHCP范围:
192.168.122.2-192.168.122.254 - 模式:NAT(虚拟机可以访问互联网,主机可以访问虚拟机)
4.使用virt manager创建虚拟机
- 启动virt管理器
- 创建新VM(文件→ 新建虚拟机)
- 选择安装介质(ISO)
- 分配资源:
- 内存:建议4096 MB - CPU:建议使用2+
- 重要:在“网络选择”下,选择“虚拟网络‘默认’:NAT”
- 完成安装
5.配置虚拟机
安装来宾操作系统后:
# Inside the VM - Install required packages
# Arch/Manjaro
sudo pacman -S --needed openssh xdotool scrot xorg-xrandr xorg-xinput
# Debian/Ubuntu
sudo apt install openssh-server xdotool scrot x11-xserver-utils xinput
# Enable SSH
sudo systemctl enable --now sshd6.创建自动化用户
在VM上:
# Create vmrobot user
sudo useradd -m -s /bin/bash vmrobot
sudo passwd vmrobot
# Set up SSH key authentication
sudo -u vmrobot mkdir -p /home/vmrobot/.ssh
sudo -u vmrobot chmod 700 /home/vmrobot/.ssh在主机上:
# Copy your public key to the VM
ssh-copy-id vmrobot@192.168.122.XX
# Or manually add to /home/vmrobot/.ssh/authorized_keys on VM7.授予X11访问vmrobot的权限
vmrobot用户需要权限才能访问X显示器。在虚拟机上,作为拥有桌面会话的用户:
# Quick fix (run once per session)
xhost +local:vmrobot
# Permanent fix - add to ~/.xprofile or ~/.xinitrc
echo "xhost +local:" >> ~/.xprofile8.选择SSH用户策略
SSH用户有两种方法:
选项A:专用 vmrobot 用户(默认)
- 更安全——权限有限,不会意外破坏桌面配置
- 需要
xhost +local:vmrobotX11访问(步骤7) - 集
VM_DESKTOP_USER如果你需要需要桌面命令
用户的上下文(剪贴板、密码管理器、dbus):
# On the VM, allow vmrobot to run commands as your desktop user
echo 'vmrobot ALL=(sergey) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/vmrobot-desktop
sudo chmod 440 /etc/sudoers.d/vmrobot-desktop然后设置 VM_DESKTOP_USER=sergey 在您的配置中。 使用 ssh_execute("xclip -selection clipboard -o", as_desktop_user=True).
选项B:SSH直接作为桌面用户
- 更简单——开箱即用的完全桌面访问,无需xhost或sudo
- 集
VM_USER到您的桌面用户名(例如。,sergey) - 所有命令都以完全桌面权限运行
- 最适合不需要担心隔离的个人/开发虚拟机
9.查找虚拟机的IP地址
# From the host
virsh -c qemu:///system domifaddr manjaro
# Or from inside the VM
ip addr show | grep "inet 192.168.122"10.测试连接
# Test SSH
ssh vmrobot@192.168.122.XX
# Test X11 automation
ssh vmrobot@192.168.122.XX 'DISPLAY=:0 xdotool getmouselocation'
# Test screenshot
ssh vmrobot@192.168.122.XX 'DISPLAY=:0 scrot /tmp/test.png && echo Success'安装
1.克隆存储库
git clone https://github.com/Neanderthal/mcp-qemu-vm.git
cd mcp-qemu-vm2.安装依赖项
使用 uv (推荐):
uv venv && source .venv/bin/activate
uv pip install -r requirements.txt使用 pip:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt配置
设置环境变量或创建 .env 文件:
| 变量 | 默认值 | 描述 |
|---|---|---|
VM_HOST | 192.168.122.79 | VM IP地址 |
VM_USER | vmrobot | SSH用户名 |
VM_PORT | 22 | SSH端口 |
VM_DISPLAY | :0 | X11显示器 |
VM_IDENTITY | (空) | SSH私钥路径(可选) |
VM_DESKTOP_USER | (空) | 桌面会话所有者,如果与 VM_USER |
VM_KNOWN_HOSTS | (无) | SSH known_hosts文件路径(可选) |
VM_CONNECT_TIMEOUT | 10 | SSH连接超时(秒) |
看 .env.example 用于记录模板。
用法
MCP客户端配置
添加到您的MCP客户端配置中(例如,Claude Desktop claude_desktop_config.json):
{
"qemu-vm-control": {
"command": "python3",
"args": ["/path/to/mcp-qemu-vm/server.py"],
"env": {
"VM_HOST": "192.168.122.79",
"VM_USER": "vmrobot",
"VM_PORT": "22",
"VM_DISPLAY": ":0"
}
}
}配置文件位置:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - 窗户:
%APPDATA%/Claude/claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
使用MCP Inspector进行开发
uv run mcp dev server.py
# With custom environment
VM_HOST=192.168.122.79 VM_USER=vmrobot uv run mcp dev server.py独立运行
python server.py工具参考
项目管理
项目将所有输出(屏幕截图、日志、结果、建议)组织到以下带时间戳的文件夹中 data/projects/.
| 工具 | 说明 |
|---|---|
project_init(name, description) | 创建新项目(截图前需要) |
project_load(project_path) | 加载现有项目 |
project_list() | 列出所有项目 |
project_info() | 获取当前项目统计信息 |
project_log(message, level) | 添加日志条目 |
project_read_logs(lines, level_filter) | 读取项目日志 |
project_save_result(filename, content) | 保存结果文件 |
project_save_advice(title, content) | 为以后的会话保存提示 |
project_read_advice() | 阅读所有已保存的建议 |
鼠标和键盘
| 工具 | 说明 |
|---|---|
move_mouse(x, y, mode) | 移动光标(模式:“绝对”或“相对”) |
click(button, count) | 单击鼠标按钮(左/中/右) |
type_text(text) | 键入文本 |
press_keys(keys) | 按下组合键。, ["Ctrl", "L"] |
wait(seconds) | 暂停执行 |
run_actions(actions) | 在一次调用中执行一系列操作 |
批处理操作示例
[
{"action": "press_keys", "keys": ["Ctrl", "Shift", "p"]},
{"action": "wait", "seconds": 0.5},
{"action": "type_text", "text": "Terminal: Focus Terminal"},
{"action": "press_keys", "keys": ["Return"]}
]SSH操作
| 工具 | 说明 |
|---|---|
ssh_execute(command, as_desktop_user) | 在VM上运行shell命令 |
ssh_upload(local_path, remote_path) | 将文件上传到VM |
ssh_download(remote_path, local_path) | 从VM下载文件 |
ssh_connection_info() | 获取连接状态 |
截图
| 工具 | 说明 |
|---|---|
take_screenshot() | 截图(需要活动项目) |
屏幕截图保存到项目的 screenshots/ 文件夹,并在以下位置作为MCP资源公开 vm://screenshot/{id}.
典型工作流程
1. project_init("my-task", "Description")
2. take_screenshot()
3. ... perform VM operations ...
4. project_read_logs()
5. project_save_result("output.txt", data)
6. project_save_advice("Title", "Lessons learned...")继续工作:
1. project_list()
2. project_load("data/projects/...") # Shows any saved advice
3. ... continue work ...LLM自动化的最佳实践
这些经验教训是从现实世界的使用中吸取的,有助于避免常见的陷阱。
1.操作前始终进行截图
在任何互动之前:
take_screenshot()- 分析图像
- 确定当前焦点(哪个窗口/字段处于活动状态)
- 只有这样才能继续行动
切勿跳过截图以“节省时间” -盲目的行为会导致错误。
2.不要相信鼠标点击可以聚焦
点击窗口/终端并不能可靠地切换焦点,尤其是在以下情况下:
- 嵌套环境(Citrix、远程桌面)
- 高延迟连接
- 具有多个面板的应用程序(VS代码、IDE)
请改用键盘快捷键:
[
{"action": "press_keys", "keys": ["Ctrl", "Shift", "p"]},
{"action": "wait", "seconds": 0.5},
{"action": "type_text", "text": "Terminal: Focus Terminal"},
{"action": "wait", "seconds": 0.3},
{"action": "press_keys", "keys": ["Return"]},
{"action": "wait", "seconds": 0.5}
]然后 take_screenshot() 在打字前进行验证。
3.所需等待时间
| 此操作后 | 等待时间 |
|---|---|
| 打开命令面板 | 0.5秒 |
| 键入搜索文本 | 0.3s |
| 按下回车键 | 0.5-1.0秒 |
| 命令执行 | 1.0-2.0秒 |
| 窗口/焦点开关 | 0.5秒 |
切勿快速开火 -它们可能会出现故障。
4.使用批处理操作
使用 run_actions() 而不是单独调用工具来减少延迟并确保排序:
# Instead of 5 separate calls:
run_actions([
{"action": "press_keys", "keys": ["Ctrl", "Shift", "p"]},
{"action": "wait", "seconds": 0.5},
{"action": "type_text", "text": "command"},
{"action": "wait", "seconds": 0.3},
{"action": "press_keys", "keys": ["Return"]}
])5.SSH范围限制
ssh_execute 仅达到 第一VM层.对于嵌套环境(VM→ 思杰→ Windows),使用UI自动化在可见终端中键入命令。
6.恢复命令
| 问题 | 解决方案 |
|---|---|
| 在错误的窗口中键入(几个字符) | Escape → u (在Vim中撤消) |
| 多条线放错了地方 | Escape → uuuuuuu |
| 文件已损坏 | Escape → :e! → Enter (重新加载) |
| VS代码还原 | Ctrl+Shift+P → “还原文件” |
7.要避免的常见错误
- 点击终端后立即打字(焦点可能没有切换)
- 跳过屏幕截图以“节省时间”
- 使用
ssh_execute用于嵌套环境命令 - 不在行动之间等待
- 假设焦点在未经验证的情况下切换
建筑
┌─────────────┐ SSH ┌──────────────┐
│ │ ◄──────────────────► │ │
│ MCP Server │ │ QEMU VM │
│ (Host) │ │ (Linux) │
│ │ │ │
└──────┬──────┘ └──────────────┘
│ │
│ MCP Protocol │
│ (stdio) │
│ │
▼ ▼
┌─────────────┐ xdotool, scrot
│ LLM Client │ X11 automation
│ (Claude) │
└─────────────┘网络拓扑:
┌────────────────────────────────────────────────────┐
│ Host (192.168.122.1) │
│ ┌──────────┐ │
│ │ virbr0 │◄── NAT bridge │
│ └────┬─────┘ │
│ │ │
│ ┌────┴─────┐ │
│ │ QEMU VM │ 192.168.122.79 │
│ │ (manjaro)│ │
│ └──────────┘ │
└────────────────────────────────────────────────────┘项目结构
mcp-qemu-vm/
├── server.py # Main MCP server (single file)
├── pyproject.toml # Project metadata, ruff & pytest config
├── requirements.txt # Python dependencies
├── .env.example # Documented env var template
├── data/
│ └── projects/ # Project folders
│ └── YYYYMMDD-HHMMSS_name/
│ ├── screenshots/
│ ├── logs/
│ ├── results/
│ └── advice/
└── README.md故障排除
无法连接到VM
- 检查VM是否正在运行:
virsh -c qemu:///system list- 检查网络是否处于活动状态:
virsh -c qemu:///system net-list
# If default is inactive:
virsh -c qemu:///system net-start default- 检查VM是否具有IP:
virsh -c qemu:///system domifaddr - 测试SSH连接:
ssh vmrobot@192.168.122.XX鼠标/键盘不工作
- 验证
xdotool已安装在VM上:which xdotool - 检查X11显示:
echo $DISPLAY(应该是:0) - 手动测试:
DISPLAY=:0 xdotool getmouselocation
截图失败/X11授权错误
如果你看到 Authorization required, but no authorization protocol specified:
快速修复 (在VM上以X会话所有者身份运行):
xhost +local:vmrobot永久修复 -添加到 ~/.xprofile:
xhost +local:验证访问权限:
# Check current xhost settings
DISPLAY=:0 xhost
# Should show:
# access control enabled, only authorized clients can connect
# LOCAL:VM网络问题
# Restart the default network
virsh -c qemu:///system net-destroy default
virsh -c qemu:///system net-start default
# Check virbr0 bridge exists
ip addr show virbr0许可证
麻省理工学院
