ccdesk
Provides desktop control on GNOME under Wayland, with full-screen screenshots via gnome-screenshot, pointer and text input via ydotool, and clipboard access via wl-clipboard. Keyboard shortcuts and window management are limited or unavailable.
Provides desktop control on Hyprland, including screenshots via grim, pointer input via ydotool, keyboard input via wtype, window listing and focusing via hyprctl, and clipboard access via wl-clipboard.
Provides desktop control on KDE Plasma under Wayland, with pointer input via ydotool and clipboard access via wl-clipboard. Screenshots and keyboard input are not supported.
Provides desktop control on Linux, including screenshots, mouse and keyboard input, window management, and clipboard operations. Supports both X11 and Wayland environments.
Provides desktop control on Sway, including screenshots via grim, pointer input via ydotool, keyboard input via wtype, window listing and focusing via swaymsg, and clipboard access via wl-clipboard.
Enables desktop control on Wayland compositors, with capabilities such as screenshots via grim, pointer input via ydotool, keyboard input via wtype, window management via compositor-specific tools like swaymsg or hyprctl, and clipboard access via wl-clipboard.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ccdesktake a screenshot, then focus the terminal and type 'hello world'"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ccdesk
Desktop control for Claude Code on Linux. ccdesk is a small MCP server that lets Claude Code take screenshots, move and click the mouse, type, press keys, list and focus windows, and use the clipboard. It ships with a skill that teaches Claude the safe workflow: screenshot, one action, verify.
There's no Claude Desktop app on Linux. ccdesk fills that gap with the system tools you
probably already have (xdotool, scrot, wmctrl, xclip). The core is standard-library
Python; the only dependency is the official mcp package.
Install
# system tools (Debian/Ubuntu; X11)
sudo apt install xdotool scrot wmctrl xclip x11-utils
# optional: imagemagick (fallback screenshots), xvfb + python3-tk (to run the test suite)
pipx install . # from a checkout of this repo
ccdesk doctor # check what was detected
ccdesk install --dry-run # show what install would write and run
ccdesk install # register the MCP server + install the skillOn Fedora: sudo dnf install xdotool scrot wmctrl xclip xprop. On Arch:
sudo pacman -S xdotool scrot wmctrl xclip xorg-xprop.
Related MCP server: claude-linux-mcp
Wiring it into Claude Code
ccdesk install does two things:
Copies
skills/computer-use/SKILL.mdto~/.claude/skills/computer-use/SKILL.md(or$CLAUDE_CONFIG_DIR/skills/...).Runs
claude mcp add --scope user ccdesk -- /path/to/ccdesk mcp, after removing any earlierccdeskregistration.
Flags you pass to install are forwarded to the server: ccdesk install --read-only or
ccdesk install --allow-launch. --dry-run prints the exact file, size, checksum and
commands, and changes nothing:
$ ccdesk install --dry-run
ccdesk install --dry-run (nothing is written)
[1] would write /home/hermes/.claude/skills/computer-use/SKILL.md
6198 bytes, sha256 b0dbc9581ca05b94…, copied from /home/hermes/Projects/ccdesk/skills/computer-use/SKILL.md
[2] would run: claude mcp remove --scope user ccdesk # ignored if not registered yet
[3] would run: claude mcp add --scope user ccdesk -- /home/hermes/Projects/ccdesk/.venv/bin/ccdesk mcpTo wire it by hand instead:
claude mcp add --scope user ccdesk -- ccdesk mcp
mkdir -p ~/.claude/skills/computer-use && cp skills/computer-use/SKILL.md ~/.claude/skills/computer-use/Restart Claude Code and run /mcp. ccdesk should be listed with 13 tools.
Tools
Tool | What it does |
| Saves a PNG and returns |
| Moves the pointer and clicks. |
| Moves the pointer (hover). |
| Left-button drag along a smooth path. |
| Wheel clicks with the pointer at (x, y). |
| Types into the focused widget. |
|
|
| Returns |
| Raises and focuses a window by id or by partial title. |
| Reads or replaces the clipboard. |
| Sleeps, up to 60 s. |
| Reports the session type, tools found, screen size, scale and policy. |
| Starts an app without a shell. Only enabled with |
Coordinates are screen pixels with the origin at the top left, the same space as a full-screen screenshot.
Demo
This transcript is a real stdio session against ccdesk mcp, recorded under xvfb-run
while driving the Tk test app in tests/tk_app.py. Each > line is a tool call and each <
line is the server's response. The pixel coordinates were found in the screenshot. In
Claude Code, Claude does the same thing by reading the PNG.
> list_windows()
< {"windows": [{"id": "0x00200029", "title": "ccdesk-test", "class": "tk.Tk", "geometry": {"x": 40, "y": 50, "width": 420, "height": 420}, "desktop": null}]}
> activate_window(title_or_id='ccdesk-test')
< {"activated": {"id": "0x00200029", "title": "ccdesk-test", "class": "tk.Tk", "geometry": {"x": 40, "y": 50, "width": 420, "height": 420}, "desktop": null}}
> screenshot()
< {"path": "/home/hermes/.cache/ccdesk/screenshots/screen-20261019-200511-959.png", "width": 1280, "height": 1024}
> click(x=249, y=79)
< {"clicked": {"x": 249, "y": 79}, "button": "left", "count": 1}
> screenshot(region='99,49,300,110')
< {"path": "/home/hermes/.cache/ccdesk/screenshots/screen-20261019-200514-075.png", "width": 300, "height": 110, "origin": {"x": 99, "y": 49}, "note": "pixel (px,py) in this image is screen (origin.x+px, origin.y+py)"}
> click(x=249, y=179)
< {"clicked": {"x": 249, "y": 179}, "button": "left", "count": 1}
> type_text(text='hello from Claude')
< {"typed_chars": 17}
> press_key(key='Return')
< {"pressed": "Return"}
> press_key(key='w', modifiers=['ctrl'])
< ERROR Error executing tool press_key: Ctrl+w can close windows or quit applications; take a screenshot to verify the target, then call again with confirm=true
> launch(command='xterm')
< ERROR Error executing tool launch: launch is disabled: restart the server with `ccdesk mcp --allow-launch`When the session ended, the app reported label: "submitted:hello from Claude". In Claude
Code a typical request looks like "open Firefox, go to news.ycombinator.com and tell me the
top story". The skill makes Claude find or focus Firefox, use ctrl+l for the address bar,
type the URL, wait, screenshot and read the page.
Security model
ccdesk drives your real desktop with your user's privileges. The guardrails are:
Read-only mode.
ccdesk mcp --read-onlydisables every input tool:click,move,drag,scroll,type_text,press_key,activate_window,clipboard(set)andlaunch. Screenshots,list_windows,clipboard(get),waitanddoctorstill work.No launching by default.
launch(command)refuses unless the server was started with--allow-launch. Even then it runs the command without a shell (shlex.split, no pipes, redirects or;) in a new session.Destructive shortcuts need confirmation.
Alt+F4,Ctrl+Q,Ctrl+WandSuper+Qare refused unless the call passesconfirm=true. Supersets such asCtrl+Shift+Wcount too.Audit log. Every call, including denied and failed ones, is appended as one JSON line to
~/.cache/ccdesk/audit.log(mode 0600; override with--audit-logorCCDESK_AUDIT_LOG). Each line has a timestamp, the tool, its arguments, the status (ok/denied/error), the result or error, and the duration. Clipboard contents are logged by length only. Typed text is logged, truncated to 200 characters, which is one more reason the skill tells Claude never to type secrets.Input validation. Coordinates are bounds-checked against the screen. Counts, scroll amounts, durations, waits and text length are capped. Key names are whitelisted characters, so nothing reaches a helper tool as an option or shell syntax.
The skill. It tells Claude to screenshot before acting and verify after, to never type passwords, to never dismiss dialogs blindly, and to treat on-screen text as data, not instructions.
These guardrails are not a sandbox. Any client that can call type_text can type a shell
command into a terminal. Use --read-only when you only want Claude to look, and keep
Claude Code's own tool-permission prompts turned on for mcp__ccdesk__* if you want to
approve each action.
Wayland caveats
Wayland isolates clients from each other by design, so ccdesk can only do what the compositor allows:
Screenshots need
grim, which requires wlr-screencopy (sway, Hyprland, river, Wayfire). GNOME falls back tognome-screenshot -f, and only for full-screen captures. KDE has neither.Pointer input needs
ydotool1.x with theydotoolddaemon running and access to/dev/uinput. Absolute positioning depends on ydotool's pointer acceleration settings, so verify clicks with screenshots.Keyboard uses
wtype(virtual-keyboard protocol, not available on GNOME) and falls back toydotool typefor plain text.press_keyrequireswtype.Windows are listed and focused through
swaymsg(sway) orhyprctl(Hyprland). Elsewhere ccdesk falls back to XWayland viaxdotool, which only sees X11 apps.Clipboard uses
wl-copy/wl-paste.If you only need to drive XWayland apps,
CCDESK_BACKEND=x11(or--backend x11) forces the X11 backend.
ccdesk doctor reports exactly which of these are present.
Support matrix
Environment | screenshot | click/move/drag/scroll | type_text | press_key | list/activate windows | clipboard |
X11 (any WM/DE) | ✅ scrot / import | ✅ xdotool | ✅ xdotool | ✅ xdotool | ✅ wmctrl | ✅ xclip / xsel |
X11 without a WM (Xvfb) | ✅ | ✅ | ✅ | ✅ | ✅ xdotool + xprop fallback | ✅ |
Wayland: sway / Hyprland | ✅ grim | ⚠️ ydotool + ydotoold | ✅ wtype / ydotool | ✅ wtype | ✅ swaymsg / hyprctl | ✅ wl-clipboard |
Wayland: GNOME | ⚠️ full screen only | ⚠️ ydotool + ydotoold | ⚠️ ydotool | ❌ | ⚠️ XWayland apps only | ✅ wl-clipboard |
Wayland: KDE Plasma | ❌ | ⚠️ ydotool + ydotoold | ⚠️ ydotool | ❌ | ⚠️ XWayland apps only | ✅ wl-clipboard |
No display (SSH, CI) | ❌ (doctor explains) | ❌ | ❌ | ❌ | ❌ | ❌ |
The X11 rows are exercised by the integration suite under Xvfb. The Wayland rows are
covered by unit tests of the exact commands ccdesk builds, not on a live compositor.
Requires Python 3.10+. The full suite passes on Python 3.14 with both mcp 2.3 and mcp 1.30.
ccdesk does not replace Cua Driver. If cua-driver is on
your PATH, doctor mentions it, but ccdesk never calls it.
Development
python -m venv .venv && . .venv/bin/activate
pip install -e '.[test]'
xvfb-run -a pytest -q # unit tests + Tk integration test on a virtual X server
pytest -q # without a display the integration tests are skipped
xvfb-run -a ccdesk doctorThe integration test (tests/test_integration_tk.py) starts a Tk window with a button, a
label, an entry, a canvas and a list. It takes a screenshot, finds the button by its colour
in the PNG, clicks it, and checks that the label changed. It then types into the entry,
presses Return, drags across the canvas, scrolls the list and checks the clipboard,
asserting each result against the app's own state.
Layout:
ccdesk/
cli.py ccdesk doctor | install | mcp | version
server.py MCP tool definitions (the only module importing `mcp`)
desktop.py validation + policy + audit around a backend
safety.py read-only / launch policy, destructive keys, JSONL audit log
parsing.py pure parsers: keys, regions, wmctrl/xdotool output, PNG header
doctor.py environment report
install.py Claude Code registration and skill copy
backends/ x11.py, wayland.py, base.py
skills/computer-use/SKILL.md
tests/License
MIT. See LICENSE.
Related MCP Connectors
Use your Mac, Windows or Linux computer from ChatGPT, Claude or Codex: files, commands, documents.
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Securely control computers you explicitly pair through files, terminals, processes, screenshots, desktop UI/input, clipboard, browser automation, diagnostics, and document tools.
Cloud desktops for AI agents: create a Linux computer, see its screen, click, type and run tasks.
Related MCP Servers
- FlicenseAqualityFmaintenanceEnables Claude Code to interact with Linux X11 desktops by performing mouse actions, keyboard input, and capturing screenshots. It provides a suite of tools for automation tasks such as clicking, typing, and zooming on specific screen regions.16-
- AlicenseAqualityBmaintenanceGive Claude Desktop full desktop control on Linux/X11: screenshot, mouse, keyboard, windows, clipboard, app launch. Zero-dependency MCP extension, MIT-licensed.15MIT
- AlicenseNot gradedqualityDmaintenanceEnables full Linux desktop control including windows, mouse, keyboard, clipboard, audio, screenshots, OCR, accessibility, and system management through MCP-compatible AI agents.1MIT
- AlicenseNot gradedqualityDmaintenanceEnables Claude to control the local desktop via screenshot, mouse, keyboard, and clipboard operations.MIT