Skip to main content
Glama
kde-desktop-mcp

kde-desktop-mcp

by marvin1099

KDE Desktop Automation

A Python toolkit, CLI, and MCP server for inspecting and automating KDE Plasma. It defaults to a separate, private KWin session; access to the live desktop must be selected explicitly.

Codeberg (primary) · GitHub mirror

Prototype: support depends on the installed KDE/Wayland components and system utilities. Input is best-effort and does not prove an application acted on it. A private session isolates its compositor and home directory, but is not a security sandbox and runs as your Unix user.

What it can do

  • Create private virtual desktops and launch applications inside them.

  • Observe windows, displays, pointer/focus context, and optional screenshots.

  • Find, inspect, activate, minimize/restore, and place windows; send guarded keyboard/text input and coordinate clicks/drags.

  • Inspect and control MPRIS media players.

  • Inspect and change live PipeWire audio settings (live desktop only).

  • Expose the same target-aware operations through an stdio MCP server.

Capabilities vary by target and installed tools. There is no accessibility tree, OCR-based control discovery, or app-specific action API yet. See the usage guide for exact commands and limitations.

Related MCP server: quickshell-mcp

Requirements

  • Linux with KDE Plasma on Wayland; private sessions use KWin's virtual-output backend. Exact support depends on the installed Plasma/KWin version.

  • Python 3.12 or newer and uv to install from a checkout.

  • Optional system utilities provide additional features. Run kde-desktop doctor to see which are available; per-target capabilities reports what can be used.

Quick start

git clone https://codeberg.org/marvin1099/kde-desktop-automation.git
cd kde-desktop-automation
uv sync
uv run kde-desktop doctor
uv run kde-desktop session create --name agent --width 1280 --height 800 --json

Copy the session_id from the result and use it for commands in that private desktop:

SESSION_ID='agent-...'
uv run kde-desktop --session "$SESSION_ID" observe --json
uv run kde-desktop session launch "$SESSION_ID" -- kate --new /tmp/agent-note.txt
uv run kde-desktop --session "$SESSION_ID" screenshot --output /tmp/agent.png --json
uv run kde-desktop session stop "$SESSION_ID"

To deliberately target the real desktop, pass --session user-desktop on each command. Private sessions cannot see host windows or media players. Do not run untrusted applications in them: they are not an OS-level sandbox.

MCP server

After uv sync, configure your MCP client to launch kde-desktop-mcp from this checkout:

{
  "mcpServers": {
    "kde-desktop": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/absolute/path/to/kde-desktop-automation",
        "kde-desktop-mcp"
      ]
    }
  }
}

Every MCP desktop call requires an explicit session value: a managed session ID or user-desktop when intentionally using the live desktop.

Safety essentials

  • A missing or stopped private session never falls back to the live desktop.

  • Window-targeted input requires that window to already be active; it is guarded by focus, not atomically routed to the window.

  • Global clicks and drags use logical desktop coordinates, move the pointer, and may change focus. A successful input receipt is not proof of an app effect; inspect again and verify the result independently.

  • Window placement is a KWin frame-geometry request. KWin may constrain it; the tool reads back and reports the effective geometry.

  • Audio controls are live-desktop-only. Private sessions do not provide an isolated audio server.

Guides

Development

uv sync --all-groups
uv run pytest -q
uv run ruff check .
uv run ruff format --check .
uv run mypy src
uv build

The private-KWin tests are opt-in. The Dolphin-to-Kate drag test additionally requires Dolphin, Kate, kdotool, and wl-paste:

KDE_DESKTOP_RUN_KWIN_INTEGRATION=1 \
KDE_DESKTOP_RUN_KWIN_DND_INTEGRATION=1 \
uv run pytest tests/test_kwin_integration.py::test_private_dolphin_drag_and_drop_opens_file_in_kate -q

License

Licensed under the GNU Affero General Public License v3.0 only.

Available Tools

32 tools
kde_audio_listA
Read-only

List live PipeWire outputs, inputs, defaults, volume/mute, and active output streams. Requires session='user-desktop'.

Inputs: session (required).

kde_audio_route_streamA
Destructive

Move one live output stream to a sink after checking its exact stream ID and application name; requires session='user-desktop'.

Inputs: session (required), sink_name (required), stream_id (required), application_name (required), +1 more.

kde_audio_set_defaultC
Destructive

Set and verify the live default output sink or input source.

Inputs: session (required), direction (required), device_name (required).

kde_audio_set_muteC
Destructive

Explicitly mute or unmute one live sink/source and verify the result.

Inputs: muted (required), session (required), direction (required), device_name (required).

kde_audio_set_volumeB
Destructive

Set and verify a live sink/source volume from 0 through 100 percent.

Inputs: session (required), direction (required), device_name (required), volume_percent (required).

kde_capabilitiesB
Read-only

Report supported operations and known limitations for a selected target.

Inputs: session (required).

kde_desktop_observeB
Read-only

Return a fresh desktop snapshot with windows, logical display geometry, pointer/focus context, and screenshot metadata/image content when Spectacle is available.

Inputs: session (required).

kde_display_listA
Read-only

List logical display geometry in the selected target session.

Inputs: session (required).

kde_input_clickB
Destructive

Click an already-active target window at normalized window coordinates [0, 1].

Inputs: x (required), y (required), session (required), window_id (required), +1 more.

kde_input_click_atA
Destructive

Click a global logical-desktop pixel coordinate, not a window-relative point. The point must lie on a listed display; this may move the pointer or change focus.

Inputs: x (required), y (required), session (required), button.

kde_input_dragB
Destructive

