Skip to main content
Glama

mcp-computer-use

English · עברית

A small MCP server that lets coding agents (Codex, Claude Code, Cline, Antigravity…) ask "what does that window show?" and get back a two-line JSON answer instead of thousands of tokens of raw window text, as well as perform safe, app-scoped UI actions (click, type_text).

Intended to be published publicly on GitHub (MIT). Not published yet.

Why (token savings)

When an agent runs agent-cu itself, the whole accessibility tree / window text lands in its context and is re-sent on every following step. In our test one "is Claude done?" check cost ~206k tokens (~47k context per step, ~3% of a ChatGPT Plus 5-hour quota).

This server does the reading locally:

  1. agent-cu text -a <App> reads the window (no model).

  2. Code extracts only the status and the last message using specialized per-app extractor profiles (Claude Code, Codex desktop, editor, browser, or generic fallback). ~1.5 s.

  3. A local Ollama model (default gpt-oss:20b) summarizes that short text. Measured 4–8 s, correct.

  4. The agent receives ~50 tokens of JSON.

qwen3:4b was tested and kept emitting reasoning, so gpt-oss:20b is the default (configurable).

NOTE

Bench insight (measured 2026-10-18): For small or simple windows (e.g. a calculator or a short webpage) a direct read with agent-cu text can be as cheap in tokens as the bridge (~1k–2k tokens). The bridge pays off on large, busy windows (chat apps, IDEs) where raw text runs 40k–200k+ tokens, and whenever pre-extracted details answer the question directly.

Related MCP server: vision-mcp

Tools

Tool

Description

look_at_screen(question, app=None, client=None, session_id=None, keep_warm=False, include_image=False)

Reads one window and answers. If app is omitted, the app named in the question (also Hebrew aliases like "קלוד") or the foreground window is used. Read-only. client / session_id are optional (see Sessions). Pass include_image=True to also return a downscaled window JPEG. CLI: --ask QUESTION [--app APP] [--image-out PATH].

click(app=None, target=None, steps=None, client=None, session_id=None, confirm_dangerous=False)

Clicks a visible label, or a sequence of 1–10 labels via steps. Without app, the foreground window's app is used (APP_NOT_FOUND if none). Stopped on first failure. CLI: --click APP TARGET, --click-steps APP STEP....

type_text(target, text, app=None, client=None, session_id=None, confirm_dangerous=False)

Sets the value of an editable field in the app without submitting. Without app, the foreground window's app is used. Replaces content; Enter is never pressed; no keystrokes sent to other windows. CLI: --type APP TARGET TEXT.

ping()

Heartbeat: server up, local Ollama reachable (auto-started if needed), model replies pong. No screen reading. Returns {ok, server, ollama, model_reply_ok, model, seconds, cold, error?}. The first ping can take 30–50 s when the model is cold. CLI: --ping.

release_model()

Unloads the model now and returns freed_mb. Call it at the end of a task. CLI: --release.

health()

Checks backend health: Ollama reachable, model pulled, model loaded, memory, free RAM, current keep_alive policy, agent-cu installed. CLI: --health.

When to read (look_at_screen) vs click/type

  • Read first: Use look_at_screen to inspect window state, verify results, or when unsure what UI elements/labels are visible. It is completely read-only and side-effect free.

  • Visible labels, never refs: Pass the visible UI label (1 to 200 characters), never an @eN reference. Accessibility element refs change on every snapshot; @eN targets are rejected with INVALID_TARGET.

  • Single action vs batches: Prefer one click per call when exploring or verifying step by step. Use steps for a known sequence of 1 to 10 visible labels (e.g. calculator buttons ["7", "+", "5", "="]). Every step gets a fresh snapshot and runs through the safety gate; execution stops at the first failure.

  • Direct text entry (type_text): Sets the value of an editable field (roles: textfield, textarea, edit, combobox, textbox, document, searchfield) directly in the target app. It replaces the existing content without submitting — Enter is never pressed, and no keystrokes are sent to other windows. Text length is limited by max_type_chars (default 2000).

Optional window image capture (include_image)

When include_image=True, the tool returns the same JSON answer plus an "image": {"width": int, "height": int, "bytes": int} metadata dictionary and an MCP image block (ImageContent, JPEG format, max 1024 px wide, quality 70) of the target window only.

  • Non-intrusive capture: Captured via Win32 PrintWindow through a bundled PowerShell script (cu_capture.ps1). No window is focused, brought to front, moved, or restored. It works while the window is covered by other windows and, in our tests, even while the Windows session is locked.

  • Failures & Minimization: If the target window is minimized, IMAGE_WINDOW_MINIMIZED is returned. If capture fails for any reason (e.g. blank capture, timeout, window not found), the failure is reported in "image_error": {"code", "message", "retryable", "suggestion"} and the text answer is still returned without an image block.

  • Error codes:

    • IMAGE_CAPTURE_FAILED: Capture script failed or target window was not found / ambiguous.

    • IMAGE_CAPTURE_BLANK: Captured bitmap was completely blank (window may be minimized or hardware-accelerated).

    • IMAGE_WINDOW_MINIMIZED: Target window is minimized (must be restored to capture).

    • IMAGE_CAPTURE_TIMEOUT: Capture exceeded image_timeout.

  • Configuration: image_timeout (env MCP_CU_IMAGE_TIMEOUT, default 15.0 s) sets the subprocess timeout.

  • CLI: mcp-computer-use --ask "What is open?" --app "Calculator" --image-out snapshot.jpg writes the JPEG to disk and outputs JSON with image / image_error.

  • Zero dependencies: Pure Win32 P/Invoke in PowerShell; no Python imaging libraries (such as Pillow) are required. Default is False; when false, output and tool schema are byte-identical and unchanged.

  • Token cost: Measured on 2026-10-18 with Codex CLI (one look_at_screen call on the Calculator, 644×1067 JPEG ≈ 42 KB): Codex reported total input tokens of 120,991 / 145,588 without the image and 97,326 / 70,301 with it. Run-to-run prompt/context variation (±40k) is larger than any image cost, so the cost of a single image could not be measured this way. Treat images as expensive anyway (typically ~1,000–2,000 tokens per image for vision models) and request include_image=True only when text is not enough (inspecting layouts, charts, rendering artifacts, visual glitches).

Label matching hierarchy & model resolution

The server resolves UI targets using a strict ranking hierarchy:

  1. Exact match: Case-sensitive exact string equality with the UI element name (tier 1, score 1.0, how: "exact").

  2. Normalized match: Casefold, Unicode NFKC normalization, Hebrew niqqud and cantillation stripped (U+0591–U+05C7), maqaf (־ U+05BE → space), Hebrew geresh (׳ U+05F3) and gershayim (״ U+05F4) converted to ASCII ' and ", only the bidi/zero-width marks U+200B–U+200F, U+061C, U+202A–U+202E, U+2066–U+2069, U+FEFF removed (the safety blocklist check separately strips all category Cf format characters), and only a trailing …, ... or : stripped (tier 2, score 0.95, how: "normalized").

  3. Synonyms and IDs: Digit and math operator synonyms in English and Hebrew (e.g. "7" ↔ "seven" ↔ "שבע", "+" ↔ "plus" ↔ "ועוד", "-" ↔ "−" (U+2212) ↔ "minus" ↔ "פחות", "*" ↔ "×" ↔ "multiply" ↔ "כפול" ↔ "הכפל ב", "/" ↔ "÷" ↔ "divide" ↔ "חלקי" ↔ "חלק ב", "=" ↔ "equals" ↔ "שווה", "." ↔ "decimal separator" ↔ "תו הפרדה עשרוני"), or matching element accessibility id (tier 3, score 0.9). Note that "-" also matches "−" (U+2212). Role phrases (e.g. button 7, כפתור 7, field Search, שדה חיפוש) are split to disambiguate.

  4. Weak matches: Live value matches, token contains, or fuzzy sequence similarity >= 0.80 (tier 4-5). Weak matches never auto-click by themselves; they return candidates, and when resolve_with_model is on the local model may choose one of them (≤5), which is then clicked after the safety check; otherwise up to 5 candidates are returned with TARGET_AMBIGUOUS.

Safety rules & blocklist

To prevent unintended destructive actions, an action blocklist is always enforced before clicking or typing:

  • Default blocklist (always enforced):

    • English dangerous actions: Delete, Remove, Send, Allow, Approve, Accept, Pay, Buy, Purchase, Submit, Confirm, Publish, Merge, Uninstall, Format.

    • Hebrew multi-word: הסר התקנה.

    • Hebrew base actions: מחק, הסר, שלח, אשר, אפשר, שלם, קנה, פרסם.

    • Hebrew plural imperatives: מחקו, הסירו, שלחו, אשרו, אפשרו, שלמו, קנו, פרסמו.

    • Hebrew inflected forms / verbal nouns / infinitives: מחיקה, למחוק, הסרה, להסיר, שליחה, לשלוח, אישור, לאשר, לאפשר, תשלום, לשלם, קנייה, לקנות, פרסום, לפרסם.

  • Config & environment additions: [safety] blocklist / blocklist_extra in TOML, or environment variables MCP_CU_SAFETY_BLOCKLIST / MCP_CU_SAFETY_BLOCKLIST_EXTRA only ADD words; default blocklist words can never be removed.

  • Evaluation: The target label is checked first (before taking a snapshot), followed by the resolved element name.

  • Confirmation workflow: If a blocked word matches and confirm_dangerous=false (the default), the action is blocked and returns DANGEROUS_ACTION_NEEDS_CONFIRMATION with would_click and matched_rule.

  • CRITICAL: The calling agent MUST ask the human user and get explicit approval before calling again with confirm_dangerous=true.

  • Non-blocked defaults: Common navigation actions like "Close" / "Exit" (and Hebrew "סגור" / "יציאה") are not blocked by default (add them to the blocklist in TOML or env if wanted).

Action audit log (.sessions/actions.log)

Every click and type action is recorded in an append-only JSON Lines file at <project>/.sessions/actions.log (or MCP_CU_SESSIONS_DIR):

  • Retention: Records older than 24 hours (action_log_ttl_hours, default 24.0) are purged atomically during appends.

  • Concurrency: Thread-safe and process-safe with file-level locking (actions.log.lock).

  • Whitelisted fields only: time, client, session_id, app, action, target, ref, name, role, result, confirmed, error_code, text_len, hint.

  • Privacy & Scrubbing: Typed text is NEVER logged — only its character length (text_len). Furthermore, automatic scrubbing inspects all logged string fields and replaces any value containing the typed text or fragments of 6+ characters with <redacted>.

Error codes

Error Code

Description

TARGET_NOT_FOUND

No matching UI target found in the window (returns up to 5 near candidate suggestions).

TARGET_AMBIGUOUS

Multiple candidates matched (returns up to 5 candidates to disambiguate).

TARGET_NOT_EDITABLE

The target was found but its role is not an editable field (type_text).

INVALID_TARGET

Target is empty, longer than 200 chars, or an @eN ref; passing both or neither of target and steps; invalid steps count (not 1–10) or invalid step label; or a non-string text in type_text.

TEXT_TOO_LONG

Typed text exceeds max_type_chars (default 2000 characters).

DANGEROUS_ACTION_NEEDS_CONFIRMATION

