Skip to main content
Glama

mcp-winaccess-win

Version 1.8.0 · Windows-only desktop automation MCP server. Built directly on the OS APIs — ctypes (SendInput, ImageGrab, Win32 windows, clipboard) and UI Automation via comtypes — with no pyautogui / pywinauto / pywin32.

Requirements

  • Windows 10/11 (x64) — this package only runs on Windows.

  • Python 3.10+.

  • The server must run inside an interactive desktop session (a logged-in user), not as a background service — otherwise SendInput/UI Automation cannot reach the desktop.

  • No administrator rights are required for normal user applications (see Limitations).

  • OCR auto-install needs network access and 7-Zip (or an existing Tesseract install; see Troubleshooting).

Related MCP server: Windows MCP Server

Install

pip install mcp-winaccess-win              # OCR support (pytesseract) is included
pip install "mcp-winaccess-win[vision]"    # optional: OpenCV template matching

The Tesseract binary (a system program, not a Python package) is downloaded and installed automatically on first OCR use into %LOCALAPPDATA%\mcp-winaccess\tesseract (with eng + rus language data). Use --tesseract_cmd <path> to point at an existing install, or --no-auto-tesseract to disable the automatic install (see Troubleshooting).

Run

python -m mcp_winaccess_win.server
# or the console script
mcp-winaccess-win

Command-line arguments

Argument

Default

Meaning

--transport

local

local (stdio) or remote (streamable-http)

--listen

0.0.0.0

HTTP bind address (remote only)

--port

8765

HTTP port (remote only)

--token

(none)

Bearer token required for HTTP (remote only)

--tesseract_cmd

auto

auto, or an explicit path to tesseract.exe

--auto-tesseract

on

automatic Tesseract install; --no-auto-tesseract disables it

--no-shell

off

disables the run_command tool (shell execution); enabled by default

Local (stdio) is the default and needs no arguments. To serve over HTTP, protect the desktop with a token — a token is required whenever --listen is not loopback:

mcp-winaccess-win --transport remote --listen 127.0.0.1 --port 8765 --token mysecret

OpenCode config (opencode.jsonc)

Local (stdio) — OpenCode launches the server itself:

{
  "mcp": {
    "winaccess": {
      "type": "local",
      "command": ["uvx", "mcp-winaccess-win", "--tesseract_cmd", "auto"],
      "enabled": true
    }
  }
}

Remote (streamable-http) — the token goes in the Authorization header:

{
  "mcp": {
    "winaccess": {
      "type": "remote",
      "url": "http://127.0.0.1:8765/mcp",
      "headers": { "Authorization": "Bearer mysecret" },
      "enabled": true
    }
  }
}

Architecture

Layer

Implementation

Mouse / keyboard

SendInput (ctypes); text via KEYEVENTF_UNICODE (Unicode without the clipboard)

Screenshots

Pillow ImageGrab (bbox, all_screens, window handle)

Windows

ctypes EnumWindows / MoveWindow / SetWindowPos / PostMessage

Clipboard

Win32 clipboard via ctypes

UI tree, menus, dialogs

UI Automation COM via comtypes

Vision / OCR

OpenCV template matching / pytesseract with an auto-installed Tesseract binary

Modules: mcp_winaccess_win/server.py (tool wrappers), mcp_winaccess_win/adapter/windows.py (adapter), mcp_winaccess_win/adapter/win32_input.py, mcp_winaccess_win/adapter/win32_screen.py, mcp_winaccess_win/adapter/win32_window.py, mcp_winaccess_win/adapter/win32_clipboard.py, mcp_winaccess_win/adapter/win32_overlay.py (element highlight), mcp_winaccess_win/adapter/win32_notifications.py, mcp_winaccess_win/adapter/win32_process.py (launch/kill/enumerate processes), mcp_winaccess_win/adapter/tesseract_setup.py (auto-install OCR engine), mcp_winaccess_win/adapter/uia.py (UI Automation), mcp_winaccess_win/adapter/base.py (interface + shared helpers).

Conventions

  • value (window identifier): a partial title/class (str), a window handle (int), or a prefix title:, class:, pid:N, exe:name.exe.

  • control_identifier: the ID returned by get_all_controls (element_N) or a control Name/AutoID.

  • All coordinates are absolute screen pixels (virtual-desktop space).

  • Any failure returns a string starting with ERROR:; success messages are human-readable.

  • Tool schemas carry per-parameter descriptions, Literal enums for fixed choices, a human-readable title, and behavioural hints (readOnlyHint/destructiveHint/idempotentHint) so agents can tell observing tools from state-changing ones.

