Skip to main content

kwin-mcp

Model Context Protocol server for Linux desktop GUI automation on KDE Plasma 6 Wayland

PyPI version Downloads Python 3.12+ License: MIT CI

A Model Context Protocol (MCP) server that enables AI agents (Claude Code, Cursor, and other MCP clients) to launch, interact with, and observe any Wayland application in a fully isolated virtual KWin session -- without affecting the user's desktop. It also supports live desktop automation by connecting to an existing KWin session (real desktop or container) for collaborative workflows. With 31 MCP tools covering mouse, keyboard, touch, clipboard, accessibility tree inspection, screenshot capture, and window management, kwin-mcp provides everything needed for end-to-end GUI testing and desktop automation on Linux.

Table of Contents

Why kwin-mcp?

  • Isolated sessions -- Each session runs in its own dbus-run-session + kwin_wayland --virtual sandbox. Your host desktop is never affected.
  • Live session support -- Connect to a real KDE Plasma desktop or a KWin instance inside a container (e.g. systemd-nspawn) for collaborative "share my screen" workflows.
  • No screenshots required for interaction -- The AT-SPI2 accessibility tree gives the AI agent structured widget data (roles, names, coordinates, states, available actions), so it can interact with UI elements without relying solely on vision.
  • Zero authorization prompts -- Uses KWin's private EIS (Emulated Input Server) D-Bus interface directly, bypassing the XDG RemoteDesktop portal. No user confirmation dialogs.
  • Works with any Wayland app -- Anything that runs on KDE Plasma 6 Wayland works: Qt, GTK, Electron, and more. Input is injected via the standard libei protocol.
  • Full input coverage -- Mouse, keyboard, multi-touch, and clipboard -- all injected through the isolated session for complete desktop automation.

Use Cases

Automated GUI Testing

Run end-to-end GUI tests for KDE/Qt/GTK applications in headless isolated sessions. kwin-mcp launches each app in its own virtual KWin compositor, interacts via mouse, keyboard, and touch input, then verifies results through screenshots and the accessibility tree -- all without a physical display.

AI-Driven Desktop Automation

Let AI agents like Claude Code autonomously operate desktop applications. The agent reads the accessibility tree to understand the UI, performs actions through 31 MCP tools, and observes the results via screenshots -- creating a complete feedback loop for any Wayland application.

Live Desktop Collaboration

Connect to your real desktop session and let Claude observe and interact with what you see. Use session_connect or pass --default-live-session to make live mode the default. Also supports attaching to KWin running inside containers (e.g. systemd-nspawn) for isolated agent desktops.

Headless GUI Testing in CI/CD

Integrate Linux desktop GUI testing into CI/CD pipelines. kwin-mcp's virtual sessions require no X11 or physical display server, making it suitable for headless environments like GitHub Actions or GitLab CI runners on Linux.

Kiosk and Embedded Device Automation

Automate kiosk interfaces and embedded Linux desktops running KDE Plasma or a bare KWin Wayland compositor. Use session_start for isolated virtual testing of kiosk UIs, or session_connect to attach directly to a live kiosk or embedded device session for real-time automation and diagnostics.

Quick Start

Requires KDE Plasma 6 on Wayland. See System Requirements for details.

1. Install system and build dependencies

uv tool install and uvx always install kwin-mcp into an isolated Python environment, and pip install does the same when run inside a virtual environment. An isolated environment cannot reuse your distribution's python3-gi or python3-dbus packages, so PyGObject, pycairo, and dbus-python are built from source during installation and need a C compiler and development headers. Install the packages from Installing System Dependencies first. On Debian 13 (Trixie):

sudo apt-get install -y --no-install-recommends build-essential pkg-config python3-dev libcairo2-dev libgirepository-2.0-dev libdbus-1-dev

2. Install

# Using uv (recommended)
uv tool install kwin-mcp

# Or using pip
pip install kwin-mcp