Target or element matched the safety blocklist. Requires explicit human user approval before setting confirm_dangerous=true.

APP_NOT_FOUND

App window not found, empty app name, or app name contains shell metacharacters.

AGENT_CU_NOT_INSTALLED

agent-cu binary not found on PATH.

AGENT_CU_FAILED

Underlying UI automation command failed.

OLLAMA_UNREACHABLE

Ollama service could not be reached or auto-started.

MODEL_NOT_FOUND

Configured model is not pulled in Ollama.

MODEL_TIMEOUT

Model inference timed out.

MODEL_FAILED

Model inference failed.

QUESTION_TOO_LONG

Question exceeds max_question_chars (default 300).

EMPTY_QUESTION

Question string is empty.

IMAGE_CAPTURE_FAILED

Window image capture failed, or target window was not found / ambiguous.

IMAGE_CAPTURE_BLANK

Captured image was blank (window may be minimized, hardware-accelerated, or covered).

IMAGE_WINDOW_MINIMIZED

Target window is minimized. Restore or un-minimize the window before requesting an image.

IMAGE_CAPTURE_TIMEOUT

Window image capture timed out (exceeded image_timeout).

CLI options & security notice

The CLI supports running actions directly:

# Click a single label
mcp-computer-use --click "מחשבון" "7"

# Run a sequence of steps (1 to 10 labels)
mcp-computer-use --click-steps "מחשבון" "7" "+" "5" "="

# Set text in an editable field
mcp-computer-use --type "מחשבון" "שדה הזנה" "123"

# Confirm a dangerous action after explicit human approval
mcp-computer-use --click "MyApp" "Delete" --confirm-dangerous
WARNING

Command-Line & Text Entry Security Notice: Both CLI --type and the MCP type_text tool pass the text to agent-cu as an argument (agent-cu type -s REF -a APP -- TEXT), making the text visible to local processes while it runs (briefly, e.g. via Task Manager or process inspection). The CLI additionally exposes the text in the calling shell's command line and history. Do not type secrets or passwords with it.

Calculator examples (MCP & CLI)

Packaged and UWP apps run inside ApplicationFrameHost where the app name is the localized window title (e.g. Calculator on English Windows or מחשבון on Hebrew Windows; launch with cu-open.ps1 calc.exe).

MCP Tool Calls (JSON):

// Single click
{
  "app": "מחשבון",
  "target": "7"
}

// Known sequence via steps (max 10)
{
  "app": "מחשבון",
  "steps": ["7", "+", "5", "="]
}

// Type into an editable field
{
  "app": "מחשבון",
  "target": "שדה הזנה",
  "text": "42"
}

CLI Execution:

mcp-computer-use --click "מחשבון" "7"
mcp-computer-use --click-steps "מחשבון" "7" "+" "5" "="

Per-app profiles

When look_at_screen reads a window, it selects a specialized extractor profile based on the application name (app_name) and window title (window_title). Profiles are evaluated in strict first-match-wins order:

$$\text{claude_code} \longrightarrow \text{codex_desktop} \longrightarrow \text{editor} \longrightarrow \text{browser} \longrightarrow \text{generic}$$

  1. claude_code: Matched when "claude" is in the lower-cased app name.

  2. codex_desktop: Matched when the app name is chatgpt, codex, codex desktop, or openai.codex (Windows app ChatGPT), or when the window title contains codex.

  3. editor: Matched for VS Code-family editors by app name (code, code.exe, code - oss, code-oss, code - insiders, cursor, antigravity ide, windsurf, vscodium), or by window title patterns ( - Visual Studio Code, - Cursor, - Antigravity IDE -, - Windsurf, - VSCodium, - Code - Insiders).

  4. browser: Matched for supported browsers by app name (chrome, google chrome, msedge, edge, microsoft edge, brave, firefox, mozilla firefox) or by window title browser suffixes ( - Google Chrome, - Microsoft Edge, microsoft edge, - Mozilla Firefox, - Brave).

  5. generic: Default fallback when no specialized profile matches.

Output per profile (top-level status & details)

Every look_at_screen call returns a top-level status (working, finished, waiting, error, or unknown) alongside an optional details dictionary populated by code (from UI Automation text and accessibility snapshots, without a model; disable extra snapshot inspection with MCP_CU_SNAPSHOT_DETAILS=0):

  • Claude Code (claude_code):

    • Top-level status: working, finished, or unknown.

    • details keys: project, session (chat title), branch, folder, model, files, background_tasks, context_used, waiting_for_user, waiting_prompt (from approval buttons), failures, next_step (actionable suggestions in English and Hebrew), and asks_user.

  • Codex desktop (codex_desktop, Windows app ChatGPT):

    • Top-level status: working, finished, waiting, or unknown — determined strictly from UI controls only (Stop button, Copy + Good/Bad response buttons, approval dialogs; prose text inside assistant turns is never used as a status signal).

    • details keys:

      • project: Project or workspace name (from "What should we work on in...", "Change project: ...", or thread header folder/project controls).

      • session: Chat / thread title (from heading or thread header).

      • mode: Current mode (from "Switch mode, current mode: ...").

      • projects: Sidebar project list (up to 8, corroborated by project action controls).

      • recent_chats: Sidebar recent chat list (up to 5, corroborated by pin/archive controls).

      • needs_attention: Boolean true when the "View activity, needs attention" button is visible.

      • next_step: Extracted from "Next steps:" or "השלב הבא:".

      • failures: Error and failure lines detected via find_failures.

      • waiting_prompt (and waiting_for_user=true): Extracted prompt when waiting for user approval (e.g. "Allow command?", "Approve command?"), corroborated by paired approve/deny buttons.

  • Editor (editor, VS Code / Cursor / Antigravity IDE / Windsurf / VSCodium):

    • Top-level status: waiting if a prompt is pending, error if failures are detected, otherwise unknown.

    • details keys:

      • project: Workspace or project folder name (from window title or Explorer tree section).

      • file: Currently active file (from window title or single active editor tab).

      • waiting_prompt (and waiting_for_user=true): Real modal dialog prompts (workspace trust "Do you trust the authors...", extension installation, save confirmations), verified by accompanying dialog action buttons.

      • failures: Diagnostic errors (Error: ..., Exception:) and error counts from the Problems panel or last terminal run (older output superseded by new shell prompts or subsequent test summaries is automatically discarded).

      • next_step: Actionable next steps found in evidence lines.

  • Browser (browser, Chrome / Edge / Brave / Firefox):

    • Top-level status: error when a network error page is detected (e.g. DNS probe, connection refused, no internet); otherwise unknown.

    • details keys:

      • page_title (and title): Cleaned page title (browser suffixes and Edge profile segments stripped).

      • url: Current page URL from address bar or top text lines.

      • tab: Active tab label (memory usage tags stripped).

      • headings: Up to 5 key page headings extracted from the web content area (RootWebArea) or text.

      • failures: Failures and errors within web document content.

      • next_step: Actionable next steps found within document content.

      • Filters out browser chrome (toolbars, tab strip, address bar, favourites bar) so only web content is extracted.

  • Generic (generic):

    • Top-level status: Always unknown.

    • details keys: failures (detected from the last 30 lines of extracted tail text, if any).

The conservative rule

All extractors strictly adhere to a conservative principle: return unknown status and retain unclassified content rather than guessing or inferring state from ambiguous prose or unstructured text.

Limitations

  • Browser content visibility: Browsers may expose no page content to UI Automation while the Windows session is locked or the browser window is minimised (accessibility tree only exposes top-level chrome or an empty document area).

  • Codex desktop thread-state rules: Thread-state heuristics for Codex desktop were built and validated from synthetic samples and may need tuning against future desktop app updates.

Sessions (optional context between calls)

client (e.g. codex) and session_id (chosen by the client, e.g. fix-ui) are optional; both are sanitized to [A-Za-z0-9_-], max 64 chars.

  • Without them every call is independent: the full screen is re-read, "what changed" is not possible and no file is written. Repeated calls without a session get a short hint suggesting one.

  • With them the server keeps one small JSON file per pair, <project>/.sessions/{client}__{session_id}.json (app, project, session, last_message, next_step, status, last 5 questions with short answers, updated_at). Each call reads the file, reads the screen, compares, answers only the question, returns changed_since_last and updates the file. The same question on an unchanged screen is answered from the file (cached: true, no model call).

  • A new session_id replaces the old one for that client (the old file is deleted), so each client has one active file. A session_id without client uses client default.

  • Files not updated for 24 h are deleted on every call (MCP_CU_SESSION_TTL_HOURS). Folder: MCP_CU_SESSIONS_DIR. No in-memory state is kept.

Ollama auto-start

If OLLAMA_URL points at this machine (127.0.0.1 / localhost) and Ollama does not answer, the server starts ollama serve itself: detached, hidden window, with OLLAMA_HOST=127.0.0.1:<port from OLLAMA_URL> set only for the child process (your global OLLAMA_HOST, e.g. a Mac, is never touched), then polls /api/tags for up to 30 s (a cold ollama serve can need more than 10 s). The started server outlives the MCP host: on Windows it is started with CREATE_BREAKAWAY_FROM_JOB; if the host's job object refuses that (e.g. codex exec) or the child is still in a job, it is started through WMI Win32_Process.Create instead (parented by WmiPrvSE, outside the host's job). The method used is reported as method (breakaway / wmi / popen last resort) in health().last_autostart; server output goes to .sessions/ollama-autostart.log. A call right after an auto-start gets the cold-load timeout budget.

  • Checked on every call without a session and on the first call of a session (new session file); not on every call inside a session. If a call inside a session fails with OLLAMA_UNREACHABLE, it starts Ollama once and retries once.

  • A port check plus a lock file (.sessions/ollama-autostart.lock) prevent double starts.

  • ollama is found on PATH or at %LOCALAPPDATA%\Programs\Ollama\ollama.exe.

  • MCP_CU_AUTOSTART_OLLAMA=0 disables it; MCP_CU_AUTOSTART_TIMEOUT (default 30). health() reports ollama_autostarted.

Memory release (smart keep_alive)

  • Single call, no active session: the model stays loaded 3 min (MCP_CU_KEEP_ALIVE_IDLE).

  • Active session (any .sessions file updated in the last 10 min) or keep_warm=true: 10 min (MCP_CU_KEEP_ALIVE_SESSION), so the model is released 10 min after the last call.

  • Memory pressure: free RAM is checked before and after each call; below 2048 MB (MCP_CU_MIN_FREE_MB, 0 = off) the model is unloaded right after answering, even mid-session. A background thread in the server (MCP_CU_MEMORY_WATCH=1, every MCP_CU_MEMORY_WATCH_INTERVAL=30 s) does the same while the model is loaded.

  • Callers should call release_model() at the end of a task. Each answer has a memory field (keep_alive, reason, was_loaded, free_ram_mb, unloaded_low_memory). CLI: mcp-computer-use --release.

Success:

{"windows_seen": ["Claude"], "status": "finished",
 "summary": "Claude finished: 916 tests pass, commit be8b48e pushed, installer built.",
 "confidence": 0.95,
 "details": {"project": "MyApp-Desktop", "session": "Multimodal work in progress", "branch": "fix/pre-api",
             "next_step": "After installing, reopen QUAL.", "failures": ["Finished a background command (1 failed)"]},
 "changed_since_last": ["status: working -> finished", "new text in the last message"],
 "session": {"client": "codex", "session_id": "bench"},
 "model_used": "gpt-oss:20b", "duration_seconds": 6.1,
 "memory_mb": 11264.0, "tokens_per_second": 12.1}