Drag between global logical-desktop pixel coordinates. Every interpolated point must lie on a listed display; steps are limited to 1–64. Duration and start/end pauses are bounded to make real UI drag-and-drop gestures deliverable without changing their global-coordinate semantics. This can move the pointer or change the active window and is not bound to a particular window.

Inputs: end_x (required), end_y (required), session (required), start_x (required), +6 more.

kde_input_keyB
Destructive

Send a key chord to an already-active target window; no implicit activation.

Inputs: chord (required), session (required), window_id (required).

kde_input_typeA
Destructive

Type literal text into an already-active target window; no implicit activation.

Inputs: text (required), session (required), window_id (required).

kde_media_controlA
Destructive

Submit play, pause, play-pause, stop, next, previous, or a relative seek to one explicitly selected MPRIS player. For seek, seconds is required, must be non-zero, and is an offset (negative rewinds). Use kde_media_seek_to when you need an absolute playback position.

Inputs: action (required), player (required), session (required), seconds.

kde_media_inspectA
Read-only

Read playback status, title/artist/album, current position, and duration from one explicitly selected MPRIS player.

Inputs: player (required), session (required).

kde_media_listB
Read-only

List MPRIS players registered on the selected session's D-Bus.

Inputs: session (required).

kde_media_seek_toA
Destructive

Seek one exact listed MPRIS player to an absolute position from 0 through 86400 seconds. The request is not verified; inspect the player afterward.

Inputs: player (required), session (required), position_seconds (required).

kde_pointer_positionA
Read-only

Read the selected session's current pointer position without moving it.

Inputs: session (required).

kde_screenshotB
Read-only

Capture the selected desktop and return the PNG as an MCP image result.

Inputs: session (required), output, overwrite.

kde_session_createB

Create an isolated private KWin session; never creates or attaches to the live desktop.

Inputs: name, width, height, make_default.

kde_session_launchA

Launch an executable with argv inside a managed private KWin session; no shell is used.

Inputs: argv (required), session_id (required).

kde_session_listA
Read-only

List managed private KWin sessions and identify the private default.

Inputs: no named parameters.

kde_session_showB
Read-only

Inspect a managed private KWin session by ID.

Inputs: session_id (required).

kde_session_stopA
Destructive

Stop a managed private session and its tracked applications. Does not affect the live desktop. On shared servers, use only through the coordinator authorized to manage that session.

Inputs: session_id (required).

kde_session_useA
Idempotent

Set the persisted private default for CLI clients that omit --session. This does not change MCP desktop calls, which require an explicit session.

Inputs: session_id (required).

kde_window_activateB

Activate a selected window. user-desktop activation changes real user focus.

Inputs: session (required), window_id (required).

kde_window_findA
Read-only

Find exactly one window by app ID and/or title substring; ambiguity returns candidates.

Inputs: session (required), title, app_id.

kde_window_inspectA
Read-only

Inspect one window using a UUID from the same selected session.

Inputs: session (required), window_id (required).

kde_window_listA
Read-only

List windows in a private session or explicitly selected user-desktop.

Inputs: session (required).

kde_window_set_geometryA
DestructiveIdempotent

Set an explicit KWin frame rectangle in logical desktop pixels and verify its effective geometry. This is window placement, not a simulated mouse drag.

Inputs: x (required), y (required), width (required), height (required), +2 more.

kde_window_set_minimizedA
DestructiveIdempotent

Set a window's minimized state explicitly and verify it. Setting false restores it; live changes may change user focus.

Inputs: session (required), minimized (required), window_id (required).

kde_window_waitB
Read-only

Wait up to 60 seconds for a unique matching window, optionally until KWin reports fullscreen or its geometry fills a logical display.

Inputs: session (required), title, app_id, timeout, +2 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 32 tools

    Disambiguation4/5

    Most tools are clearly partitioned by domain and action (session_*, window_*, input_*, audio_*, media_*), and descriptions actively disambiguate near-pairs like click vs click_at (window-relative vs global) and media_control vs media_seek_to (relative vs absolute). Minor residual overlap remains: kde_screenshot vs kde_desktop_observe (which also returns screenshot content), and kde_window_find/wait/list/inspect all target the same resource from different angles.

    Naming Consistency5/5

    Every tool follows the same kde_<domain>_<verb>_<noun> snake_case pattern (kde_session_create, kde_audio_set_volume, kde_media_seek_to, kde_window_set_geometry). The domain prefix groups tools predictably and no mixed conventions appear.

    Tool Count3/5

    32 tools is heavy for a single server, though the count is spread across seven genuinely distinct subsystems (sessions, windows, input, audio, media, display, screenshot) rather than being padding. It sits at the edge where an agent must scan a large surface to pick a tool, but each tool still maps to a real operation.

    Completeness3/5

    Coverage is broad and lifecycle-ish for sessions, audio, media, and window placement/state, but there are notable desktop-automation gaps: no window close/kill tool and no mouse scroll/wheel input, both of which are core to GUI automation and would force workarounds. Session management also lacks an explicit delete (only stop/launch).

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      A
      maintenance
      Enables 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.
      159 PyPI
      78
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables driving a Quickshell QML app inside a headless compositor, with tools to screenshot windows, inspect their object trees, and read or write QML state.
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to automate and observe Linux desktop GUIs on KDE Plasma 6 Wayland through isolated virtual sessions or live desktop connections, providing 30 tools for input, clipboard, accessibility tree inspection, screenshots, and window management.
      2
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to inspect, automate, and test desktop GUI applications on Wayland through window/desktop streaming, semantic AT-SPI accessibility tree inspection, and boundary-clamped mouse, keyboard, drag, and scroll input injection. It also manages application process lifecycle, captures window frames, and registers Python GUI scripts as native Linux desktop launchers.
      25 PyPI
      1
      MIT