cua-plugin

cua-plugin

MCP server that enables agents to control native GUI apps by snapshotting accessibility trees and performing actions like click, type, and scroll without bringing the app to the foreground.

Category
访问服务器

README

cua — computer use for protoAgent

Lets the agent drive native GUI apps on this machine: snapshot a window's accessibility tree, then click / type / scroll by element — without pulling the app to the foreground while you're using the computer.

It wraps cua-driver (MIT) as a managed MCP server. The driver is a separate binary that runs out-of-process, so this plugin adds zero packages to protoAgent's venv and works in the frozen desktop build.

Design rationale, options weighed, and the evidence behind them: protoAgent ADR 0084.


Read this before you enable it

This is real control of your real desktop — your files, your logged-in sessions, your accounts.

protoAgent's safety fences do not apply to anything the agent does here. Not "apply weakly" — do not apply. The network egress allowlist lives inside the fetch_url tool; the filesystem fence (ADR 0007) is a path check inside fs_tools. Both are in-process checks in protoAgent's own Python tools, and a mouse click never reaches either. An agent that can open your browser can reach any site on the internet. An agent that can open Finder can read any file you can.

That's not a bug to be patched — it's what computer use is. protoAgent's posture (ADR 0071) is trust-and-consent, not sandboxing, and this plugin is that posture at full strength. Enable it deliberately.

If you want computer use with containment, that's a VM, not this plugin — see ADR 0084 D5 on the deferred cua-sandbox path.


Setup

1. Install the driver. It is not installed for you, and this plugin never installs it — the probe just reports it missing until you do.

/bin/bash -c "$(curl -fsSL https://cua.ai/driver/install.sh)"     # macOS / Linux
irm https://cua.ai/driver/install.ps1 | iex                        # Windows

Lands in ~/.local/bin by default (--bin-dir or CUA_DRIVER_BIN_DIR to change). Uninstall: curl -fsSL https://cua.ai/driver/uninstall.sh | bash.

2. Grant permissions (macOS). The driver needs Accessibility and Screen Recording. Don't do this by hand in System Settings — run:

cua-driver permissions grant

This exists because TCC grants attach to the responsible app identity, and the intuitive route grants the wrong one. Approving a dialog raised from your terminal grants your terminal, not the driver; the driver still can't read a window, and every status check lies to you about it in the cheeriest way. The grant subcommand launches CuaDriver via LaunchServices so the dialog attributes to com.trycua.driver, then confirms.

Verify with cua-driver permissions status --json — it answers through the running daemon, so a true carries the driver's own identity ("attribution": "driver-daemon"). With no daemon it reports unknown rather than guessing.

Don't trust cua-driver check_permissions. It reports the caller's TCC identity, so from your shell it happily says accessibility: true on a machine where the driver has no grant at all. permissions status is the honest one. (This plugin's Test button uses permissions status; an earlier cut used the tool and reported a missing grant on a fully-granted machine.)

3. Enable the plugin. Settings ▸ Computer use ▸ Enable computer use, then hit Test connection. That's not decorative: it's the only thing that checks all three failure modes at once (binary found, TCC granted for the driver, and configured tool names real for this driver build). A healthy result reads like:

/Users/you/.local/bin/cua-driver · 17 tool(s) bound of 38 published

There is no step 4 — you don't manage a daemon. When protoAgent spawns cua-driver mcp, the driver notices it lacks grants under whatever launched it and auto-launches the CuaDriver daemon, then proxies through it:

cua-driver-rs: mcp launched without CuaDriver.app's TCC grants; auto-launching
the daemon via `open -n -g -a CuaDriver --args serve` and proxying MCP requests
through it. Pass --no-daemon-relaunch to stay in-process.

That's why one permissions grant is enough: the grant lives on com.trycua.driver and holds no matter who spawns the server — your shell, scripts/dev.sh, or the packaged desktop app. Don't pass --no-daemon-relaunch; it stays in-process and puts the grant burden back on protoAgent's own identity.


Settings

Field Default Notes
Enable computer use off Off ⇒ no server spawns, no tools exist.
cua-driver path (blank) Blank = probe PATH, then ~/.local/bin, /opt/homebrew/bin, /usr/local/bin.
Tool surface core core binds the documented loop (17 tools); full binds all 38.
Extra tools (none) Names added on top of core, e.g. kill_app.

Why core is the default

The driver publishes 38 tools (verified on 0.8.3). Binding all of them spends context on every turn for surface the agent almost never needs (protoAgent ADR 0005). core is the snapshot→act loop; everything else is one config edit away.

Left out of core on purpose:

  • bring_to_front — steals focus, which is the one thing this driver exists to avoid.
  • kill_app — destructive.
  • get_accessibility_tree — despite the name, a desktop-level snapshot (apps + visible windows + bounds/z-order) that overlaps list_apps/list_windows. get_window_state is the per-window AX tree you actually act on.
  • page — the browser capability, with its own session protocol (WEB_APPS.md).
  • start_session / end_session, recording, cursor styling — MCP mints a session per connection, so you don't need these.
  • check_for_update — driver self-update. Deliberately operator-driven (ADR 0084): plugins.update_policy can't see a binary updating itself.

extra_tools names that the driver doesn't publish are dropped silently by the MCP filter — a wrong name is a missing tool, not an error. Test connection lists the driver's real tools and flags any that don't match.


Gotchas

Don't turn off persistent MCP sessions. mcp.persistent_sessions: false breaks element-indexed workflows. The driver caches the per-(pid, window_id) accessibility element map in the process your session talks to; a stateless session spawns a fresh cua-driver mcp per call, so the cache is gone between the snapshot that minted an element_index and the click that uses it. This plugin sets persistent: true on its entry, but the host computes mcp.persistent_sessions AND entry.persistent — a global false wins and there is nothing the entry can do about it.

The desktop app has a different PATH than your shell. ~/.local/bin is routinely absent from a service's environment. If the driver works in dev and vanishes in the packaged app, set cua-driver path to the absolute path.

screenshot doesn't exist. It was removed upstream (cua PR #1692) — capture is get_window_state with capture_mode: "vision". Docs and blog posts that tell you to call screenshot are out of date.

MCP doesn't need to be on. A plugin-contributed server activates MCP by itself; you don't need mcp.enabled: true.


What it registers

  • A managed MCP server (register_mcp_server) spawning cua-driver mcp over stdio. Tools arrive namespaced cua-driver__*. The factory returns None — the documented "don't start" path — when disabled or when the binary is absent. Verified end-to-end against driver 0.8.3: 17 tools bind, the allowlist holds exactly (no leakage from the other 21), and it activates MCP on its own — mcp.enabled: true is not required.
  • A skill (register_skill_dir) teaching the snapshot-before-and-after invariant. This is not documentation garnish: the driver is accessibility-tree-first, element_index values are minted per snapshot and go stale across turns, and actions that silently no-op look identical to actions that worked. Without the protocol the tools look broken.
  • POST /api/config/test-cua backing the Settings Test button.

No Python tools, no runtime dependencies.

Development

uv venv --python 3.11 && uv pip install -r requirements-dev.txt ruff
.venv/bin/ruff check . && .venv/bin/ruff format --check . && .venv/bin/pytest -q

The suite runs with no protoAgent hosttests/conftest.py registers the plugin as a synthetic package the way the real loader does, and fakes the registry seam.

License

MIT. Wraps trycua/cua (MIT), installed separately and not vendored here.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选