mcp-computer-use
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-computer-useIs Claude done with the refactor? Check the Claude window."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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:
agent-cu text -a <App>reads the window (no model).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.
A local Ollama model (default
gpt-oss:20b) summarizes that short text. Measured 4–8 s, correct.The agent receives ~50 tokens of JSON.
qwen3:4b was tested and kept emitting reasoning, so gpt-oss:20b is the default (configurable).
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 |
| Reads one window and answers. If |
| Clicks a visible label, or a sequence of 1–10 labels via |
| Sets the value of an editable field in the app without submitting. Without |
| Heartbeat: server up, local Ollama reachable (auto-started if needed), model replies |
| Unloads the model now and returns |
| Checks backend health: Ollama reachable, model pulled, model loaded, memory, free RAM, current keep_alive policy, agent-cu installed. CLI: |
When to read (look_at_screen) vs click/type
Read first: Use
look_at_screento 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
@eNreference. Accessibility element refs change on every snapshot;@eNtargets are rejected withINVALID_TARGET.Single action vs batches: Prefer one click per call when exploring or verifying step by step. Use
stepsfor 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 bymax_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
PrintWindowthrough 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_MINIMIZEDis 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 exceededimage_timeout.
Configuration:
image_timeout(envMCP_CU_IMAGE_TIMEOUT, default 15.0 s) sets the subprocess timeout.CLI:
mcp-computer-use --ask "What is open?" --app "Calculator" --image-out snapshot.jpgwrites the JPEG to disk and outputs JSON withimage/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_screencall 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 requestinclude_image=Trueonly 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:
Exact match: Case-sensitive exact string equality with the UI element name (
tier 1, score 1.0,how: "exact").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").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 accessibilityid(tier 3, score 0.9). Note that"-"also matches"−"(U+2212). Role phrases (e.g.button 7,כפתור 7,field Search,שדה חיפוש) are split to disambiguate.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 whenresolve_with_modelis 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 withTARGET_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_extrain TOML, or environment variablesMCP_CU_SAFETY_BLOCKLIST/MCP_CU_SAFETY_BLOCKLIST_EXTRAonly 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 returnsDANGEROUS_ACTION_NEEDS_CONFIRMATIONwithwould_clickandmatched_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 |
| No matching UI target found in the window (returns up to 5 near candidate suggestions). |
| Multiple candidates matched (returns up to 5 |
| The target was found but its role is not an editable field ( |
| Target is empty, longer than 200 chars, or an |
| Typed text exceeds |
| Target or element matched the safety blocklist. Requires explicit human user approval before setting |
| App window not found, empty app name, or app name contains shell metacharacters. |
|
|
| Underlying UI automation command failed. |
| Ollama service could not be reached or auto-started. |
| Configured model is not pulled in Ollama. |
| Model inference timed out. |
| Model inference failed. |
| Question exceeds |
| Question string is empty. |
| Window image capture failed, or target window was not found / ambiguous. |
| Captured image was blank (window may be minimized, hardware-accelerated, or covered). |
| Target window is minimized. Restore or un-minimize the window before requesting an image. |
| Window image capture timed out (exceeded |
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-dangerousCommand-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}$$
claude_code: Matched when"claude"is in the lower-cased app name.codex_desktop: Matched when the app name ischatgpt,codex,codex desktop, oropenai.codex(Windows appChatGPT), or when the window title containscodex.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).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).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, orunknown.detailskeys: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), andasks_user.
Codex desktop (
codex_desktop, Windows appChatGPT):Top-level
status:working,finished,waiting, orunknown— 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).detailskeys: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: Booleantruewhen the "View activity, needs attention" button is visible.next_step: Extracted from "Next steps:" or "השלב הבא:".failures: Error and failure lines detected viafind_failures.waiting_prompt(andwaiting_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:waitingif a prompt is pending,errorif failures are detected, otherwiseunknown.detailskeys: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(andwaiting_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:errorwhen a network error page is detected (e.g. DNS probe, connection refused, no internet); otherwiseunknown.detailskeys:page_title(andtitle): 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: Alwaysunknown.detailskeys: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
hintsuggesting 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, returnschanged_since_lastand updates the file. The same question on an unchanged screen is answered from the file (cached: true, no model call).A new
session_idreplaces the old one for that client (the old file is deleted), so each client has one active file. Asession_idwithoutclientuses clientdefault.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.ollamais found on PATH or at%LOCALAPPDATA%\Programs\Ollama\ollama.exe.MCP_CU_AUTOSTART_OLLAMA=0disables it;MCP_CU_AUTOSTART_TIMEOUT(default 30).health()reportsollama_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
.sessionsfile updated in the last 10 min) orkeep_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, everyMCP_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 amemoryfield (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 -qOllama
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 testConfiguration
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 |
|
| Ollama server URL |
|
| Model used for summarization / candidate picking |
|
| Max chars extracted from window for model |
|
| Longer questions rejected with |
|
| Smart timeout bounds and scaling |
|
| Extra seconds added when model is cold |
|
| Learn the timeout from recent warm calls |
|
| Total wall budget per tool call ( |
|
| Command and timeout for UI automation |
|
| Optional HTTP health check server |
| bundled | Override default system prompt |
|
| Read accessibility tree for Claude details |
|
| Sessions and action log folder |
|
| Hours before inactive session files are purged |
|
| Model retention duration in memory |
|
| Session recency window for keeping model alive |
|
| Minimum free RAM in MB before unloading model |
|
| Background watcher to unload model under RAM pressure |
|
| Auto-start local Ollama if unreachable |
|
| Additional comma-separated blocklist words |
|
| Extra additional blocklist words |
|
| Hours before old action audit records are purged |
|
| Use local model to resolve ambiguous candidates (≤5) |
|
| Max characters allowed for |
|
| 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 = 120Claude 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.exeThen 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), passappwhen known, step by step for bigger checks, and followerror.suggestion.Read first: Use
look_at_screenif unsure of window state or target labels.Click by visible label: Pass visible UI labels (1–200 chars), never
@eNrefs.Use
stepsfor known sequences: Up to 10 labels (e.g. calculator keys).Safety: Never set
confirm_dangerous=truewithout explicit human approval in chat.Do not use
agent-cudirectly to click or type unless the MCP tool fails.Optionally pass
client+session_idand reuse them for the whole task to get context andchanged_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-fatalhint.
Good | Bad |
|
|
|
|
|
|
| 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 --humanOptions: -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:
Register the profile: Register via
register_profile(name, matcher, extractor, snapshot_details)insrc/mcp_computer_use/extractors/registry.py(and secondary window-title matching inselect_profileinsrc/mcp_computer_use/extractors/__init__.py).Add anonymized fixtures: Place sanitized accessibility snapshot and text captures under
tests/fixtures/<profile>/(scrub personal data, usernames, tokens, and local paths).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.
השרת הזה עושה את הקריאה מקומית:
agent-cu text -a <App>קורא את החלון, בלי מודל.קוד שולף רק את המצב ואת ההודעה האחרונה באמצעות פרופילים ייעודיים לפי תוכנה (Claude Code, Codex desktop, עורכי קוד, דפדפנים, או ברירת מחדל כללית). כשנייה וחצי.
מודל מקומי ב-Ollama (ברירת מחדל
gpt-oss:20b) מסכם את הטקסט הקצר. נמדד: 4 עד 8 שניות, עם תשובה נכונה.הסוכן מקבל כ-50 טוקנים של JSON.
נבדק גם qwen3:4b, אבל הוא ממשיך "לחשוב בקול", ולכן ברירת המחדל היא gpt-oss:20b. אפשר לשנות אותה.
תובנת ביצועים ומדידה (18.10.2026): עבור חלונות קטנים או פשוטים (כגון מחשבון או עמוד אינטרנט קצר), קריאה ישירה של חלון באמצעות agent-cu text יכולה להיות זולה בטוקנים באותה מידה (~1,000–2,000 טוקנים). היתרון המשמעותי של השרת בא לידי ביטוי בחלונות גדולים ועמוסים (תוכנות צ'אט, עורכי קוד ו-IDEs), שבהם טקסט גולמי מגיע ל-40k עד 200k+ טוקנים, וכן כאשר שדות ה-details שנשלפים אוטומטית עונים ישירות על השאלה ללא צורך בניתוח חוזר של המודל.
הכלים
כלי | תיאור |
| קורא חלון אחד ועונה. לקריאה בלבד. ללא |
| לוחץ על תווית גלויה, או על רצף של 1 עד 10 תוויות דרך |
| מזין ערך ישירות לשדה עריכה ללא שליחה (Enter אינו נלחץ). ללא |
| בדיקת דופק: מוודא שהשרת עונה, ש-Ollama המקומי זמין (ומפעיל אותו אם צריך), ושהמודל עונה |
| פורק את המודל מהזיכרון מיד ומחזיר כמה זיכרון שוחרר ( |
| בודק אם Ollama זמין, אם המודל הורד ונטען, זיכרון, RAM פנוי, מדיניות keep_alive ואם agent-cu מותקן. שורת פקודה: |
מתי לקרוא (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אך ורק כאשר תשובת הטקסט אינה מספקת (בדיקת פריסה, תרשימים, באגים חזותיים).
מדרג התאמת תוויות ובחירת מועמדים
השרת מאתר פקדים בממשק לפי מדרג עדיפויות קפדני:
התאמה מדויקת (Exact): שוויון מחרוזות מדויק כולל אותיות גדולות/קטנות (
tier 1, ציון 1.0,how: "exact").התאמה מנורמלת (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").מילים נרדפות ומזהים (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,שדה חיפוש) מופרדים כדי למנוע עמימות.התאמות חלשות (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 תווים ומעלה.
קודי שגיאה
קוד שגיאה | תיאור |
| לא נמצא פקד ממשק מתאים בחלון (מוחזרים עד 5 מועמדים קרובים כהצעה). |
| נמצאו מספר פקדים מתאימים (מוחזרים עד 5 |
| הפקד אותר אך סוגו אינו שדה עריכה ( |
| היעד ריק, ארוך מ-200 תווים, או מזהה רפרנס |
| הטקסט חורג ממגבלת |
| היעד או שם הפקד (target or element) תואם למילה ברשימת החסימה. נדרש אישור אנושי מפורש לפני קריאה עם |
| חלון התוכנה לא נמצא, שם תוכנה ריק, או שם המכיל תווים מיוחדים של מעטפת הפקודות. |
| הכלי |
| פקודת הנגישות נכשלה. |
| שירות Ollama אינו נגיש ולא הצליח להפעיל את עצמו. |
| המודל המבוקש טרם הורד ב-Ollama. |
| פניית המודל חרגה ממגבלת הזמן. |
| פעולת המודל נכשלה. |
| השאלה ארוכה מ- |
| מחרוזת השאלה ריקה. |
| צילום תמונת החלון נכשל, החלון לא נמצא או שנמצאו מספר חלונות מתאימים (עמימות). |
| התמונה שהתקבלה ריקה לחלוטין (החלון עשוי להיות ממוזער, בעל האצת חומרה או מכוסה). |
| חלון היעד ממוזער. יש לשחזר את החלון לפני בקשת תמונה. |
| צילום תמונת החלון חרג ממגבלת הזמן הקצוב ( |
אפשרויות שורת הפקודה (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הערת אבטחה להזנת טקסט ושורת הפקודה: גם ה-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}$$
claude_code: נבחר כאשר מחרוזת"claude"מופיעה בשם התוכנה (באותיות קטנות).codex_desktop: נבחר כאשר שם התוכנה הואchatgpt,codex,codex desktopאוopenai.codex(אפליקציית Windows שלChatGPT), או כאשר כותרת החלון כוללתcodex.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).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).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 -qOllama
כתובת ברירת המחדל היא 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)
כדי להוסיף פרופיל מחלץ עבור אפליקציה חדשה:
רישום הפרופיל: רושמים באמצעות
register_profile(name, matcher, extractor, snapshot_details)בקובץsrc/mcp_computer_use/extractors/registry.py(והתאמה משנית לפי כותרת חלון ב-select_profileב-src/mcp_computer_use/extractors/__init__.py).הוספת קובצי בדיקה (fixtures): מוסיפים צילומי snapshot וטקסט אנונימיים תחת
tests/fixtures/<profile>/(ללא מידע אישי, שמות משתמש, טוקנים או נתיבים מקומיים).בדיקות מבוססות fixtures: כותבים לפחות 3 בדיקות (≥ 3 fixture tests) המאמתות זיהוי סטטוס, חילוץ שדות details ומקרי קצה (לדוגמה
tests/test_extractor_<profile>.py).
רישיון
MIT
Available Tools
4 toolshealthA
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| app | No | Optional app/window name, e.g. 'Claude' or 'ChatGPT'. Pass it when known. | |
| client | No | Optional. Your client name, e.g. 'codex' or 'claude' ([A-Za-z0-9_-], max 64). Used with session_id to keep context between calls. | |
| question | Yes | One short, focused question in English (max 300 chars), e.g. 'Is Claude working or finished?'. Split bigger checks into several calls. | |
| keep_warm | No | Optional. true = keep the model loaded 10 min (session value) instead of 3 min, when you will ask again soon without a session_id. | |
| session_id | No | Optional. 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
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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.
4 tool updates
v0.1.0- First observed
health - First observed
look_at_screen - First observed
ping - First observed
release_model
TDQS
Scored across 4 tools
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 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.
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.
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
Give agents eyes on any web page: structured context, and changes explained in plain language.
Connect ChatGPT, Claude, Cursor or VS Code to your Windows PC: files, terminal, browser, apps.
Hosted browser for AI agents: screenshots, post-JS DOM, console, WCAG. No install, no API key.
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceEnables 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.2MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI-powered vision analysis using local Ollama models. Supports screenshot analysis, OCR, text detection, and health monitoring via MCP protocol.28 npm3MIT
- AlicenseAqualityBmaintenanceEnables AI agents to query Windows process, window, and console information via structured JSON instead of screenshots, reducing token usage by 94-98%.2047 npm1MIT
- AlicenseBqualityBmaintenanceThis 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.292MIT