kwin-mcp is an MCP (Model Context Protocol) server for Linux desktop GUI automation on KDE Plasma 6 Wayland. Purpose: Enable AI agents (Claude Code and other MCP clients) to launch, interact with, and observe any Wayland application — either in a fully isolated virtual KWin session for reproducible GUI testing, or by connecting to a live KDE Plasma desktop (real session or container) for collaborative desktop automation workflows.
- Package Manager:
uv(Astral). Always use uv instead of pip/poetry. - Lint + Format:
ruff(Astral). Config inpyproject.tomlunder[tool.ruff]. - Type Check:
ty(Astral). Config inpyproject.tomlunder[tool.ty]. - Build:
uv build(uv_build backend)
uv sync # Install/sync dependencies
uv add <pkg> # Add dependency
uv add --dev <pkg> # Add dev dependency
uv run ruff check . # Lint
uv run ruff format . # Format
uv run ty check # Type check
uv run python -m kwin_mcp # Run server- Python 3.12+
- ruff rules: E, F, W, I, N, UP, B, A, SIM, TCH, RUF
- Line length: 100
- Quotes: double quote
- Type hints required
- All documents (.md files), code comments, and docstrings must be written in English
See ROADMAP.md. Key modules:
core.py: AutomationEngine — MCP-independent automation logic (session, input, screenshot, a11y)server.py: Thin MCP wrappers delegating to AutomationEnginecli.py: Interactive REPL + pipe mode viacmd.Cmd(kwin-mcp-clientry point)session.py: Virtual sessions (dbus-run-session + kwin_wayland --virtual) and live session attachment (session_connect to real desktop or container)screenshot.py: KWin ScreenShot2 D-Bus (screenshots)accessibility.py: AT-SPI2 (widget tree)input.py: KWin EIS D-Bus + libei (input injection)
- Read
ROADMAP.mdto understand current progress - Start from the first incomplete item in the next milestone
- After code changes, run
uv run ruff check .+uv run ruff format .+uv run ty check - Update ROADMAP.md checklist when a milestone item is completed
- Verify with CLI, not MCP tools: After modifying any kwin-mcp code, verify via the CLI (
uv run python -m kwin_mcp.cli), NOT the MCP server tools. The MCP server process is already running with the old code loaded in memory — calling MCP tools after editing source files will NOT reflect the changes. Use the CLI to launch a session and test the modified functionality. Usekeep_screenshots=trueinsession_startto preserve screenshot files aftersession_stop(they are deleted by default). Files in/tmp/kwin-mcp-screenshots-*must be cleaned up manually when this option is used. - Invoke docs-seo agent after relevant file changes: After modifying any of the trigger files below, invoke the
@docs-seoagent to evaluate whether documentation is stale. A no-op conclusion is acceptable if nothing needs updating.
| Changed File | Trigger Label | docs-seo Action |
|---|---|---|
src/kwin_mcp/server.py |
tool-registration, code-general | Check tool count, README tool tables, CONTRIBUTING structure |
src/kwin_mcp/session.py |
session-api | Check README arch diagram, CONTRIBUTING session docs |
src/kwin_mcp/core.py |
engine-api, code-general | Check README arch description, CONTRIBUTING structure |
src/kwin_mcp/*.py (any) |
code-general | Check concrete numbers, CONTRIBUTING file listing |
pyproject.toml |
package-metadata | Sync keywords with .claude/positioning.yml; check CLAUDE.md keyword tiers |
CHANGELOG.md |
changelog-update | Sync docs-seo.md positioning; add new search intents |
README.md |
readme-update | Sync docs-seo.md positioning; update CLAUDE.md keyword tiers |
ROADMAP.md |
roadmap-update | Add new long-tail keywords; update CONTRIBUTING.md if milestone adds contributor workflow |
.claude/positioning.yml |
manifest-update | Full sync of docs-seo.md + CLAUDE.md SEO sections |
Automation — Claude Code hook: .claude/settings.json registers a PostToolUse hook on Bash that runs .claude/hooks/docs-seo-trigger.sh when git commit or git add is executed. The script detects whether committed files match trigger patterns, then injects context into the conversation prompting docs-seo evaluation.
Automation — CI: .github/workflows/docs-seo.yml runs scripts/check_docs_seo.py on pull requests to validate SEO keyword consistency.
Manual invocation: Use /check-docs-seo skill or the @docs-seo agent directly.
at-spi2-core: AT-SPI2 accessibility framework (installed)python-gobject: GObject introspection Python bindings (installed)kwin: KWin Wayland compositor (installed)spectacle: Screenshot tool (installed, fallback)selenium-webdriver-at-spi: inputsynth binary (AUR, may need installation)
When writing or editing any documentation (README.md, CHANGELOG.md, GitHub release notes, pyproject.toml metadata, or repository settings), follow these SEO guidelines.
Primary: kwin-mcp, MCP server, GUI automation, KDE Plasma, Wayland automation, Linux desktop automation, live desktop automation Secondary: headless GUI testing, AI agent desktop, accessibility tree, AT-SPI2, libei, EIS, KWin virtual session, live session, session_connect, desktop testing framework, Wayland compositor testing, MCP tools, real desktop automation, desktop collaboration, kiosk automation, embedded device automation Long-tail: headless Wayland GUI testing, KDE Plasma automated testing, Linux GUI test automation CI/CD, Claude Code desktop automation, AI-driven Linux desktop testing, live KDE Plasma session automation, AI agent real desktop control, connect to live KWin session, container desktop automation, kiosk desktop automation, embedded Linux desktop testing
- H1 must be the project name; the line immediately after must be a bold description under 160 characters (acts as meta description for GitHub/search engines)
- Include a badge row (PyPI version, downloads, Python version, license, CI status)
- Use keyword-rich headings (e.g. "Available Tools", "System Requirements", "How It Works")
- Maintain the tool reference tables with tool name, parameters, and description columns
- Include copy-paste installation commands (uv, pip, from source)
- Cross-link sections with a Table of Contents
- Keep the architecture diagram (ASCII art) up to date when adding tools or modules
- Follow Keep a Changelog format
- Use Added / Changed / Deprecated / Removed / Fixed / Security categories
- Name specific tools (e.g.
mouse_click,accessibility_tree) in entries - Include comparison links at the bottom (
[0.x.y]: https://github.com/...) - Maintain an
[Unreleased]section at the top for in-progress changes
- Always written in English
- Minor+ releases structure: opening paragraph with value proposition -> Highlights (bullet list) -> New Tools table (if applicable) -> Installation commands -> Full Changelog comparison link
- Patch releases structure: What's Changed -> detailed description -> Full Changelog comparison link
- First sentence must convey the value proposition (what the user gains)
- Name exact technologies: AT-SPI2, libei, EIS, KWin ScreenShot2, D-Bus, PyGObject, wl-clipboard, wtype
- Include tool counts when relevant (e.g. "30 MCP tools" or "17 new tools")
descriptionmust be under 120 characters and include "MCP server" + "Linux" + "GUI automation" + "KDE Plasma" + "Wayland"- Maintain 20+ keywords covering: protocol (mcp, model-context-protocol), compositor (kwin, kde, plasma, wayland), purpose (gui-automation, desktop-automation, testing, e2e-testing, headless, headless-testing), technology (at-spi2, libei, accessibility, ai-agents), ecosystem (claude-code, linux-desktop, wayland-automation, mcp-server)
- Keep classifiers up to date (Development Status, Python versions, Topics)
[project.urls]must include Homepage, Repository, Issues, Changelog, and Documentation
- About description: must match pyproject.toml
descriptionor be a shorter variant with primary keywords - Topics: maintain 15-20 topics mirroring pyproject.toml keywords plus GitHub-specific tags (e.g.
hacktoberfestwhen applicable) - Homepage URL: link to PyPI project page (
https://pypi.org/project/kwin-mcp/) - Social preview: use a branded 1280x640 image with project name, tagline, and technology logos/icons