3. Configure Claude Code

Add to your project's .mcp.json:

{
  "mcpServers": {
    "kwin-mcp": {
      "command": "uvx",
      "args": ["kwin-mcp"]
    }
  }
}

4. Use it

Ask Claude Code to launch and interact with any GUI application:

Start a KWin session, launch kcalc, and press the buttons to calculate 2 + 3.

Claude Code will autonomously start an isolated session, launch the app, read the accessibility tree to find buttons, click them, and take a screenshot to verify the result.

Configuration

The fastest way to wire kwin-mcp into your editor is to install one of the bundled plugins. Each plugin auto-registers the MCP server and ships the kwin-desktop-automation skill, which teaches the agent which tool to call when (session-mode selection, the observe → act → verify loop, US-QWERTY vs Unicode typing, AT-SPI2 surface-local coordinates, and other platform pitfalls).

Claude Code — install the plugin from the marketplace:

/plugin marketplace add isac322/kwin-mcp
/plugin install kwin-mcp@kwin-mcp

OpenCode — add the npm plugin to your opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["@isac322/kwin-mcp-opencode"]
}

For the full integration guide (manual fallback, customising the skill, troubleshooting), see docs/ai-agent-integration.md.

Claude Code

Add to your project's .mcp.json:

{
  "mcpServers": {
    "kwin-mcp": {
      "command": "uvx",
      "args": ["kwin-mcp"]
    }
  }
}

Or if installed globally:

{
  "mcpServers": {
    "kwin-mcp": {
      "command": "kwin-mcp"
    }
  }
}

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "kwin-mcp": {
      "command": "uvx",
      "args": ["kwin-mcp"]
    }
  }
}

Running Directly

# As an installed script
kwin-mcp

# As a Python module
python -m kwin_mcp

# Interactive CLI (REPL for rapid testing)
kwin-mcp-cli

# Live session mode (default to real desktop instead of virtual)
kwin-mcp --default-live-session
kwin-mcp-cli --default-live-session

Available Tools

Session Management (3 tools)

Tool Parameters Description
session_start app_command? str, screen_width? int (1920), screen_height? int (1080), enable_clipboard? bool (false), keep_screenshots? bool (false), isolate_home? bool (false), keep_home? bool (false), env? dict Start an isolated KWin Wayland session, optionally launching an app. Set enable_clipboard=true to enable clipboard tools (requires wl-clipboard). Set keep_screenshots=true to preserve screenshot files after session_stop. Set isolate_home=true to create a temporary HOME with isolated XDG directories (config, data, cache, state), preventing apps from reading/writing host user settings. Set keep_home=true to preserve the isolated home directory after session_stop. Pass extra environment variables via env.
session_connect dbus_address? str, wayland_display? str, keep_screenshots? bool (false) Connect to an existing KWin session (real desktop or container). Defaults to $DBUS_SESSION_BUS_ADDRESS and $WAYLAND_DISPLAY. Clipboard is always enabled. session_stop only disconnects without killing KWin or pre-existing apps.
session_stop (none) Stop the session and clean up. For virtual sessions: terminates KWin and all apps. For live sessions: disconnects without killing KWin or pre-existing apps.

Observation (3 tools)

Tool Parameters Description
screenshot include_cursor? bool (false) Capture a screenshot of the virtual display (saved as PNG, returns file path)
accessibility_tree app_name? str, max_depth? int (15), role? str Get the AT-SPI2 widget tree with roles, names, states, coordinates, the text content of editors and entries (text='...', capped at 200 characters), and scrollbar/slider positions (value=current/max). Use role to filter to specific element types (e.g. "button", "check box"). Non-matching elements are hidden but their children are still traversed.
find_ui_elements query str, app_name? str, states? list[str] Search for UI elements by name, role, or description (case-insensitive); matches report their text content and scrollbar/slider value when they have one. Optionally filter by AT-SPI2 states (e.g. ["focused"], ["active", "visible"]). query can be empty when filtering by states only.

