Skip to main content
Glama

computer-mcp ๐Ÿ–ฅ๏ธ

A Windows desktop-control MCP server for AI agents โ€” Python / FastMCP, stdio transport, 45 tools in one file.

Give any MCP-capable agent real eyes and hands on Windows โ€” UIA element-based control, native-image screenshots, instant app launching, batched action sequences, smart waits, and safety gates โ€” in a 0โ€“1000 normalized coordinate system so it never guesses pixels.

badge-python badge-platform badge-mcp badge-tools badge-license

This is NOT the npm @zavora-ai/computer-use-mcp and NOT Codex's bundled computer-use โ€” it is this repo's single-file Python server.


Why this exists

Most computer-use setups share two fatal habits:

  1. Screenshot-and-guess โ€” the model receives images, estimates pixel coordinates, and mis-clicks at any non-standard resolution/DPI.

  2. Token burn โ€” every state check costs a full screenshot.

computer-mcp inverts that:

Habit

Instead

Guess pixels from images

UIA element trees โ€” exact names, roles, and coords of every button/label/field (get_ui_tree, find_element, click_element) โ€” zero image tokens

Screenshot to check state

Cheap state checks โ€” get_screen_info, list_windows, diff_screenshot (returns changed regions, not images), wait_for_pixel, get_pixel_color

Many slow round-trips

batch() โ€” click โ†’ paste โ†’ wait โ†’ verify as one tool call (40 actions, 120 s cap)

Type via simulated keys

paste_text (clipboard + Ctrl+V) for unicode/long text โ€” preserves the user clipboard by default

Launch apps by poking the Start menu

open_app() resolves Start-Menu shortcuts, Microsoft Store AUMIDs, App-Paths registry and PATH โ€” launches instantly, no UI theatre

Everything drives the real desktop at your user privileges; designed to run quietly in the background while you keep working.


Related MCP server: PointHand

Requirements

OS

Windows 10 or 11 (single-file server; runs on your session, no admin needed)

Python

3.10+ on PATH (python.org)

Screen

Any resolution / DPI โ€” coordinates are normalized 0โ€“1000

Optional

opencv-python for confidence-based template matching (included in requirements)

Install

git clone https://github.com/Tb3bhargav/computer-mcp.git
cd computer-mcp

# (recommended) isolated venv
python -m venv .venv
.\.venv\Scripts\pip install -r requirements.txt

# smoke test โ€” should exit 0 and print nothing
python -m py_compile server.py

The server is not started by hand: your MCP client launches it over stdio and talks the Model Context Protocol. The config snippets below show exactly how.

๐Ÿ’ก Pick the right interpreter In client configs, point command at your venv's interpreter for zero global installs: C:/path/to/computer-mcp/.venv/Scripts/python.exe On Windows the launcher is typically python (or python.exe under ...\Programs\Python\Python311\). Use forward slashes in JSON paths.


Add it to your MCP client

All snippets assume the repo lives at C:/Users/nj322ws/OneDrive/Desktop/My Projects/computer-mcp โ€” adjust to where you cloned it.

Generic mcp.json โ€” Claude Desktop ยท Cursor ยท Cline ยท Continue ยท Windsurf

Client

Config file

Claude Desktop

%APPDATA%\Claude\claude_desktop_config.json

Cursor

~/.cursor/mcp.json

Cline

cline_mcp_settings.json (Cline โ†’ MCP Servers โ†’ Configure)

Continue

~/.continue/config.json

Windsurf

~/.codeium/windsurf/mcp_config.json

{
  "mcpServers": {
    "computer": {
      "command": "python",
      "args": ["C:/Users/nj322ws/OneDrive/Desktop/My Projects/computer-mcp/server.py"]
    }
  }
}

OpenCode โ€” global ~/.config/opencode/opencode.json (production-tested setup)

{
  "mcp": {
    "computer": {
      "type": "local",
      "command": [
        "C:/Users/nj322ws/AppData/Local/Programs/Python/Python311/python.exe",
        "C:/Users/nj322ws/OneDrive/Desktop/My Projects/computer-mcp/server.py"
      ],
      "cwd": "C:/Users/nj322ws/OneDrive/Desktop/My Projects/computer-mcp",
      "enabled": true,
      "timeout": 180000
    }
  },
  "permission": {
    "computer_*": "allow"
  }
}

"permission": { "computer_*": "allow" } whitelists every tool name of this server in OpenCode. Drop it if you prefer to approve each desktop-control call manually.

OpenCode also supports per-project config with the same shape (e.g. project opencode.jsonc or .opencode/opencode.jsonc):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "computer": {
        "type": "local",
        "command": ["python", "C:/Users/nj322ws/OneDrive/Desktop/My Projects/computer-mcp/server.py"]
      }
    }
  },
  "permission": { "computer_*": "allow" }
}