Failure (the caller can still act on extracted):

{"error": {"code": "MODEL_TIMEOUT", "message": "gpt-oss:20b did not answer within 38s",
           "retryable": true, "suggestion": "Retry once (the model may have been cold-loading) or use the raw `extracted` text."},
 "windows_seen": ["Claude"],
 "extracted": {"status": "finished", "last_message": "…", "extractor": "claude", "truncated": false},
 "model_used": "gpt-oss:20b", "timeout_seconds": 38.0, "duration_seconds": 38.4}

Smart timeout: timeout_base + timeout_per_1k_chars × chars/1000, clamped to [timeout_min, timeout_max], plus cold_load_extra when /api/ps shows the model is not loaded, is loaded with a different context_length than num_ctx (Ollama would reload it), or Ollama was just auto-started. Defaults (30 s base, 20–90 s, +45 s cold) leave generous headroom over a warm gpt-oss:20b answer (~12 s at ~11 tok/s on a laptop). ping() and the click model resolver use timeout_base (+ cold_load_extra when cold) directly. ping() uses the same num_ctx as look_at_screen, so the model it loads is reused by the next call.

Adaptive timeout (adaptive_timeout = true, default): after each successful look_at_screen model call its wall-clock duration is recorded; warm calls go into a rolling window of the last adaptive_window (8) samples, cold-load calls are kept apart and never used. The next warm timeout is max(2 × p90(window), timeout_min) plus the same per-1k-chars term (added on top, a conservative choice since samples already include their own size), clamped to [timeout_min, timeout_max]; cold load still adds cold_load_extra. No samples yet → the static formula above. A MODEL_TIMEOUT never shrinks it: the next timeout is multiplied by 1.5 per timeout (still capped by timeout_max) until a success resets the bump. History is per process and persisted atomically to timing_stats.json in the sessions dir, so a fresh process (each codex exec run) starts with it; a missing or corrupt file means no history. adaptive_timeout = false restores the static formula.

Call budget (call_budget_seconds, default 110, env MCP_CU_CALL_BUDGET_SECONDS, 0 = off): a total wall budget per tool call measured from its start, so the answer (or structured error) arrives before the MCP host's tool timeout (Codex tool_timeout_sec = 120). The autostart wait is shrunk to leave room for the model, and every model timeout (look_at_screen first try and retry, ping, the click resolver; a click batch counts as one call) is min(computed, budget − elapsed). With less than 5 s left the call returns MODEL_TIMEOUT at once with a retry suggestion (click returns TARGET_AMBIGUOUS with candidates). Successful and failed look_at_screen results carry timing: timeout_seconds, timeout_source (static | adaptive | bumped), samples, cold, budget_seconds, budget_capped, model_wall_seconds.

Setup (Windows, PowerShell)

Requirements: Python 3.10+, Node + npm i -g agent-cu, Ollama.

cd C:\Develop\mcp-computer-use
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -e ".[dev]"
pytest -q

Ollama

The default URL is http://127.0.0.1:11435 (a local instance on a non-default port, because a global OLLAMA_HOST may point to another machine).

$env:OLLAMA_HOST = "127.0.0.1:11435"; ollama serve      # in its own window
$env:OLLAMA_HOST = "127.0.0.1:11435"; ollama pull gpt-oss:20b
mcp-computer-use --health                                 # check everything
mcp-computer-use --ask "Is Claude finished?" --app Claude # one-off test

Configuration

Priority: defaults < TOML file < env vars. File: mcp-computer-use.toml in the working dir, %USERPROFILE%\.config\mcp-computer-use\config.toml, or MCP_CU_CONFIG=<path> (see mcp-computer-use.example.toml).

Env

Default

Description

MCP_CU_OLLAMA_URL / OLLAMA_URL

http://127.0.0.1:11435

Ollama server URL

MCP_CU_MODEL / MODEL

gpt-oss:20b

Model used for summarization / candidate picking

MCP_CU_MAX_CHARS

2000

Max chars extracted from window for model

MCP_CU_MAX_QUESTION_CHARS

300

Longer questions rejected with QUESTION_TOO_LONG

MCP_CU_TIMEOUT_BASE / _PER_1K_CHARS / _MIN / _MAX

30 / 4 / 20 / 90

Smart timeout bounds and scaling

MCP_CU_COLD_LOAD_EXTRA

45

Extra seconds added when model is cold

MCP_CU_ADAPTIVE_TIMEOUT / MCP_CU_ADAPTIVE_WINDOW

true / 8

Learn the timeout from recent warm calls

MCP_CU_CALL_BUDGET_SECONDS

110

Total wall budget per tool call (0 = off)

MCP_CU_AGENT_CU_CMD / MCP_CU_AGENT_CU_TIMEOUT

agent-cu / 20

Command and timeout for UI automation

MCP_CU_HEALTH_HTTP / _HOST / _PORT

false / 127.0.0.1 / 8765

Optional HTTP health check server

MCP_CU_SYSTEM_PROMPT_FILE

bundled prompts/system_prompt.md

Override default system prompt

MCP_CU_SNAPSHOT_DETAILS

true

Read accessibility tree for Claude details

MCP_CU_SESSIONS_DIR

<project>/.sessions

Sessions and action log folder

MCP_CU_SESSION_TTL_HOURS

24

Hours before inactive session files are purged

MCP_CU_KEEP_ALIVE_IDLE / MCP_CU_KEEP_ALIVE_SESSION

3m / 10m

Model retention duration in memory

MCP_CU_SESSION_ACTIVE_MINUTES

10

Session recency window for keeping model alive

MCP_CU_MIN_FREE_MB

2048

Minimum free RAM in MB before unloading model

MCP_CU_MEMORY_WATCH / MCP_CU_MEMORY_WATCH_INTERVAL

true / 30

Background watcher to unload model under RAM pressure

MCP_CU_AUTOSTART_OLLAMA / MCP_CU_AUTOSTART_TIMEOUT

true / 30

Auto-start local Ollama if unreachable

MCP_CU_SAFETY_BLOCKLIST

""

Additional comma-separated blocklist words

MCP_CU_SAFETY_BLOCKLIST_EXTRA

""

Extra additional blocklist words

MCP_CU_ACTION_LOG_TTL_HOURS

24

Hours before old action audit records are purged

MCP_CU_RESOLVE_WITH_MODEL

true

Use local model to resolve ambiguous candidates (≤5)

MCP_CU_MAX_TYPE_CHARS

2000

Max characters allowed for type_text

MCP_CU_IMAGE_TIMEOUT

15.0

Timeout in seconds for window image capture

Optional HTTP health: MCP_CU_HEALTH_HTTP=1 (or --health-http) → GET http://127.0.0.1:8765/health (200 when ok, 503 otherwise).

Register the server

Codex – %USERPROFILE%\.codex\config.toml:

[mcp_servers.computer-use]
command = 'C:\Develop\mcp-computer-use\.venv\Scripts\mcp-computer-use.exe'
args = []
env = { MCP_CU_OLLAMA_URL = "http://127.0.0.1:11435", MCP_CU_MODEL = "gpt-oss:20b" }
startup_timeout_sec = 20
tool_timeout_sec = 120

Claude Code:

claude mcp add computer-use --scope user -e MCP_CU_OLLAMA_URL=http://127.0.0.1:11435 -- C:\Develop\mcp-computer-use\.venv\Scripts\mcp-computer-use.exe

Then add the AGENTS.md / CLAUDE.md snippet below so agents use it correctly.

How agents should call this server