Mouse Input (6 tools)

Tool Parameters Description
mouse_click x int, y int, button? str ("left"), double? bool, triple? bool, modifiers? list[str], hold_ms? int (0), screenshot_after_ms? list[int] Click at coordinates. Supports left/right/middle, single/double/triple click, modifier keys (e.g. ["ctrl", "shift"]), and long-press via hold_ms.
mouse_move x int, y int, screenshot_after_ms? list[int] Move the cursor (hover) to coordinates without clicking
mouse_scroll x int, y int, delta int, horizontal? bool, discrete? bool, steps? int (1) Scroll at coordinates. delta positive = down/right, negative = up/left. Use discrete=true for wheel ticks, steps to split into smooth increments.
mouse_drag from_x int, from_y int, to_x int, to_y int, button? str ("left"), modifiers? list[str], waypoints? list[[x,y,dwell_ms]], screenshot_after_ms? list[int] Drag from one point to another with smooth interpolation. Supports custom waypoints for complex drag paths.
mouse_button_down x int, y int, button? str ("left") Press a mouse button at coordinates without releasing. Use with mouse_button_up for manual drag control.
mouse_button_up x int, y int, button? str ("left") Release a previously pressed mouse button at coordinates

Keyboard Input (5 tools)

Tool Parameters Description
keyboard_type text str, screenshot_after_ms? list[int] Type a string of text character by character (US QWERTY layout)
keyboard_type_unicode text str, screenshot_after_ms? list[int] Type arbitrary Unicode text (Korean, CJK, etc.) via wtype or clipboard fallback (wl-copy + Ctrl+V). Requires wtype or wl-clipboard installed.
keyboard_key key str, screenshot_after_ms? list[int] Press a key or key combination (e.g., Return, ctrl+c, alt+F4, shift+Tab)
keyboard_key_down key str Press and hold a key without releasing. Useful for holding modifiers across multiple actions (e.g., hold Ctrl while clicking items).
keyboard_key_up key str Release a previously held key

Touch Input (4 tools)

Tool Parameters Description
touch_tap x int, y int, hold_ms? int (0), screenshot_after_ms? list[int] Tap at coordinates. Use hold_ms for long-press gestures.
touch_swipe from_x int, from_y int, to_x int, to_y int, duration_ms? int (300), screenshot_after_ms? list[int] Swipe from one point to another with configurable duration
touch_pinch center_x int, center_y int, start_distance int, end_distance int, duration_ms? int (500), screenshot_after_ms? list[int] Two-finger pinch gesture. end_distance < start_distance = pinch in, end_distance > start_distance = pinch out.
touch_multi_swipe from_x int, from_y int, to_x int, to_y int, fingers? int (3), duration_ms? int (300), screenshot_after_ms? list[int] Multi-finger swipe gesture (2-5 fingers) for system gestures like workspace switching

Clipboard (2 tools)

Tool Parameters Description
clipboard_get (none) Read the current clipboard text content. Requires enable_clipboard=true in session_start and wl-clipboard installed.
clipboard_set text str Set the clipboard text content. Same requirements as clipboard_get.

Window Management (4 tools)

Tool Parameters Description
launch_app command str, env? dict Launch an application inside the running session. Returns PID and log path.
list_windows (none) List all accessible application windows with per-window titles and active/focused state markers via AT-SPI2
focus_window app_name str Activate and raise a window by application name (case-insensitive match), via KWin scripting
window_geometry app_name? str Report window frame and client rectangles in global screen coordinates via KWin scripting. Accessibility rectangles are surface-local, so add the reported client origin before passing them to mouse_click / touch_tap.

UI Polling (1 tool)

Tool Parameters Description
wait_for_element query str, app_name? str, timeout_ms? int (5000), poll_interval_ms? int (200), expected_states? list[str] Poll the accessibility tree until an element matching the query and/or states appears or timeout expires. Use expected_states to wait for state changes (e.g. ["active"], ["checked"]). query can be empty when waiting for state changes only.