VS Code (GitHub Copilot) โ€” .vscode/mcp.json

{
  "servers": {
    "computer": {
      "type": "stdio",
      "command": "python",
      "args": ["C:/Users/nj322ws/OneDrive/Desktop/My Projects/computer-mcp/server.py"]
    }
  }
}

Codex CLI โ€” ~/.codex/config.toml

[mcp_servers.computer]
command = "python"
args = ["C:/Users/nj322ws/OneDrive/Desktop/My Projects/computer-mcp/server.py"]

Claude Code โ€” CLI one-liner

claude mcp add computer -- python "C:/Users/nj322ws/OneDrive/Desktop/My Projects/computer-mcp/server.py"

Gemini CLI โ€” ~/.gemini/settings.json

{
  "mcpServers": {
    "computer": {
      "command": "python",
      "args": ["C:/Users/nj322ws/OneDrive/Desktop/My Projects/computer-mcp/server.py"]
    }
  }
}

Verify it works: restart the client, start a chat, and ask "what's on my screen?" โ€” the agent should call get_screen_info() (reported in plain text, free tokens) instead of grabbing an image.


The 0โ€“1000 coordinate system

Every position the agent passes in โ€” clicks, regions, polls โ€” is normalized:

  • (0,0) = top-left ยท (1000,1000) = bottom-right of the primary display.

  • Internally converted to real pixels: resolution- and DPI-independent.

  • Anything returned (element boxes, image matches, diff cells) is also 0โ€“1000.


All 45 tools

Perception โ€” see without burning image tokens

Tool

What it does

get_screen_info()

OS, screen size, mouse position, active window + owning process, monitor list โ€” no image

get_system_info()

Capability report: OS/arch/python, pygetwindow/opencv availability

list_windows()

Open windows (title, rect, active) โ€” ghost/DWM-cloaked windows filtered out

read_screen_text(root, window, depth)

All visible UI text of the active/named window as one string โ€” no image

diff_screenshot(region, threshold)

What changed since last capture: changed %, region cells, union bbox โ€” no image

UI elements (UI Automation) โ€” the fast path

Tool

What it does

get_ui_tree(root, window, depth, interactive_only)

The AI DOM dump: every element with index/role/name/box/center in 0โ€“1000

find_element(text, ...)

Case-insensitive match on visible text โ†’ roles + coords

click_element(text, occurrence, double_click, right_click)

Click an element by its visible label โ€” re-searched fresh at click time, never stale

(all above also accept root:"screen")

Read the whole desktop, not one window

Screenshots & vision

Tool

What it does

take_screenshot(region, max_width, quality, grayscale)

Native image to the agent; region=[x1,y1,x2,y2] crops to save tokens

save_screenshot(path, region)

Full-res PNG to disk โ€” for evidence or template building

find_image(image_path, confidence, region)

Locate a template PNG โ†’ 0โ€“1000 center + box

get_pixel_color(x, y)

RGB/hex of one pixel โ€” poll toggles/spinners without images

Windows & apps

Tool

What it does

activate_window(title_contains)

Focus by title substring (exact > startswith > process-name > contains), restores minimized

window_control(title_contains, action)

minimize / maximize / restore / close

open_app(name)

Instant launch of any installed app: Start-Menu shortcuts, Store apps (AUMID), App-Paths registry, PATH, URIs (ms-settings:)

launch_app(query, wait_after)

OS-aware launch with wait (Spotlight on macOS, direct exec on Linux; Start-flow fallback on Windows)

list_installed_apps(filter, limit)

Everything openable, cheap and cached

list_agent_desktops() / create_agent_desktop() / switch_agent_desktop(to_agent) / close_agent_desktop()

Dedicated Windows virtual desktop that only the agent works on โ€” user's desktop untouched

Mouse

Tool

What it does

mouse_move(x, y)

Hover / tooltips

mouse_click(x, y, button, clicks)

Left/right/middle, single or multi-click

mouse_down(button) / mouse_up(button)

Press-and-hold primitives

scroll(x, y, clicks, horizontal)

Scroll wheel at a position

drag(from_x, from_y, to_x, to_y, button, duration)

Sliders, selections, window moves

Keyboard & text

Tool

What it does

type_text(text)

ASCII typewriting (~50 chars/s)

paste_text(text, restore_clipboard)

โญ Reliable entry for long/unicode/symbol text โ€” clipboard + Ctrl+V, restores your clipboard afterwards

press_key(keys)

enter, ctrl+c, alt+tab, win+r โ€ฆ