The server sends these rules to clients on initialize (MCP instructions) and in the tool descriptions:

  • English only in question (translate the user's request), one short focused question per call (max 300 chars, MCP_CU_MAX_QUESTION_CHARS), pass app when known, step by step for bigger checks, and follow error.suggestion.

  • Read first: Use look_at_screen if unsure of window state or target labels.

  • Click by visible label: Pass visible UI labels (1–200 chars), never @eN refs.

  • Use steps for known sequences: Up to 10 labels (e.g. calculator keys).

  • Safety: Never set confirm_dangerous=true without explicit human approval in chat.

  • Do not use agent-cu directly to click or type unless the MCP tool fails.

  • Optionally pass client + session_id and reuse them for the whole task to get context and changed_since_last.

  • Call release_model() when the task is done.

  • Longer questions return QUESTION_TOO_LONG. Multi-part questions (3+ ? or a numbered/bulleted list) and mostly non-Latin questions are still answered, with a non-fatal hint.

Good

Bad

Is Claude working or finished?

מה קלוד עושה? (works, but returns hint: Ask in English for best results.)

What is Claude's last message about?

Is Claude done? Did tests pass? What commit? Did it build?

click(app="מחשבון", target="7")

click(app="מחשבון", target="@e12") (@eN refs change every snapshot)

type_text(app="מחשבון", target="שדה הזנה", text="123")

Sending keystrokes with Enter without human confirmation

Snippet for a global AGENTS.md / CLAUDE.md

Paste into %USERPROFILE%\.codex\AGENTS.md and/or %USERPROFILE%\.claude\CLAUDE.md (also in docs/AGENTS_SNIPPET.md):

## On-screen checks and actions (mcp-computer-use)
To see what is on screen or interact with app windows (e.g. "is Claude finished?", "click 7 in Calculator"), use the `computer-use` MCP tools (`look_at_screen`, `click`, `type_text`) instead of running agent-cu directly.

### Screen reading (`look_at_screen`)
- Write `question` in English, even if the user speaks another language.
- One short, focused question per call (under 300 chars). Pass `app` when known ("Claude", "ChatGPT", "מחשבון").
- For bigger checks go step by step: first "Is Claude working or finished?", then "What is Claude's last message about?", then details.
- Optional: pass `client="codex"` and a `session_id` (e.g. "task-1") to get context across calls and `changed_since_last`.
- Use `details` (project, session, branch, next_step, failures, files) directly from the result.
- Read first with `look_at_screen` if unsure about the current screen or target labels.
- Request `include_image=true` only when the text answer is not enough.

### App actions (`click`, `type_text`)
- **Click by visible label**: Pass the visible UI label (1–200 chars), never an `@eN` ref; element refs change on every snapshot.
- **Batches**: Prefer one click per call when exploring. Use `steps` for a known sequence of up to 10 labels (e.g. `["7", "+", "5", "="]`); execution stops at the first failure.
- **Text entry (`type_text`)**: Sets the value of an editable field directly without submitting (no keystrokes sent to other windows; Enter is never pressed).
- **Safety**: A default blocklist guards dangerous actions (Delete, Send, Pay, מחק, שלח, etc.). If an action returns `DANGEROUS_ACTION_NEEDS_CONFIRMATION`, **never set `confirm_dangerous=true` without explicit human approval in chat**.
- **CLI fallback**: Do not use `agent-cu` directly to click or type unless the tool fails.

### General
- To launch an app, run `powershell -ExecutionPolicy Bypass -File <repo>\scripts\cu-open.ps1 <exe|path|uri>` instead of `agent-cu open`, then use the returned `app` window title (e.g. `מחשבון`).
- Before a task, call `ping()` to verify the bridge. When done, call `release_model()` to free RAM.
- Follow `error.suggestion` on errors. Apply any returned `hint` on your next call.

Launching apps: scripts/cu-open.ps1

agent-cu open calc.exe --wait starts Calculator but then times out: it waits for an app literally named calc.exe, while UWP/packaged apps run inside ApplicationFrameHost with a localized title (e.g. מחשבון). cu-open.ps1 launches anything Start-Process can (exe name, full path, shell: / ms-settings: / calculator: URIs), polls the open windows every 500 ms until a new window appears (or an existing single-instance window comes to the front), checks that agent-cu snapshot -a <app> works, and prints one JSON line:

powershell -ExecutionPolicy Bypass -File <repo>\scripts\cu-open.ps1 calc.exe
# {"ok":true,"app":"מחשבון","title":"מחשבון","process":"ApplicationFrameHost","pid":16708,"seconds":1.8,"hint":"UWP app hosted by ApplicationFrameHost: use -a 'מחשבון' (the window title).","verified":true}
agent-cu snapshot -a 'מחשבון' -i -c --human

Options: -Args '<arguments>' (with -File, pass several arguments as one quoted string), -TimeoutSec 15, -NoVerify (skip the snapshot check). On timeout it prints ok:false with error, new_windows_seen and frontmost, and exits 1. Use the returned app with every agent-cu ... -a. It never closes or moves other windows. Output is UTF-8 (Hebrew titles are kept).

Usage examples

  • look_at_screen("Is Claude finished? What did it report?", "Claude")

  • click("מחשבון", steps=["7", "+", "5", "="])

  • type_text("מחשבון", "שדה הזנה", "100")

Development

src/mcp_computer_use/: server.py (MCP + CLI), core.py (logic), agent_cu.py, matching.py, safety.py, extractors/ (registry.py, codex_desktop.py, browser.py, editor.py, claude_code.py, generic.py), ollama_client.py, timeouts.py, config.py, errors.py, guidance.py (instructions + question validation), prompts/system_prompt.md. Tests mock subprocess and Ollama: pytest -q. Works with mcp 1.x (FastMCP) and 2.x (MCPServer).

Adding a profile

To add a new per-app extractor profile:

  1. Register the profile: Register via register_profile(name, matcher, extractor, snapshot_details) in src/mcp_computer_use/extractors/registry.py (and secondary window-title matching in select_profile in src/mcp_computer_use/extractors/__init__.py).

  2. Add anonymized fixtures: Place sanitized accessibility snapshot and text captures under tests/fixtures/<profile>/ (scrub personal data, usernames, tokens, and local paths).

  3. Fixture tests: Add at least 3 fixture tests (≥ 3 fixture tests) covering status detection, details extraction, and fallback/edge cases (e.g. tests/test_extractor_<profile>.py).

License

MIT


עברית

שרת MCP קטן לקריאת מסך ולביצוע פעולות בטוחות וממוקדות-חלון (click, type_text), שמאפשר לסוכני קוד (Codex, ‏Claude Code, ‏Cline, ‏Antigravity) לשאול "מה מופיע בחלון הזה?" ולקבל תשובת JSON של שתי שורות במקום אלפי טוקנים של טקסט גולמי מהחלון, וכן לבצע לחיצות והזנות טקסט באופן מאובטח ומפוקח.

הפרויקט מיועד לפרסום פומבי ב-GitHub (רישיון MIT). עדיין לא פורסם.

למה זה חוסך טוקנים

כשהסוכן מריץ agent-cu בעצמו, כל הטקסט של החלון נכנס להקשר שלו ונשלח שוב בכל צעד. בבדיקה שלנו, שאלה אחת כמו "קלוד סיים?" עלתה כ-206 אלף טוקנים, בערך 3% ממכסת 5 השעות של Plus.

השרת הזה עושה את הקריאה מקומית:

  1. ‏agent-cu text -a <App> קורא את החלון, בלי מודל.

  2. קוד שולף רק את המצב ואת ההודעה האחרונה באמצעות פרופילים ייעודיים לפי תוכנה (Claude Code, ‏Codex desktop, עורכי קוד, דפדפנים, או ברירת מחדל כללית). כשנייה וחצי.

  3. מודל מקומי ב-Ollama (ברירת מחדל gpt-oss:20b) מסכם את הטקסט הקצר. נמדד: 4 עד 8 שניות, עם תשובה נכונה.

  4. הסוכן מקבל כ-50 טוקנים של JSON.

נבדק גם qwen3:4b, אבל הוא ממשיך "לחשוב בקול", ולכן ברירת המחדל היא gpt-oss:20b. אפשר לשנות אותה.

NOTE

תובנת ביצועים ומדידה (18.10.2026): עבור חלונות קטנים או פשוטים (כגון מחשבון או עמוד אינטרנט קצר), קריאה ישירה של חלון באמצעות agent-cu text יכולה להיות זולה בטוקנים באותה מידה (~1,000–2,000 טוקנים). היתרון המשמעותי של השרת בא לידי ביטוי בחלונות גדולים ועמוסים (תוכנות צ'אט, עורכי קוד ו-IDEs), שבהם טקסט גולמי מגיע ל-40k עד 200k+ טוקנים, וכן כאשר שדות ה-details שנשלפים אוטומטית עונים ישירות על השאלה ללא צורך בניתוח חוזר של המודל.

הכלים

כלי

תיאור

look_at_screen(question, app=None, client=None, session_id=None, keep_warm=False, include_image=False)

קורא חלון אחד ועונה. לקריאה בלבד. ללא app, נבחרת התוכנה מהשאלה או החלון שבחזית. ‏client ו-session_id הם אופציונליים (ראו "סשנים"). העברת include_image=True מחזירה בנוסף צילום JPEG של החלון. שורת פקודה: --ask QUESTION [--app APP] [--image-out PATH].

click(app=None, target=None, steps=None, client=None, session_id=None, confirm_dangerous=False)

לוחץ על תווית גלויה, או על רצף של 1 עד 10 תוויות דרך steps. ללא app נבחר החלון שבחזית. נעצר בכישלון ראשון. שורת פקודה: --click APP TARGET, --click-steps APP STEP....

type_text(target, text, app=None, client=None, session_id=None, confirm_dangerous=False)

מזין ערך ישירות לשדה עריכה ללא שליחה (Enter אינו נלחץ). ללא app נבחר החלון שבחזית. מחליף תוכן קיים; לא נשלחות הקשות לחלונות אחרים. שורת פקודה: --type APP TARGET TEXT.

ping()

בדיקת דופק: מוודא שהשרת עונה, ש-Ollama המקומי זמין (ומפעיל אותו אם צריך), ושהמודל עונה pong. לא קורא מסך. מחזיר {ok, server, ollama, model_reply_ok, model, seconds, cold, error?}. הפינג הראשון יכול לקחת 30–50 שניות כשהמודל עוד לא טעון (cold). שורת פקודה: --ping.

release_model()

פורק את המודל מהזיכרון מיד ומחזיר כמה זיכרון שוחרר (freed_mb). שורת פקודה: --release.

health()

בודק אם Ollama זמין, אם המודל הורד ונטען, זיכרון, RAM פנוי, מדיניות keep_alive ואם agent-cu מותקן. שורת פקודה: --health.

מתי לקרוא (look_at_screen) ומתי ללחוץ או להקליד

  • קריאה תחילה: משתמשים ב-look_at_screen כדי לבחון את מצב המסך, לוודא תוצאות, או כשלא בטוחים אילו פקדים או תוויות קיימים בחלון. הכלי מיועד לקריאה בלבד וללא תופעות לוואי.

  • תווית גלויה, לעולם לא מזהי רפרנס: מעבירים את התווית הגלויה כפי שהיא מופיעה בממשק (1 עד 200 תווים), ולעולם לא מזהה רפרנס כדוגמת @eN. מזהי הרפרנס של עץ הנגישות משתנים בכל snapshot; שימוש ביעד בתבנית @eN נדחה עם שגיאת INVALID_TARGET.

  • פעולה בודדת מול רצף שלבים: מומלץ לבצע לחיצה אחת בכל קריאה בעת בדיקה או חקירה של הממשק. עבור רצף ידוע מראש (עד 10 תוויות, כגון מקשי מחשבון ["7", "+", "5", "="]), משתמשים בפרמטר steps. כל שלב מבצע snapshot רענן ועובר שער בטיחות; הרצף נעצר בכישלון הראשון.

  • הזנת טקסט ישירה (type_text): מזין ערך ישירות לשדה עריכה (תפקידי textfield, textarea, edit, combobox, textbox, document, searchfield) בחלון המבוקש. הפעולה מחליפה את תוכן השדה ללא הגשה (Enter לעולם אינו נלחץ, ולא נשלחות הקשות לחלונות אחרים). אורך הטקסט מוגבל על ידי max_type_chars (ברירת מחדל: 2,000 תווים).

צילום תמונת חלון אופציונלי (include_image)

כאשר מעבירים include_image=True, הכלי מחזיר את אותה תשובת JSON בתוספת מילון מטא-דאטה "image": {"width": int, "height": int, "bytes": int} ובלוק תמונה של MCP מסוג ImageContent (פורמט JPEG, רוחב מרבי של 1024 פיקסלים, איכות 70) של חלון היעד בלבד.

  • צילום שאינו מפריע (Non-intrusive): הצילום מתבצע באמצעות קריאת Win32 PrintWindow דרך סקריפט PowerShell מובנה (cu_capture.ps1). אף חלון אינו מקבל פוקוס, אינו מועבר לחזית, אינו מוזז ואינו משוחזר. הצילום פועל גם כאשר החלון מכוסה בחלונות אחרים, ובבדיקה שלנו אף כאשר סשן ה-Windows היה נעול.

  • טיפול בכשלים ובחלונות ממוזערים: אם החלון ממוזער, מוחזרת השגיאה IMAGE_WINDOW_MINIMIZED. במקרה של כשל בצילום (תמונה ריקה, חריגת זמן, חלון שלא נמצא או עמום), מוחזר פירוט השגיאה בתוך "image_error": {"code", "message", "retryable", "suggestion"} ותשובת הטקסט עדיין מוחזרת במלואה (ללא בלוק תמונה).

  • קודי שגיאה:

    • IMAGE_CAPTURE_FAILED: כשל בתהליך הצילום או שהחלון לא נמצא / זוהו מספר חלונות מתאימים (עמימות).

    • IMAGE_CAPTURE_BLANK: התמונה שהתקבלה הייתה ריקה/שחורה לחלוטין (למשל שכבת חומרה מואצת או חלון ממוזער).

    • IMAGE_WINDOW_MINIMIZED: חלון היעד ממוזער (יש לשחזר את החלון כדי לצלמו).

    • IMAGE_CAPTURE_TIMEOUT: תהליך הצילום חרג ממגבלת הזמן שנקבעה ב-image_timeout.

  • הגדרות: image_timeout (משתנה סביבה MCP_CU_IMAGE_TIMEOUT, ברירת מחדל: 15.0 שניות) קובע את זמן ההמתנה לצילום.

  • שורת פקודה: הפקודה mcp-computer-use --ask "What is open?" --app "מחשבון" --image-out snapshot.jpg שומרת את קובץ ה-JPEG לדיסק ומדפיסה את ה-JSON יחד עם מטא-דאטה של image או image_error.

  • ללא תלויות חיצוניות: מבוסס P/Invoke ישיר של Win32 מתוך PowerShell; אין צורך בספריות Python לעיבוד תמונה (כגון Pillow). ברירת המחדל היא False; כאשר היא כבויה, פלט הכלי וסכמת ה-MCP נותרים זהים לחלוטין וללא שינוי.

  • עלות טוקנים (Token cost): נמדד ב-18.10.2026 עם Codex CLI (קריאה בודדת ל-look_at_screen על מחשבון, קובץ JPEG בגודל 644×1067 כ-42KB): Codex דיווח על 120,991 / 145,588 טוקני קלט ללא התמונה ו-97,326 / 70,301 איתה. השונות בהקשר בין הרצה להרצה (±40k) גדולה יותר מכל עלות של תמונה בודדת, ולכן לא ניתן היה למדוד את עלות התמונה הבודדת בצורה זו. בכל מקרה יש להתייחס לתמונות כיקרות (בדרך כלל כ-1,000–2,000 טוקנים לתמונה במודלי ראייה) ולבקש include_image=True אך ורק כאשר תשובת הטקסט אינה מספקת (בדיקת פריסה, תרשימים, באגים חזותיים).

מדרג התאמת תוויות ובחירת מועמדים

השרת מאתר פקדים בממשק לפי מדרג עדיפויות קפדני:

  1. התאמה מדויקת (Exact): שוויון מחרוזות מדויק כולל אותיות גדולות/קטנות (tier 1, ציון 1.0, how: "exact").

  2. התאמה מנורמלת (Normalized): התעלמות מגודל אותיות, נרמול NFKC ביוניקוד, הסרת ניקוד וטעמים בעברית (U+0591–U+05C7), המרת מקף עברי (־ U+05BE) לרווח, המרת גרש (׳ U+05F3) וגרשיים (״ U+05F4) לתווי ASCII תקניים ' ו-" (מומרים ולא נמחקים), הסרת סימני כיווניות ורוחב-אפס בלבד: U+200B–U+200F, U+061C, U+202A–U+202E, U+2066–U+2069, U+FEFF (בדיקת רשימת החסימה בבטיחות מסירה בנפרד את כל תווי ה-Cf), והסרת סיומת …, ... או : בלבד בסוף התווית (tier 2, ציון 0.95, how: "normalized").

  3. מילים נרדפות ומזהים (Synonyms & IDs): מילים נרדפות לספרות ולפעולות חשבון בעברית ובאנגלית (למשל: "7" ↔ "seven" ↔ "שבע", "+" ↔ "plus" ↔ "ועוד", "-" ↔ "−" (U+2212) ↔ "minus" ↔ "פחות", "*" ↔ "×" ↔ "multiply" ↔ "כפול" ↔ "הכפל ב", "/" ↔ "÷" ↔ "divide" ↔ "חלקי" ↔ "חלק ב", "=" ↔ "equals" ↔ "שווה", "." ↔ "decimal separator" ↔ "תו הפרדה עשרוני"), או התאמה למזהה הנגישות id של הפקד (tier 3, ציון 0.9). שימו לב ש-- תואם גם לסימן המינוס "−" (U+2212). ביטויי תפקיד (כגון button 7, כפתור 7, field Search, שדה חיפוש) מופרדים כדי למנוע עמימות.

  4. התאמות חלשות (Weak matches): התאמת ערך נוכחי (live value), הכלה של מילים (contains), או דמיון עמום (fuzzy similarity) של 0.80 ומעלה (tier 4-5). התאמות חלשות לעולם אינן לוחצות מעצמן באופן אוטומטי; הן מחזירות מועמדים, וכאשר resolve_with_model מופעל המודל המקומי רשאי לבחור אחד מהם (עד 5 מועמדים, match: "model"), והוא נלחץ רק לאחר בדיקת הבטיחות; אחרת מוחזרים עד 5 מועמדים עם השגיאה TARGET_AMBIGUOUS.

כלל בטיחות ורשימת חסימה (Safety Rule & Blocklist)

כדי למנוע פעולות הרסניות בשוגג, מופעלת תמיד רשימת חסימה לפני כל לחיצה או הקלדה:

  • רשימת חסימה ברירת מחדל (נאכפת תמיד ולא ניתנת לביטול):

    • באנגלית: Delete, Remove, Send, Allow, Approve, Accept, Pay, Buy, Purchase, Submit, Confirm, Publish, Merge, Uninstall, Format.

    • בעברית ביטויים: הסר התקנה.

    • בעברית פעולות בסיס: מחק, הסר, שלח, אשר, אפשר, שלם, קנה, פרסם.

    • בעברית ציווי רבים: מחקו, הסירו, שלחו, אשרו, אפשרו, שלמו, קנו, פרסמו.

    • בעברית נטיות ושמות פעולה: מחיקה, למחוק, הסרה, להסיר, שליחה, לשלוח, אישור, לאשר, לאפשר, תשלום, לשלם, קנייה, לקנות, פרסום, לפרסם.

  • הגדרות ומשתני סביבה: הגדרות [safety] blocklist / blocklist_extra בקובץ TOML או משתני הסביבה MCP_CU_SAFETY_BLOCKLIST / MCP_CU_SAFETY_BLOCKLIST_EXTRA יכולים רק להוסיף מילים לרשימה. מילות ברירת המחדל נאכפות תמיד.

  • בדיקה מקדימה: שם היעד נבדק תחילה (עוד לפני צילום ה-snapshot), ולאחר מכן נבדק שוב שם הפקד שאותר.

  • תהליך אישור: אם נמצאה התאמה למילה חסומה והפרמטר confirm_dangerous=false (ברירת המחדל), הפעולה נחסמת ומוחזרת השגיאה DANGEROUS_ACTION_NEEDS_CONFIRMATION יחד עם would_click ו-matched_rule.

  • הנחיה קריטית: הסוכן הפונה חייב לשאול את המשתמש האנושי ולקבל אישור מפורש בצ'אט לפני קריאה חוזרת עם confirm_dangerous=true.

  • פעולות שאינן חסומות כברירת מחדל: פעולות ניווט נפוצות כגון "Close" / "Exit" (ובעברית "סגור" / "יציאה") אינן חסומות כברירת מחדל (ניתן להוסיפן לרשימת החסימה בהגדרות לפי הצורך).

יומן פעולות לביקורת (.sessions/actions.log)

כל פעולת לחיצה והקלדה מתועדת בקובץ JSON Lines בנתיב <project>/.sessions/actions.log (או לפי MCP_CU_SESSIONS_DIR):

  • תוקף רשומות (TTL): רשומות ישנות מ-24 שעות (action_log_ttl_hours, ברירת מחדל 24.0) נמחקות אוטומטית ובאופן אטומי בעת כל כתיבה.

  • סנכרון תהליכים: נעילה בטוחה בין תהליכים וחוטים באמצעות קובץ נעילה ייעודי (actions.log.lock).

  • שדות מורשים בלבד: time, client, session_id, app, action, target, ref, name, role, result, confirmed, error_code, text_len, hint.

  • פרטיות וטיהור מידע: הטקסט המוקלד לעולם אינו נרשם ביומן — נרשם רק אורכו במספר תווים (text_len). בנוסף, מנגנון טיהור אוטומטי סורק את כל שדות המחרוזת ומחליף ב-<redacted> כל שדה המכיל את הטקסט המוקלד או מקטעים ממנו באורך 6 תווים ומעלה.

קודי שגיאה

קוד שגיאה

תיאור

TARGET_NOT_FOUND

לא נמצא פקד ממשק מתאים בחלון (מוחזרים עד 5 מועמדים קרובים כהצעה).

TARGET_AMBIGUOUS

נמצאו מספר פקדים מתאימים (מוחזרים עד 5 candidates להבהרה).

TARGET_NOT_EDITABLE

הפקד אותר אך סוגו אינו שדה עריכה (type_text).

INVALID_TARGET

היעד ריק, ארוך מ-200 תווים, או מזהה רפרנס @eN; העברת שניהם יחד או אף אחד מהם מבין target ו-steps; מספר שלבים לא תקין ב-steps (לא 1–10) או תווית שלב לא תקינה; או ערך text שאינו מחרוזת ב-type_text.

TEXT_TOO_LONG

הטקסט חורג ממגבלת max_type_chars (ברירת מחדל: 2,000 תווים).

DANGEROUS_ACTION_NEEDS_CONFIRMATION

היעד או שם הפקד (target or element) תואם למילה ברשימת החסימה. נדרש אישור אנושי מפורש לפני קריאה עם confirm_dangerous=true.

APP_NOT_FOUND

חלון התוכנה לא נמצא, שם תוכנה ריק, או שם המכיל תווים מיוחדים של מעטפת הפקודות.

AGENT_CU_NOT_INSTALLED

הכלי agent-cu אינו מותקן ב-PATH.

AGENT_CU_FAILED

פקודת הנגישות נכשלה.

OLLAMA_UNREACHABLE

שירות Ollama אינו נגיש ולא הצליח להפעיל את עצמו.

MODEL_NOT_FOUND

המודל המבוקש טרם הורד ב-Ollama.

MODEL_TIMEOUT

פניית המודל חרגה ממגבלת הזמן.

MODEL_FAILED

פעולת המודל נכשלה.

QUESTION_TOO_LONG

השאלה ארוכה מ-max_question_chars (ברירת מחדל: 300 תווים / default 300).

EMPTY_QUESTION

מחרוזת השאלה ריקה.

IMAGE_CAPTURE_FAILED

צילום תמונת החלון נכשל, החלון לא נמצא או שנמצאו מספר חלונות מתאימים (עמימות).

IMAGE_CAPTURE_BLANK

התמונה שהתקבלה ריקה לחלוטין (החלון עשוי להיות ממוזער, בעל האצת חומרה או מכוסה).

IMAGE_WINDOW_MINIMIZED

חלון היעד ממוזער. יש לשחזר את החלון לפני בקשת תמונה.

IMAGE_CAPTURE_TIMEOUT

צילום תמונת החלון חרג ממגבלת הזמן הקצוב (image_timeout).

אפשרויות שורת הפקודה (CLI) והערת אבטחה

ניתן להפעיל פעולות ישירות משורת הפקודה:

# לחיצה על תווית בודדת
mcp-computer-use --click "מחשבון" "7"

# רצף שלבים (1 עד 10 תוויות)
mcp-computer-use --click-steps "מחשבון" "7" "+" "5" "="

# הזנת טקסט לשדה עריכה
mcp-computer-use --type "מחשבון" "שדה הזנה" "123"

# אישור פעולה מסוכנת רק לאחר קבלת אישור אנושי מפורש
mcp-computer-use --click "MyApp" "מחק" --confirm-dangerous
WARNING

הערת אבטחה להזנת טקסט ושורת הפקודה: גם ה-CLI (באפשרות --type) וגם כלי ה-MCP (type_text) מעבירים את הטקסט ל-agent-cu כארגומנט (agent-cu type -s REF -a APP -- TEXT), כך שהטקסט גלוי לתהליכים מקומיים אחרים במערכת בזמן ריצתו (לזמן קצר, למשל במנהל המשימות או ברשימת התהליכים). בנוסף, שימוש ב-CLI חושף את הטקסט בשורת הפקודה ובהיסטוריית הפקודות של המעטפת (shell). אין להקליד סיסמאות או מידע סודי/רגיש באמצעותו.

דוגמאות למחשבון (MCP ו-CLI)

בתוכנות UWP ואפליקציות מודרניות של Windows (הרצות בתוך ApplicationFrameHost), שם התוכנה הוא כותרת החלון המתורגמת (למשל Calculator במערכת באנגלית, או מחשבון במערכת בעברית; פתיחה עם cu-open.ps1 calc.exe).

קריאות כלי MCP (JSON):

// לחיצה בודדת
{
  "app": "מחשבון",
  "target": "7"
}

// רצף שלבים ידוע מראש (עד 10)
{
  "app": "מחשבון",
  "steps": ["7", "+", "5", "="]
}

// הזנת ערך לשדה עריכה
{
  "app": "מחשבון",
  "target": "שדה הזנה",
  "text": "42"
}

הפעלה משורת הפקודה (CLI):

mcp-computer-use --click "מחשבון" "7"
mcp-computer-use --click-steps "מחשבון" "7" "+" "5" "="

פרופילים ייעודיים לפי תוכנה (Per-app profiles)

בעת קריאת חלון באמצעות look_at_screen, השרת מתאים ובוחר פרופיל חילוץ ייעודי לפי שם התוכנה (app_name) וכותרת החלון (window_title). בדיקת הפרופילים מתבצעת בסדר עדיפויות קפדני (ההתאמה הראשונה שמתקיימת נבחרת):

$$\text{claude_code} \longrightarrow \text{codex_desktop} \longrightarrow \text{editor} \longrightarrow \text{browser} \longrightarrow \text{generic}$$

  1. claude_code: נבחר כאשר מחרוזת "claude" מופיעה בשם התוכנה (באותיות קטנות).

  2. codex_desktop: נבחר כאשר שם התוכנה הוא chatgpt, codex, codex desktop או openai.codex (אפליקציית Windows של ChatGPT), או כאשר כותרת החלון כוללת codex.

  3. editor: נבחר עבור עורכי קוד ממשפחת VS Code לפי שם התוכנה (code, code.exe, code - oss, code-oss, code - insiders, cursor, antigravity ide, windsurf, vscodium), או לפי סיומת ותבנית כותרת החלון ( - Visual Studio Code, - Cursor, - Antigravity IDE -, - Windsurf, - VSCodium, - Code - Insiders).

  4. browser: נבחר עבור דפדפנים נתמכים לפי שם התוכנה (Chrome: chrome, google chrome; Edge: msedge, edge, microsoft edge; Brave: brave; Firefox: firefox, mozilla firefox), או לפי סיומת כותרת החלון ( - Google Chrome, - Microsoft Edge, microsoft edge, - Mozilla Firefox, - Brave).

  5. generic: ברירת המחדל כאשר אף פרופיל ייעודי אינו מתאים.

פלט לפי פרופיל (סטטוס עליון ושדות details)

כל קריאה ל-look_at_screen מחזירה סטטוס עליון (status: ‏working, finished, waiting, error או unknown) יחד עם אובייקט details אופציונלי שממולא על ידי קוד (מתוך טקסט הנגישות ועץ ה-snapshot, ללא מודל; לביטול צילום snapshot נוסף: MCP_CU_SNAPSHOT_DETAILS=0):

  • Claude Code (claude_code):

    • סטטוס עליון (status): ‏working, finished או unknown.

    • מפתחות details: ‏project, שם הסשן (session), ענף (branch), תיקייה (folder), מודל (model), קבצים (files), משימות רקע (background_tasks), ניצול הקשר (context_used), כפתורי אישור ממתינים (waiting_for_user), שאלת אישור (waiting_prompt), כשלים (failures), הצעות לצעד הבא באנגלית ובעברית (next_step), ושאלות שהסוכן מפנה למשתמש (asks_user).

  • Codex desktop (codex_desktop, תוכנת Windows בשם ChatGPT):

    • סטטוס עליון (status): ‏working, finished, waiting או unknown — נקבע אך ורק מתוך פקדי ממשק (UI controls) (כפתור Stop, כפתור העתקה Copy יחד עם משוב Good/Bad response, ותיבות אישור; טקסט חופשי בתוך תור העוזר לעולם אינו נחשב כאות סטטוס).

    • מפתחות details:

      • project: שם הפרויקט או סביבת העבודה (מתוך "What should we work on in...", "Change project: ...", או מפקדי התיקייה/הפרויקט בכותרת השרשור).

      • session: כותרת השיחה / השרשור (מכותרת ה-heading או כותרת השרשור).

      • mode: מצב עבודה נוכחי (מתוך "Switch mode, current mode: ...").

      • projects: רשימת פרויקטים בסרגל הצד (עד 8, מאומתים מול פקדי פעולות פרויקט).

      • recent_chats: רשימת שיחות אחרונות בסרגל הצד (עד 5, מאומתות מול פקדי נעיצה וארכוב).

      • needs_attention: ערך בוליאני true כאשר מופיע כפתור "View activity, needs attention".

      • next_step: נשלף מתוך "Next steps:" או "השלב הבא:".

      • failures: שגיאות וכשלים שזוהו באמצעות find_failures.

      • waiting_prompt (ו-waiting_for_user=true): שאלת האישור כשהתוכנה ממתינה לאישור משתמש (כגון "Allow command?", "Approve command?"), מאומתת מול צמד כפתורי אישור/דחייה (approve/deny).

  • Editor (editor, עורכי קוד VS Code / Cursor / Antigravity IDE / Windsurf / VSCodium):

    • סטטוס עליון (status): ‏waiting אם ממתינה שאלת אישור, error אם זוהו כשלים, אחרת unknown.

    • מפתחות details:

      • project: שם התיקייה או הפרויקט (מתוך כותרת החלון או עץ ה-Explorer).

      • file: הקובץ הפעיל (מתוך כותרת החלון או לשונית עורך פעילה יחידה).

      • waiting_prompt (ו-waiting_for_user=true): שאלת אישור עבור דיאלוגים אמיתיים (שאלת אמון בספרייה "Do you trust the authors...", התקנת הרחבות, או שמירת קובץ), מאומתת מול כפתורי הפעולה של הדיאלוג.

      • failures: שגיאות ואבחונים (Error: ..., Exception:) ומספר שגיאות מתוך חלונית Problems או מהרצת הטרמינל האחרונה (פלט ישן שקדם לפקודת מעטפת חדשה או לסיכום בדיקות מאוחר יותר מושמט אוטומטית).

      • next_step: הצעות לצעד הבא מתוך שורות הראיות.

  • Browser (browser, דפדפנים Chrome / Edge / Brave / Firefox):

    • סטטוס עליון (status): ‏error בעמודי שגיאת רשת (כגון DNS probe, חיבור נדחה, אין אינטרנט); אחרת unknown.

    • מפתחות details:

      • page_title (ו-title): כותרת העמוד נקייה מסיומות דפדפן ומקטעי פרופיל Edge.

      • url: כתובת ה-URL הנוכחית מתוך שורת הכתובות או שורות הטקסט העליונות.

      • tab: כותרת הלשונית הפעילה (ללא תגיות צריכת זיכרון).

      • headings: עד 5 כותרות עמוד מתוך אזור תוכן העמוד (RootWebArea) או מהטקסט.

      • failures: שגיאות וכשלים מתוך גוף המסמך.

      • next_step: צעדים הבאים מתוך תוכן העמוד.

      • מסנן אוטומטית את סרגלי הדפדפן (toolbars, רצועת לשוניות, שורת כתובת, סרגל מועדפים) ומחלץ רק את תוכן עמוד האינטרנט.

  • Generic (generic):

    • סטטוס עליון (status): תמיד unknown.

    • מפתחות details: כשלים (failures) שזוהו ב-30 השורות האחרונות של טקסט הסוף הנשלף (אם קיימים).

הכלל השמרני (Conservative rule)

כל המחלצים פועלים לפי עיקרון שמרני מובהק: החזרת סטטוס unknown ושמירת תוכן לא מסווג במקום לנחש או להסיק מצב מטקסט חופשי ועמום.

הערות מגבלה (Limitations)

  • חשיפת תוכן בדפדפנים: דפדפנים עשויים שלא לחשוף תוכן עמוד למנגנון ה-UI Automation כאשר סשן ה-Windows נעול או כשחלון הדפדפן ממוזער (עץ הנגישות חושף במצב זה רק את מעטפת הדפדפן או אזור מסמך ריק).

  • כללי מצב השרשור ב-Codex desktop: כללי זיהוי מצב השרשור נבנו ותוקפו על גבי דגימות סינתטיות ועשויים לדרוש כיול והתאמות מול עדכוני גרסה עתידיים של האפליקציה.

הפעלה אוטומטית של Ollama

אם OLLAMA_URL מצביע על המחשב הזה (127.0.0.1 או localhost) ו-Ollama לא עונה, השרת מפעיל בעצמו ollama serve ברקע, בחלון מוסתר, עם OLLAMA_HOST=127.0.0.1:<הפורט מ-OLLAMA_URL> רק לתהליך הזה. ה-OLLAMA_HOST הגלובלי שלך (למשל ה-Mac) לא משתנה. אחר כך הוא בודק עד 30 שניות ש-/api/tags עונה. השרת שהופעל ממשיך לרוץ גם אחרי שה-MCP host נסגר: ב-Windows הוא מופעל עם CREATE_BREAKAWAY_FROM_JOB, ואם ה-job של ה-host חוסם את זה (למשל codex exec) הוא מופעל דרך WMI Win32_Process.Create. השיטה מדווחת בשדה method, והפלט נכתב ל-.sessions/ollama-autostart.log.

  • הבדיקה נעשית בכל קריאה בלי סשן, ובקריאה הראשונה של כל סשן, לא בכל קריאה בתוך סשן. אם קריאה באמצע סשן נכשלת עם OLLAMA_UNREACHABLE, השרת מפעיל את Ollama פעם אחת ומנסה שוב פעם אחת.

  • בדיקת פורט וקובץ נעילה (.sessions/ollama-autostart.lock) מונעים הפעלה כפולה.

  • את ollama הוא מחפש ב-PATH או ב-%LOCALAPPDATA%\Programs\Ollama\ollama.exe.

  • ‏MCP_CU_AUTOSTART_OLLAMA=0 מכבה את ההפעלה האוטומטית; ‏MCP_CU_AUTOSTART_TIMEOUT (ברירת מחדל 30). ‏health() מדווח ollama_autostarted.

שחרור זיכרון חכם

  • קריאה בודדת בלי סשן פעיל: המודל נשאר טעון 3 דקות (MCP_CU_KEEP_ALIVE_IDLE).

  • כשיש סשן פעיל (קובץ ב-.sessions שעודכן ב-10 הדקות האחרונות) או כשנשלח keep_warm=true: 10 דקות (MCP_CU_KEEP_ALIVE_SESSION). המודל משתחרר 10 דקות אחרי הקריאה האחרונה.

  • לחץ זיכרון: לפני כל קריאה ואחריה נבדק כמה RAM פנוי. אם נשארו פחות מ-2048MB (MCP_CU_MIN_FREE_MB, ‏0 מכבה), המודל נפרק מיד אחרי התשובה, גם באמצע סשן. בנוסף, חוט רקע בשרת בודק כל 30 שניות כשהמודל טעון ועושה אותו דבר (MCP_CU_MEMORY_WATCH=1).

  • כדאי שהלקוח יקרא ל-release_model() בסוף המשימה. הכלי פורק את המודל מיד ומחזיר כמה זיכרון שוחרר (freed_mb). בכל תשובה יש שדה memory.

סשנים (הקשר בין קריאות, אופציונלי)

‏client (שם הלקוח, למשל codex) ו-session_id (שם שהלקוח בוחר, למשל fix-ui) הם אופציונליים. מותרים רק A-Z a-z 0-9 _ -, עד 64 תווים.

  • בלעדיהם כל קריאה עומדת בפני עצמה: השרת קורא את כל המסך מחדש, אי אפשר לשאול "מה השתנה", ולא נכתב שום קובץ. אם לקוח שואל כמה פעמים ברצף בלי סשן, מוחזר hint שמציע להוסיף אותו.

  • איתם השרת שומר קובץ JSON קטן אחד לכל זוג, ‏<project>/.sessions/{client}__{session_id}.json, עם האפליקציה, הפרויקט, הסשן, ההודעה האחרונה, הצעד הבא, המצב, 5 השאלות האחרונות עם תשובות קצרות וזמן העדכון. בכל קריאה השרת קורא את הקובץ ואת המסך, משווה ביניהם, עונה רק על מה שנשאל, מחזיר changed_since_last ומעדכן את הקובץ. אם נשאלה אותה שאלה והמסך לא השתנה, התשובה נלקחת מהקובץ בלי לפנות למודל (cached: true).

  • ‏session_id חדש מחליף את הקודם של אותו לקוח, והקובץ הקודם נמחק. לכל לקוח יש תמיד קובץ פעיל אחד. ‏session_id ללא client משתמש בלקוח ברירת המחדל default.

  • קבצים שלא עודכנו 24 שעות נמחקים בכל קריאה (MCP_CU_SESSION_TTL_HOURS). את התיקייה אפשר לשנות עם MCP_CU_SESSIONS_DIR. שום דבר לא נשמר בזיכרון.

במקרה של כישלון חוזר error עם code, ‏message, ‏retryable ו-suggestion, ולצדו extracted, הטקסט הקצר שנשלף, כך שהסוכן יכול להמשיך גם בלי המודל.

זמן קצוב חכם: בסיס, ועוד תוספת לכל 1,000 תווים, בין מינימום למקסימום. אם המודל עוד לא טעון בזיכרון, מתווספת הקצבה לטעינה.

זמן קצוב מסתגל (adaptive_timeout = true, ברירת מחדל): אחרי כל קריאה מוצלחת למודל נרשם משך הזמן שלה. קריאות "חמות" נשמרות בחלון של adaptive_window (8) הקריאות האחרונות; קריאות שכללו טעינה קרה נשמרות בנפרד ולא משמשות לחישוב. הזמן הבא הוא max(2 × p90, timeout_min) ועוד התוספת לכל 1,000 תווים, בתחום [timeout_min, timeout_max], ועוד cold_load_extra בטעינה קרה. בלי דגימות משתמשים בנוסחה הקבועה. אחרי MODEL_TIMEOUT הזמן הבא מוכפל פי 1.5 (עד timeout_max), והצלחה מאפסת את ההגדלה. ההיסטוריה נשמרת בקובץ timing_stats.json בתיקיית ה-sessions, כך שגם תהליך חדש (כל ריצה של codex exec) מתחיל איתה; קובץ חסר או פגום פשוט מתעלמים ממנו. adaptive_timeout = false מחזיר את הנוסחה הקבועה.

תקציב לקריאה (call_budget_seconds, ברירת מחדל 110, 0 מבטל): סך הזמן לכל קריאת כלי, מתחילתה, כדי שהתשובה או השגיאה המובנית יחזרו לפני שהמארח יחתוך (ב-Codex ‏tool_timeout_sec = 120). ההמתנה להפעלה האוטומטית של Ollama מתקצרת כדי להשאיר זמן למודל, וכל זמן קצוב של המודל (look_at_screen כולל הניסיון החוזר, ping, ובחירת יעד ב-click) הוא min(מחושב, תקציב − זמן שעבר). אם נשארו פחות מ-5 שניות, חוזר מיד MODEL_TIMEOUT עם הצעה לנסות שוב. התוצאה של look_at_screen כוללת timing עם timeout_seconds, ‏timeout_source ‏(static / adaptive / bumped), ‏samples ו-budget_capped.

התקנה ב-Windows (PowerShell)

דרישות: Python 3.10 ומעלה, ‏Node עם npm i -g agent-cu, ו-Ollama.

cd C:\Develop\mcp-computer-use
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -e ".[dev]"
pytest -q

Ollama

כתובת ברירת המחדל היא http://127.0.0.1:11435. זה מופע מקומי על פורט נפרד, כי ה-OLLAMA_HOST הגלובלי שלך מפנה ל-Mac.

$env:OLLAMA_HOST = "127.0.0.1:11435"; ollama serve      # בחלון נפרד
$env:OLLAMA_HOST = "127.0.0.1:11435"; ollama pull gpt-oss:20b
mcp-computer-use --health
mcp-computer-use --ask "Is Claude finished?" --app Claude

הגדרות

ההגדרות נקבעות לפי סדר עדיפות: ברירות המחדל, מעליהן קובץ TOML, ומעל הכול משתני סביבה. פירוט מלא בטבלה בחלק האנגלי ובקובץ mcp-computer-use.example.toml. משתנים חשובים נוספים עבור מנגנון הבטיחות:

  • MCP_CU_SAFETY_BLOCKLIST ו-MCP_CU_SAFETY_BLOCKLIST_EXTRA: מוסיפים מילים חסומות לרשימת ברירת המחדל.

  • MCP_CU_ACTION_LOG_TTL_HOURS: זמן שימור רשומות ביומן הפעולות בשעות (ברירת מחדל: 24).

  • MCP_CU_RESOLVE_WITH_MODEL: שימוש במודל מקומי להכרעה בין מועמדים עמומים (ברירת מחדל: true).

  • MCP_CU_MAX_TYPE_CHARS: אורך טקסט מרבי להזנה ב-type_text (ברירת מחדל: 2000).

  • MCP_CU_IMAGE_TIMEOUT: זמן קצוב בשניות לצילום תמונת חלון (ברירת מחדל: 15.0).

  • MCP_CU_TIMEOUT_BASE / _PER_1K_CHARS / _MIN / _MAX: זמן ההמתנה לתשובת המודל, base + per_1k × תווים/1000 בתחום [min, max] (ברירות מחדל: 30 / 4 / 20 / 90 שניות). MCP_CU_COLD_LOAD_EXTRA (ברירת מחדל: 45) מתווסף כשהמודל לא טעון. MCP_CU_ADAPTIVE_TIMEOUT / MCP_CU_ADAPTIVE_WINDOW (ברירות מחדל: true / 8) וגם MCP_CU_CALL_BUDGET_SECONDS (ברירת מחדל: 110). תשובה של gpt-oss:20b טעון לוקחת כ-12 שניות במחשב נייד (~11 טוקנים לשנייה), כך שיש מרווח נדיב.

את בדיקת התקינות דרך HTTP מפעילים עם MCP_CU_HEALTH_HTTP=1, ואז היא זמינה בכתובת GET http://127.0.0.1:8765/health.

רישום ב-Codex וב-Claude Code

ב-Codex מוסיפים את הבלוק [mcp_servers.computer-use] לקובץ %USERPROFILE%\.codex\config.toml. ב-Claude Code מריצים claude mcp add computer-use .... הדוגמאות המדויקות מופיעות בחלק האנגלי. כדאי להוסיף גם ל-AGENTS.md או ל-CLAUDE.md את קטע ההוראות מתוך docs/AGENTS_SNIPPET.md.

איך סוכנים צריכים לפנות לשרת

השרת שולח את הכללים האלה ללקוח כבר בהתחברות (instructions) וגם בתיאורי הכלים:

  • את question כותבים באנגלית בלבד. הסוכן מתרגם בעצמו את מה שהמשתמש ביקש.

  • שאלה אחת קצרה וממוקדת בכל קריאה, עד 300 תווים (אפשר לשנות ב-MCP_CU_MAX_QUESTION_CHARS).

  • כשהתוכנה ידועה, מעבירים app.

  • בדיקה גדולה מפצלים לשלבים: קודם המצב, אחר כך הפרטים.

  • קריאה תחילה: קוראים עם look_at_screen כאשר לא בטוחים במצב החלון או בתוויות הפקדים.

  • לחיצה לפי תווית גלויה: מעבירים תווית גלויה (1 עד 200 תווים), לעולם לא מזהי רפרנס @eN (המשתנים בכל snapshot).

  • רצף שלבים ידוע מראש: משתמשים ב-steps לרצף של עד 10 צעדים ידועים (למשל מקשי מחשבון).

  • בטיחות: לעולם אין להעביר confirm_dangerous=true ללא קבלת אישור אנושי מפורש בצ'אט.

  • שימוש ב-agent-cu: אין להריץ את agent-cu ישירות ללחיצה או להקלדה אלא אם הכלי נכשל.

  • מבקשים include_image=true אך ורק כאשר תשובת הטקסט אינה מספקת (מבנה פריסה, תרשימים, באגים חזותיים).

  • אפשר לשלוח client ו-session_id ולהשתמש באותו זוג לאורך כל המשימה לקבלת הקשר ו-changed_since_last.

  • בסוף המשימה קוראים ל-release_model().

  • כשחוזרת שגיאה, פועלים לפי suggestion.

שאלה ארוכה מדי מחזירה QUESTION_TOO_LONG. שאלה מרובת חלקים, או שאלה שכתובה ברובה לא באותיות לטיניות (למשל עברית), עדיין מקבלת תשובה, ואיתה hint עם הצעה לשיפור.

טובות:

  • look_at_screen("Is Claude working or finished?", "Claude")

  • click("מחשבון", target="7")

  • type_text("מחשבון", target="שדה הזנה", text="123")

פחות טובות:

  • look_at_screen("מה קלוד עושה?") (עובד, אך מוחזר hint לשאול באנגלית)

  • click("מחשבון", target="@e12") (מזהי רפרנס נדחים; יש להעביר תווית גלויה)

  • ביצוע פעולה חסומה עם confirm_dangerous=true ללא אישור מפורש מהמשתמש האנושי

את קטע ההוראות לסוכנים (באנגלית, בחלק האנגלי וגם בקובץ docs/AGENTS_SNIPPET.md) מדביקים בקובץ AGENTS.md הגלובלי של Codex או בקובץ CLAUDE.md של Claude Code.

פתיחת תוכנות: scripts/cu-open.ps1

הפקודה agent-cu open calc.exe --wait פותחת את המחשבון, אבל נכשלת בזמן קצוב: היא מחכה לתוכנה בשם calc.exe, בזמן שתוכנות UWP רצות בתוך ApplicationFrameHost עם כותרת מתורגמת (למשל מחשבון). הסקריפט cu-open.ps1 פותח כל מה ש-Start-Process יודע לפתוח: שם קובץ, נתיב מלא, או כתובות כמו ms-settings: ו-calculator:. כל חצי שנייה הוא בודק אם נפתח חלון חדש (או אם חלון קיים של תוכנה שרצה במופע יחיד עבר לחזית), מוודא ש-agent-cu snapshot -a <app> עובד, ומדפיס שורת JSON אחת עם ok, ‏app (השם לשימוש ב-agent-cu -a), ‏title, ‏process, ‏pid, ‏seconds ו-hint.

powershell -ExecutionPolicy Bypass -File <repo>\scripts\cu-open.ps1 calc.exe

אפשרויות: -Args '<ארגומנטים>' (עם -File מעבירים כמה ארגומנטים כמחרוזת אחת במרכאות), ‏-TimeoutSec 15, ו--NoVerify לדילוג על הבדיקה. אם לא נפתח חלון בזמן, מוחזר ok:false עם הסבר, החלונות החדשים שנראו והחלון שבחזית. הסקריפט לא סוגר ולא מזיז חלונות אחרים, והפלט ב-UTF-8 כך שכותרות בעברית נשמרות. סוכנים צריכים לפתוח תוכנות תמיד דרך cu-open.ps1 ולא דרך agent-cu open.

דוגמאות שימוש

  • look_at_screen("Is Claude finished?", "Claude")

  • click("מחשבון", steps=["7", "+", "5", "="])

  • type_text("מחשבון", "שדה הזנה", "100")

פיתוח

מבנה הקבצים ב-src/mcp_computer_use/: server.py (שרת MCP ו-CLI), core.py (לוגיקה ראשית), agent_cu.py, matching.py, safety.py, חבילת extractors/ (registry.py, codex_desktop.py, browser.py, editor.py, claude_code.py, generic.py), ollama_client.py, timeouts.py, config.py, errors.py, guidance.py, prompts/system_prompt.md. הרצת בדיקות עם pytest -q. תומך ב-mcp 1.x ו-2.x.

הוספת פרופיל חדש (Adding a profile)

כדי להוסיף פרופיל מחלץ עבור אפליקציה חדשה:

  1. רישום הפרופיל: רושמים באמצעות register_profile(name, matcher, extractor, snapshot_details) בקובץ src/mcp_computer_use/extractors/registry.py (והתאמה משנית לפי כותרת חלון ב-select_profile ב-src/mcp_computer_use/extractors/__init__.py).

  2. הוספת קובצי בדיקה (fixtures): מוסיפים צילומי snapshot וטקסט אנונימיים תחת tests/fixtures/<profile>/ (ללא מידע אישי, שמות משתמש, טוקנים או נתיבים מקומיים).

  3. בדיקות מבוססות fixtures: כותבים לפחות 3 בדיקות (≥ 3 fixture tests) המאמתות זיהוי סטטוס, חילוץ שדות details ומקרי קצה (לדוגמה tests/test_extractor_<profile>.py).

רישיון

MIT

Available Tools

4 tools
healthA

Check the backend before/after errors: Ollama reachable, model pulled and loaded, memory, free RAM, current keep_alive policy, agent-cu installed. Call this first if look_at_screen returns OLLAMA_UNREACHABLE or MODEL_NOT_FOUND.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It discloses the specific subsystems inspected, which is useful behavioral detail. Yet it does not state whether the operation is read-only, whether it has side effects (e.g., forcing a model load), or how long it might take. For a diagnostic tool, the checklist is helpful but leaves the safety and side-effect profile implicit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the concrete checks and followed by the trigger condition. Every clause adds information; no filler. The structure makes it easy to scan for the tool's purpose and call condition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has no output schema and no annotations, so the description should ideally explain the return shape or at least characterize the response. It lists what is checked but does not say what the agent gets back (e.g., a report with per-check statuses). Given the low complexity, the description is adequate but leaves a notable gap around output interpretation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is no parameter semantics to explain. Per the rubric, 0 params yields a baseline of 4. The description correctly does not waste words on nonexistent parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Check') and resource ('backend'), then enumerates exactly what is checked: Ollama reachable, model loaded, memory, free RAM, keep_alive policy, agent-cu installed. This is far more specific than a tautology. It references a sibling tool (look_at_screen) to disambiguate usage, but does not distinguish itself from the sibling 'ping', so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: use it 'before/after errors' and 'Call this first if look_at_screen returns OLLAMA_UNREACHABLE or MODEL_NOT_FOUND.' This specifies a trigger condition tied to a specific error code. However, it does not articulate when not to use it or how it relates to the sibling 'ping', so it is not fully exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

look_at_screenA

Ask ONE short English question about what a window on this computer shows; get short JSON back (windows_seen, status, summary, confidence, details, model_used, duration_seconds, memory_mb). details is filled by code: project, session, branch, next_step, failures, files, background_tasks when found. Read-only: never clicks or types. Pass app when known. For multi-part checks call step by step (status first, then details). On error, follow error.suggestion. client and session_id are OPTIONAL. Without them every call is independent: the full screen is re-read, no 'what changed' is possible and no file is written. With them the server keeps context between calls (more accurate, shorter answers, plus changed_since_last). Reuse the same pair for one task; sending a new session_id replaces the old one for that client. keep_warm (optional bool) keeps the model loaded 10 min instead of 3 when you will ask again soon. Call release_model() when your task is done.

NameRequiredDescriptionDefault
appNoOptional app/window name, e.g. 'Claude' or 'ChatGPT'. Pass it when known.
clientNoOptional. Your client name, e.g. 'codex' or 'claude' ([A-Za-z0-9_-], max 64). Used with session_id to keep context between calls.
questionYesOne short, focused question in English (max 300 chars), e.g. 'Is Claude working or finished?'. Split bigger checks into several calls.
keep_warmNoOptional. true = keep the model loaded 10 min (session value) instead of 3 min, when you will ask again soon without a session_id.
session_idNoOptional. A session name you choose, e.g. 'fix-ui' ([A-Za-z0-9_-], max 64). Reuse it on every call of the same task to get context and 'changed_since_last'. A new value replaces your previous session. Omit it and each call is independent (full re-read, no file).

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses read-only behavior (never clicks or types), the effect of omitting client/session_id (full re-read, no 'what changed', no file written), the effect of providing them (context, changed_since_last, file written), session replacement semantics, and the keep_warm timeouts. That is rich behavioral context beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is dense and front-loaded with the primary action, then output fields, then behavioral rules. It is slightly long and the session/client paragraph could be tightened, but every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-param tool with no output schema and no annotations, the description covers return fields, read-only safety, session behavior, error handling, and cleanup via release_model. An agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is already 100%, so the baseline is 3. The description still adds value by linking session_id and client to outcomes (context, changed_since_last, full re-read without them) and explaining keep_warm's 10-min vs 3-min load, plus the step-by-step pattern for app filtering. It doesn't add syntax details that the schema lacks, so it falls short of 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: ask one short question about what a window shows, and returns JSON with named fields. Siblings (ping, health, release_model) are clearly different operations, so differentiation is implicit but obvious.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit guidance: pass `app` when known, for multi-part checks call step by step with status first then details, follow error.suggestion on error, and call release_model() when done. It names when to reuse sessions and when to omit them. Nothing is left to inference about when to use this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pingA

Heartbeat: checks that this bridge works end to end. Confirms the server is up, makes sure the local Ollama is reachable (auto-starts it if needed) and asks the model for 'pong'. No screen reading. Returns {ok, server, ollama, model_reply_ok, model, seconds, cold, error?}. The first ping may take 30-50 s if the model is cold (not loaded); later pings take a few seconds.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses the side effect that Ollama is auto-started if needed, the first-call cold-start latency of 30-50s versus a few seconds when warm, and that no screen reading occurs. It could still say more about failure modes, but the 'error?' field and 'cold' flag hint at that.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose, then the return shape, then the latency caveat — a sensible ordering. It is slightly long with the field-by-field enumeration, but every sentence adds information an agent would want.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, and the description compensates by enumerating the returned fields ({ok, server, ollama, model_reply_ok, model, seconds, cold, error?}). For a zero-parameter diagnostic tool, nothing needed to invoke or interpret it is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing to document and the baseline of 4 applies. The description correctly implies invocation requires no arguments.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Heartbeat: checks that this bridge works end to end') and enumerates the exact sub-checks it performs (server up, Ollama reachable, model returns 'pong'). The 'No screen reading' clause implicitly distinguishes it from look_at_screen, but the overlapping sibling 'health' is never addressed, so the differentiation is incomplete.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the name and framing — a heartbeat/diagnostic. There is no explicit statement of when to call this versus the sibling 'health' tool, nor any exclusion or prerequisite guidance beyond the latency note.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

release_modelA

Unload the local model now and return freed memory_mb. Call it at the end of your task (after your last look_at_screen) so the RAM is free again. Safe to call when nothing is loaded.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations, so the description carries the full burden. It discloses the side effect (unloads model, returns freed_mb), the safe-when-empty behavior, and ties the timing to look_at_screen. It does not say whether re-loading is costly or whether concurrent calls conflict, but the essentials are covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences; the purpose and return value come first, then the lifecycle guidance. No waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A zero-param, no-output-schema teardown tool needs to explain timing, safety, and return value, and it does all three. Minor gap: it doesn't state the consequence of releasing too early, but that is secondary.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so baseline is 4. The description does not invent any, correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (unload) and resource (the local model), plus the side effect (freed memory_mb). Distinguishes from siblings ping/health/look_at_screen, none of which release resources.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit 'when': at the end of your task, after the last look_at_screen. Also states it is safe when nothing is loaded, removing a common hesitation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.1.0
    • First observedhealth
    • First observedlook_at_screen
    • First observedping
    • First observedrelease_model

TDQS

A3.9/5.0

Scored across 4 tools

Disambiguation4/5

look_at_screen and release_model are clearly distinct, and ping vs health are separated by intent (lightweight heartbeat vs detailed backend diagnostic). However, both ping and health check Ollama reachability and model status, so an agent could reasonably hesitate between them in a failure scenario.

Naming Consistency3/5

Naming mixes bare nouns (ping, health) with verb_noun forms (look_at_screen uses verb_preposition_noun, release_model is verb_noun). It stays readable, but there is no single predictable pattern across the four tools.

Tool Count4/5

Four tools is a reasonable, tightly scoped set for a read-only screen-inspection bridge, with three of them being support/lifecycle helpers. It is on the thin side since only one tool performs the core action, but nothing is redundant filler.

Completeness3/5

For a server literally named 'computer-use', the surface is observation-only: no clicking, typing, window enumeration, or targeted reads beyond a single look_at_screen. The read-only lifecycle (ping, health, release_model) is well covered, but the domain name promises interaction the tool set does not deliver.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables LLMs to capture and analyze screenshots of your screen, windows, or regions with smart detection capabilities. Features natural language queries, automatic window targeting, and text enhancement for UI debugging and visual inspection.
    2
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI agents to query Windows process, window, and console information via structured JSON instead of screenshots, reducing token usage by 94-98%.
    20
    47 npm
    1
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    This server enables AI agents to operate Windows and Linux computers by observing the screen, understanding the UI through accessibility, OCR, and vision, and performing mouse, keyboard, window, clipboard, and system actions with verification and recovery.
    29
    2
    MIT