Advanced (3 tools)

Tool Parameters Description
dbus_call service str, path str, interface str, method str, args? list[str] Call any D-Bus method in the isolated session. Useful for controlling KWin scripting, app-specific D-Bus APIs, and system services.
read_app_log pid int, last_n_lines? int (50) Read stdout/stderr output of a launched app by PID. Set last_n_lines=0 for all output.
wayland_info filter_protocol? str List Wayland protocols available in the session. Useful for verifying protocol access (e.g., plasma_window_management).

Frame capture: Many action tools accept an optional screenshot_after_ms parameter (e.g., [0, 50, 100, 200, 500]) that captures screenshots at specified delays (in milliseconds) after the action completes. This is useful for observing transient UI states like hover effects, click animations, and menu transitions without extra MCP round-trips. Frame capture uses the fast KWin ScreenShot2 D-Bus interface (~30-70ms per frame).

How It Works

Claude Code / AI Agent
  |
  |  MCP (stdio)
  v
kwin-mcp server  (31 tools)       kwin-mcp-cli (interactive REPL)
  |                                  |
  +--- both delegate to AutomationEngine (core.py) ---+
  |
  |-- session_start (virtual) ---> dbus-run-session
  |                                 |-- at-spi-bus-launcher
  |                                 +-- kwin_wayland --virtual
  |                                       +-- [your app]
  |
  |-- session_connect (live) ----> existing KWin (real desktop / container)
  |
  |-- screenshot ---------------> KWin ScreenShot2 D-Bus (spectacle fallback)
  |
  |-- accessibility_tree -------> AT-SPI2 (via PyGObject)
  |-- find_ui_elements ---------> AT-SPI2 (via PyGObject)
  |-- wait_for_element ----------> AT-SPI2 (polling)
  |
  |-- mouse_* ------------------> KWin EIS D-Bus --> libei
  |-- keyboard_* ---------------> KWin EIS D-Bus --> libei
  |-- touch_* ------------------> KWin EIS D-Bus --> libei
  |    +-- screenshot_after_ms -> KWin ScreenShot2 D-Bus (fast frame capture)
  |
  |-- keyboard_type_unicode ----> wtype / wl-copy + Ctrl+V
  |-- clipboard_* --------------> wl-copy / wl-paste (wl-clipboard)
  |
  |-- launch_app / list_windows / focus_window
  |                                |-- subprocess spawn
  |                                +-- AT-SPI2 (via PyGObject)
  |
  |-- dbus_call -----------------> dbus-send (generic D-Bus)
  |-- read_app_log --------------> log file read
  +-- wayland_info --------------> wayland-info

Triple Isolation (+ Optional Home Isolation)

kwin-mcp provides three layers of isolation from the host desktop:

  1. D-Bus isolation -- dbus-run-session creates a private session bus. The isolated session's services (KWin, AT-SPI2, portals) are invisible to the host.
  2. Display isolation -- kwin_wayland --virtual creates its own Wayland compositor with a virtual framebuffer. No windows appear on the host display.
  3. Input isolation -- Input events are injected through KWin's EIS interface into the isolated compositor only. The host desktop receives no input from kwin-mcp.
  4. Home directory isolation (optional) -- When isolate_home=true is set in session_start, a temporary HOME directory is created with isolated XDG directories (XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_CACHE_HOME, XDG_STATE_HOME). Apps in the session cannot read or modify host user settings (e.g. ~/.config/kdeglobals), improving test reproducibility and safety. XDG_RUNTIME_DIR is intentionally not isolated because the Wayland socket resides there.

Input Injection