Tools

94 tools. They are registered only when the adapter advertises the matching capability; unsupported tools are hidden.

Screenshots and display — screenshot, screenshot_region, screenshot_monitor, screenshot_window, screenshot_element

  • screenshot(grid=False, include_cursor=False) — the whole virtual desktop (all monitors); grid=True overlays labeled 100 px lines; include_cursor=True draws the mouse pointer.

  • screenshot_jpg(path="") — save a JPEG (temp file when path is empty).

  • screenshot_region(left, top, width, height, grid=False).

  • screenshot_monitor(index=0, grid=False) — a single monitor.

  • screenshot_window(value, grid=False) — capture a window (even if partially occluded).

  • screenshot_element(value, control_identifier, grid=False) — capture a single control.

  • compare_screenshots(image_a, image_b, save_diff="") — differing pixels/percentage between two image files.

  • list_monitors() (includes DPI scale), image_to_screen_coords(x, y, monitor_index=0), get_pixel_color(x, y), wait_for_pixel_color(x, y, color, timeout=10, tolerance=0).

Mouse and keyboard — input

  • get_mouse_position(), move_mouse(x, y), mouse_move_relative(dx, dy).

  • click(x=None, y=None, button="left", clicks=1) — omit x/y to click at the current position; clicks=2 is a double-click, button="right" a right-click.

  • mouse_down(x=0, y=0, button="left") / mouse_up(button="left") — hold/release for manual drags.

  • drag(x_from, y_from, x_to, y_to, duration=0.5), scroll(direction="down", amount=3, x=0, y=0).

  • type_text(text) (Unicode), hotkey(keys) (e.g. "ctrl+shift+s").

  • press_key(key) — a key (enter, tab, esc, f5, letters/digits) or a system key (win, volumeup, volumedown, volumemute, playpause, nexttrack, prevtrack, printscreen).

  • key_down(key) / key_up(key) — hold/release keys (e.g. Shift range selection).

  • sleep(seconds) — wait a fixed amount of time.

Clipboard — clipboard

  • clipboard_get(), clipboard_set(text), clipboard_clear().

  • clipboard_set_files(paths) / clipboard_get_files() — file paths (CF_HDROP).

  • clipboard_set_image(path) / clipboard_get_image(save_path="") — image (CF_DIB).

Vision / OCR — vision, ocr

  • locate_image_on_screen(image_path, confidence=0.9), wait_for_image(...), click_image(...) — require the vision extra.

  • ocr_screen(left, top, width, height, lang=""), find_text_on_screen(text, confidence, lang), click_text(text, confidence, lang)lang e.g. "eng" or "rus+eng"; the Tesseract binary auto-installs on first use.

  • wait_for_text(text, timeout, lang, confidence) — waits until OCR finds text (for canvas/custom UI).

Windows — window_list, window_activate, window_close, window_minimize, window_maximize, window_move, window_resize, window_snap, window_topmost

  • list_windows(process=""), find_window(value), get_active_window(), get_window_state(value) (rect, handle, pid, exe, state, monitor).

  • switch_to_window(value), wait_for_window(value, timeout, require_ready=False) (require_ready=True waits until visible and responsive), wait_for_window_gone(value, timeout).

  • minimize_window(value), maximize_window(value), restore_window(value), close_window(value).

  • move_window(value, x, y), resize_window(value, x, y, width, height), snap_window(value, position).

  • set_always_on_top(value, enabled).

value accepts a partial window title (str), a window handle (int), or a prefix: title:, class:, pid:N, exe:name.exe. list_windows(process=...) filters by exe name or PID.