key_down(key) / key_up(key)

Hold-and-release (e.g. shift for multi-select)

set_clipboard(text) / get_clipboard()

Direct clipboard control

Batch โ€” 12 action types, one call

Tool

What it does

batch(actions, stop_on_error, verify_screenshot)

Runs a sequence in ONE round-trip: click, double_click, right_click, move, type, paste, press, scroll, wait, focus_window, launch, click_text โ€” with a 120 s wall-clock cap and optional trailing verification screenshot

Waits โ€” sync without blind sleeping

Tool

What it does

wait(seconds)

Sleep (max 300 s); prefer the targeted waits below

wait_for_image(image_path, timeout, confidence, region, poll)

Poll until a template appears (dialog/loader done)

wait_for_stable(timeout, poll, threshold, region)

Block until the screen stops changing (page load, progress bar)

wait_for_pixel(x, y, hex_color, timeout, tolerance)

Poll one pixel until it matches a color โ€” spinners, toggle states

wait_until_image_gone(...)

Block until a template disappears (modal closed)

Safety & control state

Tool

What it does

set_safety_mode(enable)

ON: destructive actions require explicit confirmation

confirm_destructive(action_id)

Approve a pending destructive op returned by the safety gate

control_status()

Live state of the control machinery (mode, cancel flag, overlay state)

set_overlay_mode(auto/always/off)

Optional "AI is using your computer" overlay preference (silent off is default)

resume_control()

Clears the Esc-cancel latch after a user pause


The agent workflow this server is built around

The golden loop โ€” absorb it once with the agent of your choice:

STATE (free)         get_screen_info / list_windows
TARGETS (free)       get_ui_tree โ†’ find_element โ†’ read_screen_text
ACT                  click_element / batch / paste_text / press_key
VERIFY (free)        diff_screenshot / wait_for_pixel / wait_for_image
ONLY IF NEEDED       take_screenshot(region=...) for actual visual truth

Design principles baked into the tools:

  • Perception first, pixels last โ€” a healthy session uses screenshots only for final visual proof.

  • click_element re-finds its target at click time โ€” no stale coordinates between two UI states.

  • Windows are matched by exact title โ†’ prefix โ†’ owning process name โ†’ substring, so "whatsapp" finds WhatsApp even when the title says "John โ€ข WhatsApp".

  • list_windows/window matching filters DWM-cloaked ghosts invisible to the user.

Recipes

open_app("chrome", wait_after=4)
find_element("New tab")          # zero-image locate
click_element("New tab")
batch([
  {"focus_window": "WhatsApp"},
  {"press": "ctrl+f"}, {"paste": "Bhavna"},
  {"wait": 1.5}, {"press": "enter"}, {"wait": 2},
  {"click_text": "Bhavna Didi"},
  {"paste": "Compliments on the launch ๐ŸŽ‰"},
  {"press": "enter"}
], verify_screenshot=True)
click_element("Email")        # focus first field
paste_text("user@example.com", restore_clipboard=True)
press_key("tab")
paste_text("S3cret Password")
press_key("enter")
diff_screenshot()             # what changed โ€” without an image
click_element("Submit")
wait_for_pixel(500, 820, "#22c55e")   # success badge turns green
diff_screenshot(region=[380, 760, 620, 860])
save_screenshot("templates/save-btn.png", region=None)   # build templates once
find_image("templates/save-btn.png", confidence=0.9)
wait_until_image_gone("templates/save-btn.png")          # modal closed?
create_agent_desktop()       # sandbox ahead
switch_agent_desktop()       # agent now operates there
# ... any work ...
switch_agent_desktop(False)  # back to the user's screen
close_agent_desktop()
set_safety_mode(True)
press_key("delete")
# โ†’ "SAFETY MODE: destructive action pending โ€” press_key('delete') ...
#     Call confirm_destructive('perm_1')"
confirm_destructive("perm_1")    # now it runs

Safety

WARNING

This server gives the agentyour hands: real mouse, keyboard, clipboard and app launches are executed with your user privileges on your real desktop. Do not attach it to untrusted agents or models.

  • Explicit permissions โ€” In OpenCode, only set "permission": { "computer_*": "allow" } for agents you trust; leave it out to approve every desktop call.

  • Safety mode โ€” set_safety_mode(True) pends destructive actions (delete/backspace key events) behind confirm_destructive; default OFF.

  • Isolated desktops โ€” route risky visual work to create_agent_desktop() so the user's screen stays untouched.

  • Silent control by default โ€” control runs in the background; the takeover-overlay engine remains available (control_status, set_overlay_mode).

  • Esc-to-cancel โ€” the overlay engine's global Esc hook latches an emergency pause state whenever it is active; resume_control() clears it.