Mouse, keyboard, and touch events are injected through KWin's private org.kde.KWin.EIS.RemoteDesktop D-Bus interface. This returns a libei file descriptor that allows low-level input emulation without requiring the XDG RemoteDesktop portal (which would show a user authorization dialog). The connection uses:

  • Absolute pointer positioning for precise coordinate-based interaction
  • evdev keycodes with full US QWERTY mapping for keyboard input
  • Smooth drag interpolation (10+ intermediate steps) for realistic drag operations
  • EIS touch emulation for multi-touch gestures (tap, swipe, pinch, multi-finger swipe)

Screenshot Capture

The normal Wayland capture path tries KWin's org.kde.KWin.ScreenShot2 D-Bus interface first and uses the spectacle CLI as a fallback. Action tools with screenshot_after_ms use the same path for frame bursts, and Pillow converts ScreenShot2's raw ARGB pipe data to PNG. The Docker visual QA suite also has an explicit test-only X11 backend: when KWIN_MCP_X11_SCREENSHOT=1 is set for a server connected to the nested KWin/Xvfb fixture, captures use scrot. Normal virtual and live Wayland sessions do not opt into this backend.

Accessibility Tree

The AT-SPI2 accessibility bus within the isolated session is queried via PyGObject (gi.repository.Atspi). This provides a structured tree of all UI widgets with their roles (button, text field, menu item, etc.), names, states (focused, enabled, visible, etc.), screen coordinates, and available actions (click, toggle, etc.).

System Requirements

Requirement Details
OS Linux with KDE Plasma 6 (Wayland session)
Python 3.12 or later
KWin kwin_wayland with --virtual flag support (KDE Plasma 6.x)
libei Usually bundled with KWin 6.x (EIS input emulation)
spectacle KDE screenshot tool (CLI mode); packaged as kde-spectacle on Debian and Ubuntu
AT-SPI2 at-spi2-core for accessibility tree support
PyGObject GObject introspection Python bindings (built from source by uv/pip; see build prerequisites)
D-Bus dbus-python bindings (built from source by uv/pip; needs libdbus development files)
Build tools C compiler, pkg-config, Python headers, and cairo, GObject Introspection, and libdbus development files

Optional dependencies:

Package Required for
wl-clipboard (wl-copy, wl-paste) clipboard_get, clipboard_set, and keyboard_type_unicode clipboard fallback
wtype keyboard_type_unicode (preferred over clipboard fallback)
wayland-utils (wayland-info) wayland_info tool

Installing System Dependencies

kwin-mcp needs two groups of system packages: runtime packages (KWin, Spectacle, AT-SPI2) and build prerequisites for the Python packages it installs from PyPI.

Build Prerequisites for uv and pip Installs

uv tool install kwin-mcp and uvx kwin-mcp always use an isolated Python environment, and pip install kwin-mcp does too when run inside a virtual environment. An isolated environment cannot see the system gi (PyGObject) or dbus modules installed by your distribution, so uv or pip builds PyGObject, pycairo, and dbus-python from source. These builds need a C compiler, pkg-config, the Python headers, and the cairo, GObject Introspection, and libdbus development files. Without them, installation fails while building those packages.

On Debian 13 (Trixie):

sudo apt-get install -y --no-install-recommends build-essential pkg-config python3-dev libcairo2-dev libgirepository-2.0-dev libdbus-1-dev

For other distributions, follow the "Installing from PyPI with pip" build dependency steps in the PyGObject Getting Started guide, and also install your distribution's libdbus development package (it provides the dbus-1 pkg-config file that dbus-python needs).

Runtime Packages

Debian 13 (Trixie)

Debian packages Spectacle as kde-spectacle; there is no spectacle package. gir1.2-atspi-2.0 provides the AT-SPI2 GObject Introspection typelib that PyGObject loads at runtime.

sudo apt-get install -y --no-install-recommends kwin-wayland kde-spectacle at-spi2-core gir1.2-atspi-2.0

