353 lines
12 KiB
Markdown
353 lines
12 KiB
Markdown
# computer-use-mcp
|
|
|
|
AIRI-specific macOS desktop orchestration MCP service.
|
|
|
|
## Why This Exists
|
|
|
|
This package exists because AIRI already has many useful pieces in the monorepo —
|
|
providers, chat UX, MCP attachment, desktop app surfaces, browser integrations,
|
|
tool bridges, and workflow-related logic — but those pieces are still too easy to
|
|
use as isolated features instead of one coherent agent system.
|
|
|
|
`computer-use-mcp` is the missing execution substrate for that gap.
|
|
|
|
The current goal is not to add "another computer use demo". The goal is to give
|
|
AIRI a unified way to:
|
|
|
|
- observe the current desktop or browser state
|
|
- choose the right execution surface for the task
|
|
- run deterministic actions through tools and terminal commands
|
|
- keep approvals, trace, and audit artifacts attached to the run
|
|
- compose those actions into repeatable workflows instead of one-off demos
|
|
|
|
In short:
|
|
|
|
- AIRI remains the control plane and agent shell
|
|
- `computer-use-mcp` is the local execution and workflow substrate
|
|
- the value is in orchestration, not in cursor movement by itself
|
|
|
|
## What It Is
|
|
|
|
This package is no longer positioned as a generic remote computer-use experiment.
|
|
The current v1 shape is:
|
|
|
|
- AIRI keeps the control plane:
|
|
- MCP tool surface
|
|
- approval queue protocol
|
|
- audit log
|
|
- trace history
|
|
- screenshot persistence
|
|
- `computer-use-mcp` provides a local macOS execution layer:
|
|
- window observation
|
|
- screenshots
|
|
- app open/focus
|
|
- mouse/keyboard injection
|
|
- background terminal command execution
|
|
- AIRI desktop adds a native approval adapter:
|
|
- `approval_required` still comes from MCP
|
|
- Electron shows a native dialog
|
|
- AIRI automatically calls approve/reject on the user's behalf
|
|
|
|
The intended story is:
|
|
|
|
- AIRI uses tools first
|
|
- visual observation is supplementary, not the primary execution path
|
|
- terminal commands are executed by a background shell runner, not by scripting Terminal tabs
|
|
- desktop/Electron/native apps and browser DOM are treated as different execution surfaces
|
|
|
|
## Why It Is Not "Just A Mouse Toy"
|
|
|
|
This package should not be understood as a coordinate-replay automation toy.
|
|
|
|
What makes it different:
|
|
|
|
- it exposes an MCP tool surface instead of a one-off macro recorder
|
|
- it keeps action policy, approval, trace history, and audit output per run
|
|
- it distinguishes between desktop control and browser DOM control instead of forcing everything through blind clicks
|
|
- it prefers deterministic execution paths (`terminal_exec`, workflows, `browser_dom_*`) before raw coordinate actions
|
|
- it is designed to be called by AIRI automatically as part of a task flow, not merely driven by a human demo operator
|
|
|
|
That means the package is useful only when it helps AIRI turn scattered local
|
|
capabilities into one observable, controllable task system.
|
|
|
|
## Current Executor Modes
|
|
|
|
- `dry-run`
|
|
- default
|
|
- never injects input
|
|
- still captures best-effort local screenshots for debugging
|
|
- `macos-local`
|
|
- current primary backend
|
|
- window observation via `NSWorkspace + CGWindowList`
|
|
- input injection via Swift + Quartz `CGEvent`
|
|
- app open/focus via `open -a` and `activate`
|
|
- `linux-x11`
|
|
- retained as a legacy experimental backend
|
|
- not the main v1 story anymore
|
|
|
|
## Tool Surface
|
|
|
|
Desktop observation and control:
|
|
|
|
- `desktop_get_capabilities`
|
|
- `desktop_observe_windows`
|
|
- `desktop_screenshot`
|
|
- `desktop_open_app`
|
|
- `desktop_focus_app`
|
|
- `desktop_click`
|
|
- `desktop_type_text`
|
|
- `desktop_press_keys`
|
|
- `desktop_scroll`
|
|
- `desktop_wait`
|
|
|
|
Terminal orchestration:
|
|
|
|
- `terminal_exec`
|
|
- `terminal_get_state`
|
|
- `terminal_reset_state`
|
|
|
|
Clipboard bridge:
|
|
|
|
- `secret_read_env_value`
|
|
- `clipboard_read_text`
|
|
- `clipboard_write_text`
|
|
|
|
Browser DOM bridge:
|
|
|
|
- `browser_agent_get_status`
|
|
- `browser_agent_run`
|
|
- `browser_dom_get_bridge_status`
|
|
- `browser_dom_get_active_tab`
|
|
- `browser_dom_read_page`
|
|
- `browser_dom_find_elements`
|
|
- `browser_dom_click`
|
|
- `browser_dom_read_input_value`
|
|
- `browser_dom_set_input_value`
|
|
- `browser_dom_check_checkbox`
|
|
- `browser_dom_select_option`
|
|
- `browser_dom_wait_for_element`
|
|
- `browser_dom_get_element_attributes`
|
|
- `browser_dom_get_computed_styles`
|
|
- `browser_dom_trigger_event`
|
|
|
|
Approval and audit helpers:
|
|
|
|
- `desktop_list_pending_actions`
|
|
- `desktop_approve_pending_action`
|
|
- `desktop_reject_pending_action`
|
|
- `desktop_get_session_trace`
|
|
|
|
Workflow orchestration:
|
|
|
|
- `workflow_open_workspace`
|
|
- reveals a workspace in Finder and opens it in the configured IDE
|
|
- `workflow_validate_workspace`
|
|
- opens the workspace, confirms `pwd`, inspects local changes, and runs a validation command such as `pnpm typecheck`
|
|
- `workflow_run_tests`
|
|
- runs a test command from the workspace root
|
|
- `workflow_inspect_failure`
|
|
- focuses the IDE and re-runs or inspects a failing command path
|
|
- `workflow_browse_and_act`
|
|
- generic browse-and-act flow for app observation and follow-up actions
|
|
- `workflow_resume`
|
|
- resumes a workflow that paused on `approval_required`
|
|
|
|
## Policy Model
|
|
|
|
The current macOS v1 boundary is intentionally narrow and explicit:
|
|
|
|
- global screen coordinates are allowed for UI actions
|
|
- `allowApps` is not used as a hard gate for click/type/scroll
|
|
- `denyApps` still blocks sensitive foreground apps
|
|
- `COMPUTER_USE_OPENABLE_APPS` only gates `desktop_open_app` and `desktop_focus_app`
|
|
- AIRI itself is in the default deny list to avoid self-operation
|
|
- terminal commands always require approval
|
|
- app open/focus always require approval
|
|
- click/type/press/scroll still use per-action approval
|
|
|
|
## Environment Variables
|
|
|
|
Core:
|
|
|
|
- `COMPUTER_USE_EXECUTOR`
|
|
- `dry-run`, `macos-local`, or `linux-x11`
|
|
- `COMPUTER_USE_APPROVAL_MODE`
|
|
- `actions` (default), `all`, `never`
|
|
- `COMPUTER_USE_SESSION_ROOT`
|
|
- local output directory for screenshots and `audit.jsonl`
|
|
- `COMPUTER_USE_TIMEOUT_MS`
|
|
- `COMPUTER_USE_DEFAULT_CAPTURE_AFTER`
|
|
- `COMPUTER_USE_MAX_OPERATIONS`
|
|
- `COMPUTER_USE_MAX_OPERATION_UNITS`
|
|
- `COMPUTER_USE_MAX_PENDING_ACTIONS`
|
|
|
|
macOS orchestration:
|
|
|
|
- `COMPUTER_USE_OPENABLE_APPS`
|
|
- default `Terminal,Cursor,Google Chrome`
|
|
- `COMPUTER_USE_DENY_APPS`
|
|
- default includes `1Password`, `Keychain`, `System Settings`, `Activity Monitor`, `AIRI`
|
|
- `COMPUTER_USE_DENY_WINDOW_TITLES`
|
|
- `COMPUTER_USE_TERMINAL_SHELL`
|
|
- default current shell, otherwise `/bin/zsh`
|
|
- `COMPUTER_USE_ALLOWED_BOUNDS`
|
|
- optional global coordinate clamp
|
|
|
|
Browser DOM bridge:
|
|
|
|
- `COMPUTER_USE_BROWSER_DOM_BRIDGE_ENABLED`
|
|
- default `true`
|
|
- `COMPUTER_USE_BROWSER_DOM_BRIDGE_HOST`
|
|
- default `127.0.0.1`
|
|
- `COMPUTER_USE_BROWSER_DOM_BRIDGE_PORT`
|
|
- default `8765`
|
|
- `COMPUTER_USE_BROWSER_DOM_BRIDGE_TIMEOUT_MS`
|
|
- default `10000`
|
|
|
|
Autonomous browser agent:
|
|
|
|
- `COMPUTER_USE_BROWSER_AGENT_ROOT`
|
|
- optional override for the embedded browser-agent workspace under `src/bin/computer_use`
|
|
- `COMPUTER_USE_PYTHON`
|
|
- optional python executable override for `browser_agent_run`; defaults to the embedded `.venv/bin/python` when present, otherwise `python3`
|
|
|
|
Legacy remote runner:
|
|
|
|
- `COMPUTER_USE_REMOTE_SSH_HOST`
|
|
- `COMPUTER_USE_REMOTE_SSH_USER`
|
|
- `COMPUTER_USE_REMOTE_SSH_PORT`
|
|
- `COMPUTER_USE_REMOTE_RUNNER_COMMAND`
|
|
- `COMPUTER_USE_REMOTE_DISPLAY_SIZE`
|
|
- `COMPUTER_USE_REMOTE_OBSERVATION_BASE_URL`
|
|
- `COMPUTER_USE_REMOTE_OBSERVATION_SERVE_PORT`
|
|
- `COMPUTER_USE_REMOTE_OBSERVATION_TOKEN`
|
|
|
|
Binary overrides:
|
|
|
|
- `COMPUTER_USE_SWIFT_BINARY`
|
|
- `COMPUTER_USE_OSASCRIPT_BINARY`
|
|
- `COMPUTER_USE_SCREENSHOT_BINARY`
|
|
- `COMPUTER_USE_OPEN_BINARY`
|
|
- `COMPUTER_USE_SSH_BINARY`
|
|
- `COMPUTER_USE_TAR_BINARY`
|
|
|
|
## AIRI Integration
|
|
|
|
AIRI still connects through `mcp.json`.
|
|
Example local macOS entry:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"computer_use": {
|
|
"command": "pnpm",
|
|
"args": [
|
|
"-F",
|
|
"@proj-airi/computer-use-mcp",
|
|
"start"
|
|
],
|
|
"cwd": "/path/to/your/airi/repo",
|
|
"env": {
|
|
"COMPUTER_USE_EXECUTOR": "macos-local",
|
|
"COMPUTER_USE_APPROVAL_MODE": "actions",
|
|
"COMPUTER_USE_OPENABLE_APPS": "Terminal,Cursor,Google Chrome"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
On the AIRI desktop side, approvals are handled like this:
|
|
|
|
1. model calls a `computer_use::*` tool
|
|
2. MCP returns `approval_required`
|
|
3. Electron shows a native approval dialog
|
|
4. AIRI automatically calls `desktop_approve_pending_action` or `desktop_reject_pending_action`
|
|
5. terminal/app approvals can be reused for the current run only
|
|
|
|
For browser DOM automation, `computer-use-mcp` also exposes a local WebSocket bridge that matches the user's Chrome extension bridge pattern:
|
|
|
|
1. `computer-use-mcp` listens on `ws://127.0.0.1:8765` by default
|
|
2. the unpacked browser extension background service worker connects to that socket
|
|
3. AIRI can then call `browser_dom_*` MCP tools against the active browser tab
|
|
|
|
If you override `COMPUTER_USE_BROWSER_DOM_BRIDGE_HOST` or
|
|
`COMPUTER_USE_BROWSER_DOM_BRIDGE_PORT`, mirror the same endpoint in the Chrome
|
|
extension via `chrome.storage.local.set({ browserDomBridgeHost, browserDomBridgePort })`
|
|
so the background worker reconnects to the correct socket.
|
|
|
|
Use the two surfaces differently:
|
|
|
|
- `desktop_*` for AIRI itself, native macOS apps, Electron windows, Finder, Terminal, VS Code
|
|
- `browser_dom_*` for real browser pages, cross-frame DOM reads, form filling, selector-based interaction, and iframe-heavy flows
|
|
- `browser_agent_run` for goal-driven browser tasks where AIRI should delegate the web exploration loop instead of manually hard-coding each browser step
|
|
|
|
## Validation Commands
|
|
|
|
- `pnpm -F @proj-airi/computer-use-mcp typecheck`
|
|
- `pnpm -F @proj-airi/computer-use-mcp test`
|
|
- `pnpm -F @proj-airi/computer-use-mcp smoke:stdio`
|
|
- `pnpm -F @proj-airi/computer-use-mcp smoke:macos`
|
|
- `pnpm -F @proj-airi/computer-use-mcp e2e:airi-chat`
|
|
- `pnpm -F @proj-airi/computer-use-mcp e2e:airi-discord`
|
|
|
|
Legacy remote validation remains available:
|
|
|
|
- `pnpm -F @proj-airi/computer-use-mcp bootstrap:remote`
|
|
- `pnpm -F @proj-airi/computer-use-mcp smoke:remote`
|
|
|
|
## Demo Story To Record
|
|
|
|
If you want to record a convincing demo, show the system as an orchestrated task
|
|
runner instead of a flashy cursor dance.
|
|
|
|
Recommended recording structure:
|
|
|
|
1. Show the AIRI desktop window, a terminal, and the generated report directory.
|
|
2. Start the local AIRI desktop app and the `computer-use-mcp` service.
|
|
3. Show that AIRI can call the MCP tools automatically instead of only listing them.
|
|
4. Demonstrate one short task that exercises the full loop:
|
|
- observe state
|
|
- execute a tool or workflow
|
|
- produce a visible result
|
|
- persist trace / audit / screenshots
|
|
5. End by opening the generated `report.json`, `audit.jsonl`, or screenshots so the demo finishes with evidence rather than just screen motion.
|
|
|
|
Good first demos:
|
|
|
|
- open a workspace, confirm `pwd`, inspect local changes, and run `pnpm typecheck`
|
|
- create and run a Python hello-world project through `terminal_exec`
|
|
- use desktop control for AIRI or native apps and use `browser_dom_*` only when the task truly moves into a browser page
|
|
|
|
### Discord integration demo
|
|
|
|
For a management-readable AIRI demo, the Discord settings flow is more representative than a generic hello-world reply:
|
|
|
|
1. start AIRI desktop and `integrations/discord-bot`
|
|
2. open `/settings/modules/messaging-discord`
|
|
3. enable the module and save settings
|
|
4. verify that the Discord bot receives the forwarded config from AIRI and reconnects itself
|
|
5. finish by opening `report.json`, screenshots, audit log, and `discord-bot.log`
|
|
|
|
Notes:
|
|
|
|
- for a pure local-secret run, set `AIRI_E2E_DISCORD_TOKEN`
|
|
- for a more agentic run, set `AIRI_E2E_DISCORD_TOKEN_SOURCE=portal` or `auto` and let AIRI retrieve the token from the live browser / Discord Developer Portal session
|
|
- `clipboard_read_text` / `clipboard_write_text` are the intended bridge when AIRI must move a copied token from the browser back into AIRI settings
|
|
- the observable harness keeps the token out of the desktop audit trail by applying the secret through the renderer instead of typing it through Quartz key events
|
|
- if you only want to validate the AIRI → Discord bot configuration plumbing without a real token, set `AIRI_E2E_DISCORD_ALLOW_LOGIN_FAILURE=true`
|
|
|
|
Less convincing demos:
|
|
|
|
- long videos of coordinate clicking with no trace output
|
|
- browser form-filling done only by screen coordinates when DOM tools were available
|
|
- tasks that cannot explain afterwards what the agent observed, executed, or verified
|
|
|
|
## Known Limits
|
|
|
|
- macOS only for the main v1 path
|
|
- no accessibility tree grounding yet
|
|
- PTY/TUI terminal support is product-supported on the self-acquire mainline; legacy outward terminal reroute remains secondary
|
|
- no multi-monitor orchestration policy yet
|
|
- global coordinates are allowed, so the safety boundary is approval + audit, not strict app isolation
|