ElfdeckAI
๐ฎ ElfdeckAI
Your AI can see the game. Now it can hold the controller.
ElfdeckAI gives an LLM agent hands on real hardware. Two tiny daemons turn one-line commands โ from a shell, a script, or native MCP tool calls โ into real keyboard and gamepad input on a Linux machine:
โจ๏ธ ElfKey โ a virtual keyboard on
/dev/uinput๐น๏ธ ElfPad โ a virtual gamepad (Xbox-class: buttons, analog triggers, two sticks, D-pad)
Every "LLM plays Pokรฉmon" project you've seen plugs into an emulator's API. ElfdeckAI presses buttons on a real device โ proven live when an LLM played Pokรฉmon FireRed on a physical Steam Deck end-to-end: full intro, starter picked, first rival battle won, game saved. No emulator, no RAM reading, no capture card โ just a stream for eyes and these daemons for hands. (How it drives)
โก Quickstart (60 seconds)
git clone https://github.com/Garthnesss/ElfdeckAI && cd ElfdeckAI
python3 elfkey.py & # virtual keyboard
python3 elfpad.py & # virtual gamepad
echo "key x 150" > /tmp/elfkey.fifo # tap X
echo "press a" > /tmp/elfpad.fifo # tap A
echo "stick left 60 0" > /tmp/elfpad.fifo # push the left stick
grep -E "ElfKey|ElfPad" /proc/bus/input/devices # they're really thereThat's the whole install. Two single-file Python programs, standard
library only โ nothing to pip, nothing to build. State lives in /tmp;
reboot and it's gone.
Steam Deck? You're already done โ
/dev/uinputis user-writable there out of the box. On other Linux machines, install the included udev rule once (see Install).
Related MCP server: dual-wield-mcp
๐ค Give it to your agent (MCP)
elfdeckai_mcp.py is a zero-dependency Model Context
Protocol server that exposes both
devices as native tools โ key_tap, key_down, pad_press, pad_stick,
pad_trigger, pad_reset, โฆ โ for Claude, Hermes, or any MCP client:
{"mcpServers": {"elfdeckai": {
"command": "python3", "args": ["/path/to/ElfdeckAI/elfdeckai_mcp.py"]}}}Start the daemons, add that to your client's config, and your agent can press buttons the same way it calls any other tool. Every call is validated by the daemons' own input contract before it touches a FIFO, and a stopped daemon fails the call cleanly instead of hanging your agent.
๐๏ธ Commands
ElfKey โ /tmp/elfkey.fifo
Command | Effect |
| tap a key (default 120 ms) |
| hold / release |
| release everything and exit |
Keys: aโz, 0โ9, arrows, enter, esc, space, tab, shift,
rshift, ctrl, alt, punctuation, f1โf10, home, end, insert,
delete, โฆ (full table in the source).
ElfPad โ /tmp/elfpad.fifo
Command | Effect |
| tap a button โ or a D-pad direction |
| hold / release |
| analog stick, โ100..100 % per axis; |
| analog trigger; |
| sticks, triggers, D-pad to neutral |
| release everything |
| release everything and exit |
Buttons: a b x y lb rb l2 r2 select start guide l3 r3. ElfPad presents
as an Xbox-360-class pad, so SDL, Steam Input and RetroArch map it the
standard way with zero configuration.
๐ก๏ธ Built for callers that hallucinate
Letting a language model press buttons is safe only if the keyboard itself can't be talked into a bad state. So:
Bad input never kills the daemon. Every line passes a strict parser; malformed commands are logged and refused. (
key x abcandkey x 999999999were real crash/wedge bugs in the first version โ the tests now pin them shut.)Holds are bounded. A tap is at most 5 s. Longer holds use
down/up, which the caller controls.Nothing gets stuck. Timed moves restore in a
finallyblock; held inputs are tracked; onquit, SIGTERM or SIGINT, everything is released and recentered before the device is destroyed.The FIFO is owner-only (0600). Only your user can inject input.
๐ค Why notโฆ?
Approach | Why it falls short |
Emulator APIs (PyBoy, mGBA scripting) | Only exists inside an emulator. Your Deck is not an emulator. |
Sending keys through Moonlight/streaming | Clicks get forwarded; synthetic keyboard events don't (verified). |
xdotool / desktop automation | Can't reach native Wayland clients. |
KVM gadget / controller-spoofing hardware | Works, but it's extra hardware on your desk doing what 200 lines of Python do on the device itself. |
Install
Requirements: Linux with /dev/uinput, Python 3.8+. Nothing else.
Anywhere /dev/uinput isn't user-writable, install the udev rule once:
sudo cp 99-elfdeckai-uinput.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm triggerRun persistently as user services (expects the repo at ~/elfdeckai/):
cp systemd/*.service ~/.config/systemd/user/
systemctl --user enable --now elfkey.service elfpad.serviceTests
python3 -m pytest # 91 tests: both input contracts, device behaviour
# against a fake uinput, and the MCP server spoken
# to over real JSON-RPCRoadmap
ElfMouse โ relative pointer + buttons, completing the set.
One combined daemon (keyboard + pad + mouse in a single process).
A
pip installable package once the FIFO/MCP interfaces settle.
License
MIT โ see LICENSE. Steal it, ship it, teach your agent to speedrun something.
Author
Created and maintained by Garth Elfstrom (@Garthnesss). Issues and PRs welcome on the repo.
This server cannot be deployed
Maintenance
Related MCP Connectors
Cloud desktops for AI agents: create a Linux computer, see its screen, click, type and run tasks.
9 remote MCP servers on Cloudflare Workers for AI agents. Free tier + Pro API keys.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal Eโฆ
No-KYC VPS + per-second code sandboxes AI agents run over MCP โ 75 tools, SDK, pay BTC/XMR/USDC/USDT
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceLinux desktop HAL for AI agents. One daemon, one socket, every desktop action. GNOME, KDE, Hyprland, X11. Ships in one command.30MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for controlling Linux desktops over Wayland, enabling AI agents to perform mouse, keyboard, window, and screenshot operations on Fedora KDE Plasma.AGPL 3.0
- AlicenseNot gradedqualityAmaintenanceEnables controlling your own Linux desktop machines from any MCP-capable LLM client, with opt-in agent capabilities for shell, filesystem, processes, screenshots, system info, and input injection.1MIT
- AlicenseNot gradedqualityCmaintenanceA Windows-only local MCP server that lets Codex/ChatGPT agents control the keyboard, operate foreground windows, and send input to applications and games running with administrator privileges.MIT