Menus and dialogs — menus, dialogs, tray

  • menu_select(value, path) (e.g. "File->Save As"), get_menu_items(value, menu="") (discover the menu bar / a menu's items), context_menu_click(x, y, item).

  • list_dialogs(), handle_dialog(button_text, title="").

  • file_dialog_set_path(path, title=""), file_dialog_confirm(title="").

  • tray_icon_click(name, action="left").

UI tree (semantic controls) — ui_tree

  • get_all_controls(value, limit=150, query="", control_type="") — use the returned ID (element_N) or Name/AutoID as control_identifier; each row includes Rect and Center.

  • click_element(value, control_identifier, clicks=1) (clicks=2 = double-click), get_text, set_text(value, control_identifier, text, mode="value", clear=False) (mode="type" forces focus + typing; clear=True selects-all before typing), get_window_text(value) (flat text dump), select_item, toggle_checkbox, get_control_state, set_slider, get_selected_text, scroll_into_view, wait_for_element, drag_element.

Element inspection — ui_tree

  • get_element_at_point(x, y) — element under a screen point.

  • get_active_element() — the currently focused control.

  • highlight_element(value, control_identifier, duration=1.0, color="red", width=3) — temporary rectangle (visual confirmation).

  • highlight_region(x, y, width, height, duration=1.0, color="red", border_width=3) — temporary rectangle over an arbitrary screen region.

  • wait_for_element_gone(value, control_identifier, timeout=10) — wait until a control disappears.

  • expand_element(value, control_identifier) / collapse_element(value, control_identifier) — tree/expander controls.

  • get_control_state(value, control_identifier) — enabled/offscreen/checked/value (works for checkboxes, menu items, sliders).

  • drag_element_to_element(from_value, from_control, to_value, to_control, duration=0.5) — drag-and-drop between controls.

  • scroll_element(value, control_identifier, direction="down", amount=3).

Lists and tables — ui_tree

  • get_list_items(value, control_identifier, limit=200) — item names of a list/tree.

  • get_table_data(value, control_identifier, limit=200) — table/grid rows (cells joined by |).

Notifications — notifications

  • list_notifications() — current Windows notifications via the UserNotificationListener API (no UI opened).

  • dismiss_notifications() — clears all notifications (UI clear-all button; the WinRT clear API is unavailable to desktop apps).

Virtual desktops — desktop

  • switch_desktop(direction="right") — switch to the adjacent desktop.

  • move_window_to_desktop(value, direction="right") — move a window to the adjacent desktop.

Processes and shell — process, shell

  • run_app(path, args="", cwd="") — launch an application detached (returns its PID); pair with wait_for_window(require_ready=True).

  • kill_process(pid_or_name) — force-kill a process tree (irreversible; prefer close_window).

  • list_processes(filter="") — list running processes as PID N | name.exe.

  • run_command(command, cwd="", timeout=30, shell="cmd") — run a console command and return its exit code and output (shell="powershell" for PowerShell). Disable with --no-shell.

Examples

# 12 + 34 in Calculator
click_element("Калькулятор", "clearButton")
click_element("Калькулятор", "num1Button")
click_element("Калькулятор", "num2Button")
click_element("Калькулятор", "plusButton")
click_element("Калькулятор", "num3Button")
click_element("Калькулятор", "num4Button")
click_element("Калькулятор", "equalButton")
get_text("Калькулятор", "CalculatorResults")   # -> 46

# Screenshot with a coordinate grid
screenshot(grid=True)

Limitations

  • UIPI: SendInput cannot drive windows with higher integrity (elevated apps) from a non-elevated process. Run the server elevated to automate those.

  • Foreground activation: switch_to_window uses the Alt-unlock + SetForegroundWindow technique; some always-on-top/system windows may still refuse focus.

  • UWP apps (e.g. Calculator) can expose two ApplicationFrameWindow instances (one minimized); the adapter prefers the visible/largest frame.

  • DPI: the process is per-monitor-v2 DPI aware, so coordinates match physical pixels.

Troubleshooting

  • OCR fails — the Tesseract binary is auto-installed on first use (downloaded via the UB-Mannheim installer, extracted with 7-Zip, into %LOCALAPPDATA%\mcp-winaccess\tesseract). If that fails (no network / no 7-Zip), install Tesseract manually and pass --tesseract_cmd <path>. Language data eng and rus are fetched automatically; add more by dropping *.traineddata into the managed tessdata.

  • Vision tools missing — install the vision extra (opencv-python).

  • UI tree tools missingcomtypes is required (installed with the package).

Tests

The tests/ suite was removed; verification is done manually, function by function, against a live desktop session.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to interact with Windows operating systems through native UI automation, file navigation, application control, and system commands. Provides seamless integration between LLMs and Windows environments for tasks like clicking, typing, launching apps, and capturing desktop state.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables comprehensive Windows desktop automation including screen capture, OCR text extraction, mouse/keyboard control, window management, process control, and clipboard operations through 25+ tools for AI agents.
    46 PyPI
    5
    MIT