{
  "markdown": "<!-- mcp-name: io.github.com55/pyside6-mcp -->\n# pyside6-mcp\n\nPlaywright-style MCP server for PySide6 apps — lets AI assistants see, control, and debug your Python desktop GUI without modifying your app's source code.\n\n```\nAI assistant → MCP tools → pyside6-mcp server → HTTP bridge (ephemeral localhost port) → PySide6 app\n```\n\n## Features\n\n- **Screenshot** any window or widget\n- **Inspect** the full widget tree (class, name, geometry, text, state)\n- **Click, type, scroll, press keys** — full interaction\n- **Find widgets** by class, objectName, or text content\n- **Read Python logs** captured from the app\n- **Run Python** inside the app process for advanced inspection\n- **Launch and stop** the app from the agent\n\nZero changes to your app's source code required.\n\n## Requirements\n\n- Python 3.11+\n- PySide6 6.6+\n- [uv](https://docs.astral.sh/uv/) (recommended)\n- Windows (tested), Linux/macOS (should work)\n\n## Installation\n\nThe MCP server (stdio) and the in-app bridge are separate:\n\n| Component | Where it runs | Needs PySide6? |\n|-----------|---------------|----------------|\n| **MCP server** (`pyside6-mcp`) | MCP client's process | No |\n| **Bridge** (`python -m pyside6_mcp …`) | Inside your PySide6 app | Yes |\n\n**No changes to the target project.** `launch_app(cwd=…)` injects only the\nbridge modules via an isolated `PYTHONPATH` — nothing is added to `pyproject.toml`,\nand the MCP server's dependencies (fastmcp, httpx, …) never enter the app environment.\n\nRequires [uv](https://docs.astral.sh/uv/) on `PATH`. MCP Registry name:\n`io.github.com55/pyside6-mcp`.\n\nUnlike [qt-mcp](https://github.com/0xCarbon/qt-mcp), you do **not** add this\npackage to the target app or set a probe env var. `launch_app` injects the bridge.\n\n### Claude Code\n\nPlugin (MCP + skill). `install` only searches marketplaces you have added —\nthere is no `github:` install shorthand:\n\n```bash\nclaude plugin marketplace add com55/pyside6-mcp\nclaude plugin install pyside6-mcp@pyside6-mcp\n```\n\nMCP server only:\n\n```bash\nclaude mcp add -s user pyside6 -- uvx pyside6-mcp\n```\n\n### Cursor\n\nInstall the Agent Plugin from this repository (or from the Cursor Marketplace\nonce listed). Manual stdio config:\n\n```json\n{\n  \"mcpServers\": {\n    \"pyside6\": {\n      \"command\": \"uvx\",\n      \"args\": [\"pyside6-mcp\"]\n    }\n  }\n}\n```\n\nAfter saving, reload MCP servers in **Cursor Settings → MCP**.\nSee [`examples/cursor-mcp-config.json`](examples/cursor-mcp-config.json).\n\n### Any stdio MCP client\n\n```json\n{\n  \"mcpServers\": {\n    \"pyside6\": {\n      \"command\": \"uvx\",\n      \"args\": [\"pyside6-mcp\"]\n    }\n  }\n}\n```\n\nPlace it wherever that client expects MCP config (user-level or project-level).\nSee [`examples/mcp-config.json`](examples/mcp-config.json).\n\n### VS Code / GitHub Copilot / other clients\n\nSame stdio block as **Any stdio MCP client**.\n\n> **Note:** `uvx` downloads and runs the MCP server in an isolated env — PySide6 is **not**\n> required there. PySide6 is only needed in the target app's venv (already a project dependency).\n>\n> To run from a git checkout instead of PyPI: `uvx --from git+https://github.com/com55/pyside6-mcp pyside6-mcp`\n\n## Usage\n\n### From MCP (recommended — zero project setup)\n\n```\nlaunch_app(cwd=\"/path/to/project\")                              # main.py at root\nlaunch_app(cwd=\"/path/to/project\", script=\"app.py\")             # other name at root\nlaunch_app(cwd=\"/path/to/project\", script=\"backend/gui.py\")   # entry in subfolder\nget_launch_help()                                               # full script decision guide\nlist_apps()                                                     # pids of apps this server launched\n```\n\n`cwd` is the project root (`pyproject.toml`). `script` is the entry `.py` **relative to cwd**.\n\n`launch_app` returns `{pid}` (the Qt app process, not the `uv` wrapper). Other tools omit `pid` to target the last launched app; pass `pid=` when several are running. Do not pass `port=`.\n\n### Manual launch (when you start the app yourself)\n\nPrefer `launch_app` above. Use these only when the app is already running, or\nyou want to start it outside the MCP server.\n\n**Without editing app source** — run the entry script through the bridge launcher\n(pulls `pyside6-mcp` into a temporary env; does not add it to the project):\n\n```bash\ncd your-pyside6-project\nuv run --with pyside6-mcp python -m pyside6_mcp main.py\n# other entry: … python -m pyside6_mcp app.py\n# in a subfolder: … python -m pyside6_mcp backend/gui.py\n```\n\nBridge listens on `http://127.0.0.1:7890` by default. Override with\n`PYSIDE6_MCP_PORT`. Then from the agent call `wait_until_ready()` (and pass\n`pid=` only if you use several apps).\n\n`launch_app` is different: it picks an ephemeral port and injects only the\nbridge modules via an isolated `PYTHONPATH` — you never set the port yourself.\n\n**Embed in the app** (always-on; requires adding the package to that project):\n\n```bash\nuv add pyside6-mcp\n```\n\n```python\n# In your app's main(), after QApplication is created and before app.exec()\nfrom pyside6_mcp import install_bridge\ninstall_bridge()  # same default port 7890 / PYSIDE6_MCP_PORT\n```\n\n### From your AI assistant\n\nOnce the app is running with the bridge active, ask your assistant:\n\n> \"Screenshot the app and click the Apply button\"\n> \"Why is the checkbox disabled? Inspect its state.\"\n> \"Fill in the form and submit it\"\n> \"Show me the last 20 log lines from the app\"\n\nYour assistant uses the `launch_app`, `screenshot`, `get_widget_tree`, `find_widget`, `click`, `type_text`, `get_logs`, and other tools automatically.\n\n`launch_app` returns only when the UI is ready (a visible top-level window that has been quiet for at least 500 ms), not merely when the bridge HTTP server is up. Default `timeout` is 45 seconds.\n\n## Tools\n\n| Tool | Description |\n|------|-------------|\n| `launch_app(cwd, script?, app_args?, timeout)` | Launch app (no target-project install) and wait for UI readiness. Returns `{pid}` |\n| `list_apps()` | Pids of apps launched by this server |\n| `get_launch_help()` | How to set cwd, script, app_args before launch |\n| `wait_until_ready(timeout, quiet_ms, pid?)` | Wait for UI readiness on an already-running app |\n| `wait_for_idle(timeout, quiet_ms, pid?)` | Wait until UI has been quiet after an action |\n| `get_app_status(pid?)` | Process + bridge health; detects likely modal blocks |\n| `stop_app(pid?)` | Stop a launched app |\n| `screenshot(widget_id?, pid?)` | Capture window or specific widget (modal/active-window aware) |\n| `get_widget_tree(pid?)` | Full widget hierarchy with IDs |\n| `get_widget_info(widget_id, pid?)` | Detailed properties of one widget |\n| `get_app_state(pid?)` | Active window, focus, screen info |\n| `find_widget(class_name?, object_name?, text?, visible?, pid?)` | Search widgets |\n| `click(widget_id?, x?, y?, button?, pid?)` | Mouse click |\n| `double_click(widget_id, x?, y?, pid?)` | Double click |\n| `type_text(text, widget_id?, pid?)` | Keyboard input |\n| `press_key(key, pid?)` | Named key: enter, escape, tab, up/down, f5, … |\n| `scroll(dy, widget_id?, dx?, pid?)` | Scroll wheel |\n| `list_actions(pid?)` | List QAction menu/toolbar items |\n| `trigger_action(name?, text?, pid?)` | Trigger a QAction without clicking menus |\n| `get_logs(n?, pid?)` | Recent Python log records |\n| `get_app_output(n?, pid?)` | Raw stdout/stderr from launched app |\n| `eval_python(code, pid?)` | Execute Python inside the app process |\n\n## Agent Skill\n\nA companion skill ships at [`skills/pyside6-mcp/SKILL.md`](skills/pyside6-mcp/SKILL.md)\nand is installed automatically with the plugin. It tells the agent when and how\nto use these tools — no need to explain the workflow every time.\n\n## Architecture\n\n```\npyside6_mcp/\n├── bridge.py      # In-process HTTP server (runs inside the target app)\n├── launch.py      # Isolated PYTHONPATH inject + launch_app argv/validation\n├── session.py     # Handshake + in-memory pid → port sessions\n├── server.py      # FastMCP stdio server (the MCP client talks to this)\n├── __init__.py    # Exports install_bridge()\n└── __main__.py    # Launcher: python -m pyside6_mcp <script>\n```\n\n**Thread safety**: all Qt operations are marshaled to the main thread via `QApplication.postEvent` with a custom event type — the same mechanism Qt uses internally for cross-thread signals.\n\n## Examples\n\n- [`examples/test_app.py`](examples/test_app.py) — minimal PySide6 app to verify the bridge\n- [`examples/mcp-config.json`](examples/mcp-config.json) — generic MCP config (Cursor, VS Code, Windsurf, …)\n- [`examples/cursor-mcp-config.json`](examples/cursor-mcp-config.json) — Cursor-specific template\n- [`examples/claude-mcp-config.json`](examples/claude-mcp-config.json) — same format, kept for reference\n\n## License\n\nMIT\n",
  "bytes": 8691,
  "sha": "3c90935da4d4bbc319426d867a66230e397d6704675b30471b4835408ffa4952",
  "repo_slug": "com55/pyside6-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_com55_pyside6_mcp_a7b5a265/readme"
}