关于 ElfDeckAI
ElfDeckAI 为 Linux 和 Steam Deck 上的游戏提供虚拟键盘、手柄和鼠标,并让 AI 查看屏幕后操作输入设备。它通过内核虚拟设备工作,可在 Gaming Mode 和 Desktop Mode 使用。
主要功能
- 01模拟键盘、Xbox 360 类手柄和鼠标
- 02截取屏幕并返回 PNG
- 03支持截图坐标定位鼠标
- 04通过 SSH 从 PC 连接 Steam Deck
- 05验证输入并限制按键持续时间
- 06异常退出时释放所有输入
适用场景
- 01让 AI 查看并操作 Steam Deck 游戏
- 02在 Linux 桌面中自动执行鼠标和键盘操作
- 03根据截图坐标点击界面元素
MCP 相关
stdio MCP 服务提供 21 个键盘、手柄、鼠标和截图工具。MCP 客户端可在本机启动服务,或通过 SSH 在 Steam Deck 上启动服务并远程调用。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
ElfDeckAI
让 AI 在 Steam Deck 上玩游戏。
ElfDeckAI 为 Claude 等 AI 助手提供虚拟控制器、键盘和鼠标, 并让其能够查看 Steam Deck 的屏幕。 AI 会查看游戏画面、决定要做什么,然后自行按下按钮。 它可在游戏模式和桌面模式下运行,也适用于其他 Linux 设备。
从这里开始:Steam Deck(约 5 分钟)
你需要一台 Steam Deck,以及一台连接到同一 Wi-Fi 网络、装有支持 MCP 的 AI 应用(例如 Claude Desktop)的电脑。
1. 在 Deck 上安装。 将 Deck 切换到桌面模式(Steam 按钮 → 电源 → 切换到桌面模式),打开 Konsole,然后粘贴:
curl -fsSL https://raw.githubusercontent.com/Garthnesss/ElfDeckAI/main/install-on-deck.sh | sh
最后会显示 Deck 的 IP 地址。请留好,步骤 3 中会用到。
2. 在 Deck 上开启 SSH(只需一次),以便电脑连接到它。在同一个 Konsole 窗口中:
passwd # choose a password for the Deck, if you haven't
sudo systemctl enable --now sshd
3. 连接电脑。 在电脑上粘贴一行命令。它会询问 Deck 的 IP 地址和密码(只需一次),然后完成所有设置,包括配置 Claude Desktop。
- Windows(在 PowerShell 中):
irm https://raw.githubusercontent.com/Garthnesss/ElfDeckAI/main/setup-pc.ps1 | iex - Mac 或 Linux(在 Terminal 中):
curl -fsSL https://raw.githubusercontent.com/Garthnesss/ElfDeckAI/main/setup-pc.sh | sh
4. 试试看。 重启 Claude Desktop 并询问:“截一张 Steam Deck 的屏幕截图。” 看到 Deck 的屏幕后,启动游戏并让 AI 来玩。
提示
- 回合制游戏、RPG、解谜游戏和菜单效果最好。AI 每次操作需要一秒或更久,因此无法应对快节奏的动作游戏。
- 在游戏模式下,如果游戏忽略了 AI 的控制器,请让 AI 将控制器设为 玩家 1。它知道该怎么做,可以在游戏运行时使用 Steam 的重新排序控制器菜单。
- 遇到问题?将 AI_SETUP_GUIDE.md 提供给你的 AI,并让它帮忙。该指南逐步介绍了设置和故障排除方法。
工作原理
Deck 上的三个小程序通过 Linux 内核的 /dev/uinput 创建虚拟输入设备,让游戏和 Steam 将它们识别为真实硬件:
- ElfKey:虚拟键盘
- ElfPad:虚拟 Xbox 360 级别的游戏手柄(按钮、模拟扳机、双摇杆、方向键)
- ElfMouse:虚拟鼠标,也可以点击屏幕上的精确位置
第四个程序 MCP 服务会将这些设备以及截图工具作为工具开放,供任意 MCP 客户端调用。你电脑上的 AI 应用会通过 SSH 在 Deck 上启动该服务。它不依赖特定游戏或模拟器:ElfDeckAI 已在实体 Steam Deck 上通过 RetroArch 玩过 Pokémon FireRed,从开场一直玩到首次与劲敌对战,过程中 Agent 只能看到截图。请参阅 notes/driving.md 了解经验总结。
所有程序都是仅使用标准库的单文件 Python 程序,安装到 Deck 上无需 sudo。
其他 Linux 设备
pip install elfdeckai
elfkey &
elfpad &
elfmouse &
echo "key x 150" > /tmp/elfkey.fifo # tap X for 150 ms
echo "press a" > /tmp/elfpad.fifo # tap A
echo "move 300 -100" > /tmp/elfmouse.fifo # move the pointer
echo "click left" > /tmp/elfmouse.fifo # left click
grep -E "ElfKey|ElfPad|ElfMouse" /proc/bus/input/devices # confirm the devices exist
如果不使用 pip,可以克隆代码库并直接运行 python3 elfkey.py(以及其他程序)。
运行时状态保存在 /tmp 中,并会在重启时清除。
在 Steam Deck 上,用户默认可写入 /dev/uinput。在其他发行版上,请先安装 udev 规则(参见安装)。
MCP 服务
elfdeckai-mcp 是一个模型上下文协议服务(stdio 传输),提供 21 个工具:
| 分组 | 工具 |
|---|---|
| 键盘 | key_tap、key_down、key_up、key_release |
| 游戏手柄 | pad_press、pad_down、pad_up、pad_stick、pad_trigger、pad_center、pad_reset |
| 鼠标 | mouse_click_at、mouse_move_to、mouse_move、mouse_click、mouse_down、mouse_up、mouse_scroll、mouse_hscroll、mouse_release |
| 视觉 | screenshot |
screenshot 会截取服务所在机器的屏幕并返回 PNG,因此 Agent 无需单独的视频流,也能通过“观察、操作、再观察”的循环进行工作。它支持 Steam Deck 的 Gaming Mode(通过 gamescope)和 Desktop Mode(KDE Plasma)、wlroots 合成器以及 X11。长边超过 1280 像素的屏幕会在发送前缩小(设置 ELFDECKAI_SCREENSHOT_MAX 可更改限制,设为 0 可关闭限制),结果中会包含图像尺寸。
mouse_click_at 和 mouse_move_to 使用最近一次截图中的像素坐标,因此 Agent 可以准确点击所见内容,无论屏幕的实际分辨率或应用的缩放如何。它们假定只有一个显示器。
在运行守护进程的同一台机器上运行:
{"mcpServers": {"elfdeckai": {"command": "elfdeckai-mcp"}}}
通过 SSH,在 PC 上使用 AI 客户端连接 Steam Deck(从这里开始中的 setup-pc 脚本会为你写入此配置):
{"mcpServers": {"elfdeckai": {
"command": "ssh",
"args": ["-i", "~/.ssh/elfdeckai_ed25519", "-o", "IdentitiesOnly=yes",
"-o", "BatchMode=yes", "deck@DECK-IP-ADDRESS", ".local/bin/elfdeckai-mcp"]}}}
它使用 SSH 密钥登录,因为 MCP 客户端无法回应密码提示。如果没有 pip,请使用
"command": "python3", "args": ["/path/to/elfdeckai_mcp.py"]。
在写入 FIFO 之前,每次工具调用都会根据工具的架构和守护进程自身的解析器进行验证。如果守护进程未运行,调用会立即返回错误,而不会阻塞。
命令参考
ElfKey(/tmp/elfkey.fifo)
| 命令 | 效果 |
|---|---|
key <name> [ms] | 轻按按键(默认 120 ms) |
down <name> / up <name> | 按住 / 释放按键 |
release | 释放所有按住的按键 |
quit | 释放所有按键并退出 |
按键:a–z、0–9、方向键、enter、esc、space、tab、backspace、shift、rshift、ctrl、rctrl、alt、ralt、capslock、f1–f10、home、end、pageup、pagedown、insert、delete 和常用标点符号。完整列表见 elfkey.py 中的 KEYS。
ElfPad(/tmp/elfpad.fifo)
| 命令 | 效果 |
|---|---|
press <btn> [ms] | 轻按按钮或方向键(默认 120 ms) |
down <btn> / up <btn> | 按住 / 释放 |
stick left|right <x> <y> [ms] | 设置模拟摇杆,每个轴的范围为 −100 到 100;指定 ms 后会重新居中 |
trigger left|right <0..100> [ms] | 设置模拟扳机;指定 ms 后会释放 |
center | 将摇杆、扳机和方向键恢复到中立位置 |
reset | 释放所有输入 |
quit | 释放所有输入并退出 |
按钮:a b x y lb rb l2 r2 select start guide l3 r3,以及方向键 up down left right。
ElfPad 会被识别为 Xbox 360 控制器,因此 SDL、Steam Input 和 RetroArch 无需配置即可映射。l2 和 r2 会驱动模拟扳机轴,与真实控制器相同;这里有意不提供数字扳机按钮,因为声明这些按钮会使 Select、Start 和 Guide 脱离标准按钮索引。
ElfMouse (/tmp/elfmouse.fifo)
| 命令 | 效果 |
|---|---|
move <dx> <dy> [glide_ms] | 相对移动指针;指定 glide_ms 时,在这段时间内完成移动 |
moveto <x> <y> [<width> <height>] | 将指针放在绝对位置:width×height 帧中的像素坐标 (x, y);未指定帧时,使用屏幕范围内 0–32767 的设备单位 |
click <btn> [ms] | 单击 left、right 或 middle(默认 100 ms) |
down <btn> / up <btn> | 按住 / 释放按钮(拖动时依次使用:down、move、up) |
scroll <ticks> / hscroll <ticks> | 垂直 / 水平滚轮(正值表示向上 / 向右) |
release | 释放所有按住的按钮 |
quit | 释放所有输入并退出 |
move 是相对移动:负数 dy 表示向上移动。其单位是移动计数值,
不一定对应屏幕像素,因为指针加速会产生影响。每条命令的范围限制为
±10,000 个计数值和 ±120 个滚轮刻度。
moveto 使用第二个虚拟设备 ElfMouse Absolute,合成器会将其视作
虚拟机的平板指针,因此定位精确。按钮会在最近一次移动所用的设备上按下。
安全模型
由于调用者可能是语言模型,因此这些守护进程经过设计,确保错误输入不会让 机器陷入异常状态:
- 拒绝格式错误的输入,不会导致致命错误。 每一行都会经过严格解析;无效命令会被记录并忽略。
- 轻击时长有限。 定时按住最长持续 5 秒。更长时间的按住操作请使用
down/up。 - 不会卡住输入。 定时操作会在
finally块中恢复状态,按住的输入会被跟踪;收到quit、SIGTERM 或 SIGINT 时,会在移除设备前释放所有输入。可按需使用key_release、mouse_release和pad_reset释放所有输入。 - 仅所有者可访问。 每个 FIFO 都以 0600 权限创建。
- 审计日志。 每条已接受的命令都会写入 stderr(作为服务运行时写入日志)。
- 稳健的协议处理。 对格式错误或过大的请求,MCP 服务会返回正确的 JSON-RPC 错误;即使守护进程已停止,也不会阻塞。
范围: 这些都是真实的 OS 级输入设备。它们会作用于当前获得焦点的窗口,包括终端和浏览器。ElfDeckAI 会限制输入范围、验证输入并确保输入可释放;决定 Agent 可以在哪里操作由操作者负责。只运行你信任的 Agent,并在你可以监督的会话中运行。
与其他方法的比较
| 方法 | 局限 |
|---|---|
| 模拟器 API(PyBoy、mGBA 脚本) | 只能在特定模拟器内工作。 |
| 通过 Moonlight 或其他流媒体客户端发送按键 | 鼠标单击会被转发,但合成键盘事件不会。 |
| xdotool | 无法控制原生 Wayland 客户端。 |
| ydotool、dotool | 键盘和鼠标使用相同的 uinput 方法,但不支持游戏手柄、原始键码,也没有面向 Agent 的接口(MCP、输入范围限制、释放命令)。 |
| 硬件输入模拟器(KVM 小工具、控制器适配器) | 可以使用,但需要额外硬件。 |
安装
要求: 64 位 Linux,配备 /dev/uinput,并安装 Python 3.9 或更高版本。
如果你的用户无法写入 /dev/uinput,请安装一次 udev 规则:
sudo cp 70-elfdeckai-uinput.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm trigger
getfacl /dev/uinput # your user should appear in the ACL
运行 pip install --user elfdeckai 后,如需将守护进程作为 systemd 用户服务运行
(单元文件要求命令位于 ~/.local/bin):
mkdir -p ~/.config/systemd/user
cp systemd/*.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now elfkey.service elfpad.service elfmouse.service
开发
pip install -e ".[test]"
python3 -m pytest
测试套件涵盖每个守护进程的输入解析器、针对模拟 uinput 设备的设备行为,以及通过真实 JSON-RPC 运行的 MCP 服务。运行测试无需
/dev/uinput。
路线图
参见 ROADMAP.md。
更新日志
参见 CHANGELOG.md。
许可证
MIT。参见 LICENSE。
作者
由 Garth Elfstrom 创建并维护(@Garthnesss)。 欢迎提交问题和拉取请求。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。