# Optional: for clipboard and Unicode input
sudo apt-get install -y --no-install-recommends wl-clipboard wtype wayland-utils
Arch Linux / Manjaro
sudo pacman -S kwin spectacle at-spi2-core python-gobject dbus-python-common

# Optional: for clipboard and Unicode input
sudo pacman -S wl-clipboard wtype wayland-utils
Fedora (KDE Spin)
sudo dnf install kwin-wayland spectacle at-spi2-core python3-gobject dbus-python

# Optional: for clipboard and Unicode input
sudo dnf install wl-clipboard wtype wayland-utils
openSUSE (KDE)
sudo zypper install kwin6 spectacle at-spi2-core python3-gobject python3-dbus-python

# Optional: for clipboard and Unicode input
sudo zypper install wl-clipboard wtype wayland-utils
Kubuntu / KDE Neon (Plasma 6 releases only)

Use a release that ships KDE Plasma 6 and Python 3.12 or later; older Kubuntu releases with Plasma 5 are not supported. Install the Debian build prerequisites above as well. Ubuntu packages Spectacle as kde-spectacle.

sudo apt install kwin-wayland kde-spectacle at-spi2-core python3-gi gir1.2-atspi-2.0 python3-dbus

# Optional: for clipboard and Unicode input
sudo apt install wl-clipboard wtype wayland-utils

Installation

Install the system and build dependencies before using any method below. The uv installs, pip installs into a virtual environment, and the from-source install build PyGObject, pycairo, and dbus-python from source and fail without them.

uv tool install kwin-mcp

uv also provides uvx, which the .mcp.json examples above use to run kwin-mcp. If the kwin-mcp command is not found after uv tool install, run uv tool update-shell and restart your shell so uv's tool directory is on PATH.

Using pip

pip install kwin-mcp

From source

git clone https://github.com/isac322/kwin-mcp.git
cd kwin-mcp
uv sync
uv run kwin-mcp

Limitations

  • US QWERTY keyboard layout only -- keyboard_type supports US QWERTY only. For non-ASCII text (Korean, CJK, etc.), use keyboard_type_unicode, which requires wtype or wl-clipboard installed.
  • KDE Plasma 6+ required -- Older KDE versions or other Wayland compositors (GNOME, Sway) are not supported.
  • AT-SPI2 availability varies -- Some applications may not fully expose their widget tree via AT-SPI2.
  • Touch input is EIS-emulated -- Touch events are emulated through KWin's EIS interface, not from a real touchscreen device. Most applications handle emulated touch correctly, but some may behave differently from physical touch.
  • Clipboard requires opt-in -- Clipboard tools (clipboard_get, clipboard_set) are disabled by default because wl-copy can hang in isolated sessions. Enable with enable_clipboard=true in session_start, and ensure wl-clipboard is installed.
  • QMenu (native context menus) may not appear in AT-SPI2 -- Qt's AT-SPI2 bridge has incomplete support for popup menus on Wayland. Context menus may not be visible in accessibility_tree or find_ui_elements. Workaround: click by coordinates derived from the parent widget's rectangle plus the client origin from window_geometry.
  • Screen edge triggers ignore EIS pointer events -- Auto-hide panels and layer-shell strips do not react when the pointer reaches a screen edge through EIS. Use dbus_call to invoke KWin scripting or a keyboard shortcut instead of trying to hover the edge.
  • KWin claims multi-finger touch gestures -- Three- and four-finger swipes are consumed by the compositor as global gestures and never reach the application; use fingers=2 when the target is the app itself.
  • AT-SPI2 coordinates are surface-local, not screen-global -- Wayland clients do not know their global screen position (by design). Coordinates returned by find_ui_elements and accessibility_tree are relative to the window's top-left corner, while mouse_click and touch_tap take screen coordinates. Convert them by adding the client origin from window_geometry: clicking a reported rectangle verbatim lands on whatever occupies that screen position instead.

End-to-End Testing