How it works (in one screen)

  • One file, server.py โ€” a FastMCP stdio server; every tool is a plain typed function.

  • OS + screen detected at startup and logged to stderr (stdout is reserved for the MCP protocol).

  • UIA all on one thread โ€” Windows UI Automation COM objects are apartment-bound, so every UIA call is serialized onto a single worker with per-call timeouts.

  • App launcher index โ€” a TTL-cached (10 min) merge of Start-Menu shortcuts + Get-StartApps (incl. Microsoft Store AUMIDs) + App-Paths registry + PATH.

  • Screenshot baselines โ€” diff_screenshot keeps a downscaled grayscale baseline and returns changed grid cells + union bbox instead of pixels, so the agent only grabs a cropped image if it truly needs to see the change.

  • Graceful degradation โ€” missing optional deps reduce features (no numpy โ†’ slower diffing) but never crash the server; window matching has layered fallbacks (exact โ†’ prefix โ†’ process name โ†’ substring, then "best available window").

Testing โ€” real results on a real machine

15-file report suite: 12 scenarios, all PASS, run October 2026 on the author's daily Windows 11 machine (OneDrive-synced, in active use). Full evidence in reports/:

Test

Proves

Result

Foundation 1โ€“3

OneDrive path resolution, write persistence (7 formats), surgical edits

PASS

Self-Healing Coder

build โ†’ serve โ†’ verify โ†’ find own 404 โ†’ fix โ†’ re-verify

PASS w/ honors

Librarian from Hell

460-file scan + OCR + honest "no text found"

PASS

GitHub Janitor

36-repo scan โ†’ branch โ†’ PR, main untouched

PASS

Persistence

reboot-proof scheduled task

PASS

Mission 1 โ€“ Executive Assistant

Gmail โ†’ Excel โ†’ PPTX, zero-hallucination data flow

PASS

Mission 2 โ€“ Data Janitor

OCR + winget self-install of a missing dependency + citations

PASS

Mission 3 โ€“ Chaos Organizer

organize + byte-perfect undo, non-disturb operation

PASS

Mission 4 โ€“ Full-Stack Ghost

local edit โ†’ push โ†’ live PR verification

PASS

Mission 5 โ€“ Deep State

live research + honest N/A + no-focus-steal screenshots

PASS

Troubleshooting

Install Python from python.org and tick Add to PATH. If the Windows Store alias persists, disable App execution aliases (Settings โ†’ Apps โ†’ Advanced app settings), or point configs at python.exe's full path.

Check the client's MCP logs โ€” the server writes an OS/screen banner to stderr at startup. Confirm the absolute path in your config is exact (it lives under user folders by design) and restart the client fully.

Chromium browsers and some apps only expose accessibility info on demand. Chrome/Edge: enable accessibility in the app or set the automation flag โ€” UIA then sees the DOM. Win32 apps (Notepad, Explorer, Office, most desktop apps) expose it natively.

Template matching needs opencv-python for the confidence parameter (listed in requirements). Rebuild templates with save_screenshot right before matching, same scale/theme.

They're normalized โ€” scenarios: mixed resolutions or Windows scaling changes make real pixel deltas unreliable; any x/y you pass is /1000-mapped to the primary display and never needs recalibration.


Contributing

Issues and PRs welcome โ€” especially for the per-OS abstractions. Keep the runtime a single importable server.py (the whole point), and please add a short report under reports/ for behavior changes.

License

MIT โ€” free for any use, including commercial; keep the copyright notice in copies. ยฉ 2026 Tejus Bhargav.


Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to see and operate Windows applications through MCP, including windows, screenshots, mouse, keyboard, scrolling, UI Automation, clipboard, and freehand or geometric drawing. Supports supervised creative workflows with native Win32 input, screenshots, allow-listed apps, and an idle safety guard.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables MCP clients to observe and control the Windows desktop through the UI Automation accessibility tree โ€” no vision model required โ€” by exposing tools for reading windows and interactive elements, clicking, typing, scrolling, shortcuts, PowerShell, screenshots, virtual desktops, web scraping, file operations and persistent memory, including background-window control without stealing focus. An optional agent mode adds a single natural-language task tool that runs the full upstream agent loop when an LLM provider is configured.
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables an MCP host to observe and control Windows desktop applications deterministically: reading UIA control trees, OCR text and pixel diffs, clicking, typing, scrolling and window management, plus verbatim text reading/appending via ValuePattern/TextPattern. Visual judgment is delegated back to the host model's own multimodal context through annotated screenshots, numbered element cards, grid maps and crosshair zoom-ins, so no separate vision model is needed.
    AGPL 3.0