The Docker suite currently collects 99 tests against the packaged application, not an editable source checkout. docker/e2e.Dockerfile builds a wheel, installs it with the locked MCP 1.x dependency set into /opt/kwin-mcp-venv, and runs both AutomationEngine tests and the installed kwin-mcp console entry point. The MCP tests initialize a real client/server session over stdio JSON-RPC.

Run the complete suite from the repository root:

scripts/run-e2e-docker.sh

The runner builds the image for Docker's native architecture, creates artifacts/e2e/<UTC-timestamp>-<pid>/, runs pytest, and prints the artifact path. Additional arguments pass directly to pytest:

scripts/run-e2e-docker.sh -- tests/e2e/test_mcp_protocol.py -v
scripts/run-e2e-docker.sh -- -k "visual or screenshot" -v

Coverage includes:

  • virtual KWin engine tests for session lifecycle, AT-SPI2 observation, window geometry and control, EIS pointer/keyboard/touch input, clipboard, cleanup, and error handling;
  • exact input-schema checks for all 31 registered tools, plus installed-server stdio calls through every MCP wrapper;
  • nested visual tests that start Xvfb and a test-owned KWin compositor inside the container, connect the installed MCP server to it, and verify pixels as well as accessibility state;
  • KCalc before/after pixel transitions and a deterministic GUI probe for mouse hover, cursor inclusion, animation frame bursts, and CJK text (GUI 검증 42) rendered differently from a tofu control (□□);
  • screenshot retention and failure behavior, environment provenance, installed distribution metadata, console entry points, and process/socket cleanup.

The container uses software rendering and needs no --privileged, --cap-add, GPU, or device flags. Its nested Xvfb server is part of the visual fixture; the host does not need an X server. CI runs the same image natively on both architectures:

Architecture GitHub Actions runner
amd64 ubuntu-24.04
arm64 ubuntu-24.04-arm

A completed run retains environment.json, junit.xml, pytest.log, nested-KWin/Xvfb/MCP logs, and visual PNG evidence below its artifact directory. Failed runs also collect Docker inspect, container log, and process-list diagnostics.

One legacy success test for ScreenShot2 on KWin's exact --virtual backend remains intentionally skipped because that backend does not return capture data in this container. Error propagation for that path is tested at both engine and MCP stdio levels; screenshot success, cursor pixels, and frame bursts are tested through the explicit nested X11/scrot visual mode. See docker/README.md for the process topology, complete test-file inventory, evidence layout, and targeted commands.

Contributing

Contributions are welcome! See CONTRIBUTING.md for development setup, code style guidelines, and the pull request process.

git clone https://github.com/isac322/kwin-mcp.git
cd kwin-mcp
uv sync
uv run ruff check src/
uv run ruff format --check src/
uv run ty check src/

License

MIT

Metadata

Release files for kwin-mcp 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kwin-mcp 0.8.0
File Size Uploaded
kwin_mcp-0.8.0.tar.gz 62.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for kwin-mcp 0.8.0
File Interpreter ABI Platform
kwin_mcp-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 120.8 kB

Release files / kwin_mcp-0.8.0.tar.gz

Download URL kwin_mcp-0.8.0.tar.gz
Size 62.9 kB
Tags Source
SHA-256 checksum
How to use checksums
9f454fa2ed5c32e8bd5e80593dba5957e41025b675d50f180b45740f099753c4
BLAKE2b-256 checksum
How to use checksums
ad10cc2d27d2ea428cb028f2c1f2ea9d341bb65758acf16d4184a3fad9b35fdb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / kwin_mcp-0.8.0-py3-none-any.whl

Download URL kwin_mcp-0.8.0-py3-none-any.whl
Size 57.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a95a43860972acad49f5f65815f7ecddf0a4574573ce67da46a0e301570bec62
BLAKE2b-256 checksum
How to use checksums
4155d8c48573c82abdfda70d69524ce4e3314694a0410564bbf7220f667fdc1b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

This release

0.8.0 This release

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page