Screen Control
Screen Control is a local, token-authenticated HTTP/MCP server that gives an agent desktop โeyes and handsโ: perceive the screen, control mouse/keyboard/windows, and use game-style input safely.
Get server/PC status: screen size, monitors, OCR availability, failsafe, game-mode state.
Capture screenshots for vision-capable models, with region, monitor, scale, and quality controls.
Read the screen as text via OCR, returning lines and clickable item centers; optional region crop.
Detect screen changes with text-only motion diff, useful to verify actions without vision/OCR.
Control the mouse: move, click, scroll, drag, press/hold, and release buttons.
Control the keyboard: press keys, send hotkeys, type Unicode-safe text, hold/release keys, with optional
expect_hwndfocus guard.Inspect currently held keys/buttons and watchdog status; emergency-release all held input.
List visible top-level windows with hwnd, title, process, pid.
Focus a window and inspect its child controls.
Classify how a window receives input:
postmessage,uia,focused, orinvalid.Send background input to a window: type, key, hotkey, click, scroll, with auto/background/focused routing.
Capture and OCR a background window without focusing it.
Safely close a window via WM_CLOSE with optional title/process verification.
Use game mode: start cursor clipping, relative camera movement, stop, and heartbeat for long holds.
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., "@Screen Control take a screenshot and summarize what's on my screen"
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.
๐ฅ๏ธ Computer use for all agents
A local remote-control system for AI agents: watch your computer's screen live and send mouse/keyboard commands to it. Everything runs on your own machine โ no data ever leaves it, no cloud middleman.
If You Are an AI Agent
Read AGENT_GUIDE.md first โ it is written for you: endpoints, safety gates and working recipes. This README is the human-facing reference.
First ask the server what it is โ GET /api/capabilities โ platform.
Windows: follow the whole guide as written. Linux: check
echo $XDG_SESSION_TYPE โ X11 is supported (guide โ
Linux (X11) Usage); Wayland is
unsupported: the server refuses to start, HTTP 501
UNSUPPORTED_DISPLAY_SERVER (switch to an X11 session). Full routing lives
in AGENT_GUIDE.md โ Find Your Environment First.
Related MCP server: pov
Why Screen Control?
AI agents today can write code and call APIs โ but they can't see or touch your desktop. Screen Control gives any agent general-purpose computer use over a clean, safety-gated HTTP/MCP interface:
Perceive โ OCR for text, single frames or a live MJPEG stream for vision-capable models, and a text-only diff endpoint for models that can't consume images at all.
Act โ absolute and relative mouse, Unicode-safe keyboard, window management, background (focus-free) control, virtual desktops.
Stay safe โ token auth, blocked deadly shortcuts, focus guard, a stuck-input watchdog and an emergency failsafe are all enforced server-side, no matter how confused the agent gets.
One process, zero configuration, works with any language that can speak HTTP โ or natively through MCP in Claude Desktop, Cursor, VS Code and cloud agents.
Performance Is Agent-Bound
Screen Control is the perception and actuation layer โ the eyes and hands. The effective speed and capability of any agent using it are bounded by that agent itself and by the environment it runs in:
Thinking speed โ one action per agent "turn": the perceive โ plan โ act โ verify loop lives in the agent, so model inference latency and reasoning depth directly set the pace. The API itself adds only milliseconds per call.
Context capacity โ screen readings (OCR text, frames, diffs) consume the agent's context window; a larger window means more situational awareness before verification degrades.
Runtime environment โ network latency, MCP/HTTP round-trip overhead, tool-call limits and hosting constraints all stack on top of the loop.
In practice this means: the same repo makes a fast reasoning model fast and capable, and makes a slow model slow โ the toolchain is not the bottleneck. Real-time or action-heavy tasks need an agent with fast inference and tight tool-loop latency; slower agents should prefer deliberate, verification-heavy tasks.
Table of Contents
Features
Feature | Description |
๐ผ๏ธ Live screen feed | Continuously refreshing screenshot in the browser |
๐ฑ๏ธ Mouse control | Click, right-click, double-click, scroll, drag & drop via live screenshot |
โจ๏ธ Keyboard control | Text typing (Unicode/Turkish included, layout-independent), keys and shortcuts (Ctrl+C, Alt+Tabโฆ) |
๐๏ธ OCR | Converts on-screen text to machine-readable format |
๐ท Vision access | Raw-pixel paths for image-capable models: single frames, MJPEG stream, text-based motion detection |
๐ช Window management | List, focus, safe close (WM_CLOSE), kill (task-manager style) |
๐ฅ๏ธ Focus-free control | Read/write background windows via PostMessage without stealing focus |
๐ฎ Game mode | Camera look via relative mouse movement, hold-to-move keys |
๐ Token auth | Every request requires |
๐ฆบ Stuck-input watchdog | Auto-releases held keys after 30 s of inactivity |
๐ Failsafe | Cursor to top-left corner aborts all commands (disabled in game mode) |
Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Browser (Web UI) โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Live โ โ Control โ โ Windows / Game Mode โ โ
โ โ View โ โ Panel โ โ Panel โ โ
โ โโโโโโฌโโโโโโ โโโโโโฌโโโโโโ โโโโโโโโโโโโโฌโโโโโโโโโโโโโ โ
โ โ โ โ โ
โโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ HTTP API (Flask) โ
โ 127.0.0.1:8745 โ
โ โ
โ /api/screenshot /api/mouse /api/key โ
โ /api/vision/* /api/ocr /api/window โ
โ /api/game /api/held /api/release_all โ
โ /api/windows /api/desktops /api/desktop โ
โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Auth Layer โ โ Watchdog โ โ OCR Engine โ โ
โ โ (token) โ โ (30s auto) โ โ (RapidOCR) โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ control.py (Core) โ
โ โ
โ Screen: mss (fast capture), PIL (processing) โ
โ Mouse: pyautogui (absolute), SendInput (relative) โ
โ Keyboard: pyautogui + SendInput+KEYEVENTF_UNICODE โ
โ Windows: Win32 API (EnumWindows, SetForegroundWindow) โ
โ Background: PrintWindow (capture), PostMessage (input) โ
โ Virtual Desktops: pyvda โ
โ Game Mode: ClipCursor + MOUSE_MOVE_RELATIVE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ backends/ (pluggable) โ
โ WindowsBackend โ LinuxBackend โ MacOSBackendโ
โ (full) โ (X11) โ (stub) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโCoordinates & Concurrency
Per-Monitor DPI awareness. control.py calls
SetProcessDpiAwarenessContext(PER_MONITOR_AWARE_V2) at import time โ
before the pyautogui import, because pyautogui touches coordinate APIs
during import and would otherwise lock the process to the interpreter
manifest's default (system-aware). With PMv2 active, every coordinate in the
system is a physical pixel end to end: mss capture, OCR bounding boxes,
pyautogui/SendInput clicks, ClipCursor. On High-DPI displays (125%/150%
scaling) nothing drifts between what OCR reports and where the mouse clicks.
Lock architecture. The server uses two independent locks instead of one global lock:
Lock | Protects | Endpoints |
| mouse, keyboard, game mode, window ops |
|
| capture, OCR, vision, enumeration |
|
A slow OCR (3โ5 s on a busy screen) no longer freezes concurrent screenshot or vision reads โ reads queue behind reads, inputs behind inputs.
Live-Loop Working Principle
This system is designed for a live perceive-act loop, not pre-written command chains:
READ โ OCR or vision reads the screen before and after every action
ONE ACTION โ each round sends a single command
VERIFY โ acceptance is "it appeared on screen", not "I sent it"
ADAPT โ if verification fails, the next step changes based on what is actually seen
This is enforced by the expect_hwnd guard: typing is refused (409) if
the foreground window doesn't match the target.
Installation
Pick the version that fits how your agent works:
You are... | Version | Install |
An AI agent user (Claude Code, Cursor, skills-capable agents) | Skill | Skill version โ copy |
An MCP-capable app (Claude Desktop, VS Code, cloud agents) | MCP | MCP Support โ |
A developer / API client | REST | this page โ |
Skill version
The portable agent skill lives in skills/computer-use/
(SKILL.md plus a full API reference). It teaches any skills-capable agent
the perceive-act-verify loop, the safety rules and the endpoint catalogue โ
the agent then drives a running server.
# Claude Code โ user-level (available in every project)
cp -r skills/computer-use ~/.claude/skills/
# Claude Code โ this project only
mkdir -p .claude/skills && cp -r skills/computer-use .claude/skills/For other skill-capable agents, copy the folder into that agent's own skills
directory. Either way the server must be running (python server.py) โ
the skill provides instructions, not a backend.
REST server
cd screen-control
pip install -r requirements.txtRequirements
Package | Purpose | Required? |
| Fast screen capture | โ Yes |
| Mouse/keyboard control | โ Yes |
| Virtual desktop management | โ Yes |
| HTTP server | โ Yes |
| Image processing | โ Yes |
| OCR (screen text reading) | โ ๏ธ Optional |
Note: The OCR package is large and may take a while to install. If it fails, everything else still works โ only the OCR feature is unavailable.
System Requirements
OS: Windows 10/11 (x64), or Linux (Ubuntu/Mint family, X11 session โ see Linux (X11))
Python: 3.10+
Display: Any resolution; the system adapts automatically
Linux (X11)
Linux is supported with limits (ROADMAP Phase 5) โ tested on Linux Mint with Cinnamon in an X11 session; other X11 desktop environments are expected to work. Windows remains the reference backend.
Requirements
OS: Ubuntu / Linux Mint family (apt-based)
Session: X11 โ check this first:
echo $XDG_SESSION_TYPE # must print: x11Wayland? Not supported โ the server fails fast instead of half-working (see Known limitations).
System packages (installed by the setup script below):
sudo apt install -y xdotool wmctrl imagemagick python3-venv python3-tk python3-dev xdotool drives input/focus, wmctrl window management, ImageMagick's
import captures window pixels (optional โ an mss region fallback exists),
python3-venv creates the virtualenv and python3-dev lets evdev
(game mode) compile from source.
One-command setup
cd screen-control
./install-linux.shThe script is idempotent and checks, in order: Wayland (exits with a clear
message), DISPLAY, the apt packages, the .venv virtualenv,
pip install -r requirements.txt, and finally reports whether game mode can
work.
uinput permissions (game mode)
Game mode writes to /dev/uinput. Verify access with:
[ -w /dev/uinput ] && echo "game mode: OK" || echo "game mode: unavailable"If it is unavailable, either remediation works (spec ยง5.4):
sudo usermod -aG input $USER # then log out and back in
# โ or a udev rule:
echo 'KERNEL=="uinput", MODE="0660", GROUP="input"' | sudo tee /etc/udev/rules.d/99-uinput.rules
sudo udevadm control --reload && sudo udevadm triggerEverything except game mode works without this access.
Run
./start-server.sh
# โ same API as Windows: http://127.0.0.1:8745 (X-Auth-Token from .token)Known limitations (Linux X11)
Limitation | Detail |
X11 only | On Wayland the backend fails fast: |
Background input = focus-first | Every |
No cursor clip in game mode | X11 cannot clip the cursor โ the game must capture the pointer itself. Emergency stop: physical |
No virtual desktops |
|
Fractional scaling untested | The verification display runs at scaling 1.0; coordinates under fractional scaling are unverified. |
| Client area only, for both |
Window geometry source |
|
| Returns |
Agent note: OCR is the slowest read (โ5โ6 s full-screen measured). Prefer
/api/vision/frameor/api/streamfor repeated reads, use region OCR, and batch reads between actions โ see AGENT_GUIDE.md โ Linux (X11) Usage.
Quick Start
# 1. Start the server
cd screen-control
python server.py
# 2. Open in browser
# http://127.0.0.1:8745
# 3. Or control via API
TOKEN=$(cat .token)
curl -H "X-Auth-Token: $TOKEN" http://127.0.0.1:8745/api/screenshot -o screen.jpgAPI Reference
Capabilities
Returns the active backend name and what it can do. Agents should call this first (see ROADMAP.md for the multi-platform plan).
GET /api/capabilities
โ {"ok": true, "backend": "windows",
"capabilities": {"screen_capture": true, "game_mode": true, ...}}Feature values: true (supported), false (absent), null (unknown โ
stub backend), "optional" (depends on an optional dependency).
Platform Support Matrix
Capability | Windows | Linux X11 | Linux Waylandโ | macOS |
Screen capture | Full | Full | Portal-dependent | Permission required |
OCR | Full/optional | Full/optional | Full/optional | Full/optional |
Mouse control | Full | Full | Restricted | Accessibility permission |
Keyboard control | Full | Full | Restricted | Accessibility permission |
Window enumeration | Full | WM-dependent | Limited | Accessibility/API-dependent |
Background input | Strong | Focus-first (stealing) | Usually unavailable | Limited |
Virtual desktops | Supported | No (503) | DE/WM-dependent | Spaces-specific |
Game mode | Supported | Experimental | Limited | Experimental |
Linux X11 is implemented and supported with limits โ setup, requirements and the full limitations list are in Linux (X11). Wayland fails fast with
UNSUPPORTED_DISPLAY_SERVER(501), and macOS remains a fail-closed stub: every operation returnsBACKEND_UNAVAILABLE(501) until ROADMAP Phase 7. Windows is the reference backend.โ Wayland column is hypothetical capability planning only โ the server never starts on Wayland (see the note above), so no Wayland cell is currently reachable.
Authentication
Every request must include the X-Auth-Token header. The token is
generated on each server start and written to .token.
TOKEN=$(cat .token)Code | Meaning |
401 | Missing or invalid token |
415 | POST without |
Token bootstrap (for the bundled web UI):
GET /token
โ {"ok": true, "token": "abc123..."}The
/tokenendpoint answers only loopback callers on a loopback bind: the check uses the accepted socket's peer address (a LAN client cannot spoof it), theHostheader guards against DNS rebinding, and the response is never cached. When the server is bound to0.0.0.0or is reached from a non-loopback peer,/tokenreturns 403.
Screen Capture
GET /api/screenshot
Returns a JPEG screenshot.
Parameter | Type | Default | Description |
| int | 1 | Monitor index |
| string | โ |
|
curl -H "X-Auth-Token: $TOKEN" -o screen.jpg http://127.0.0.1:8745/api/screenshot
curl -H "X-Auth-Token: $TOKEN" "http://127.0.0.1:8745/api/screenshot?region=0,0,800,600"GET /api/info
Returns screen dimensions and system state.
{"ok": true, "width": 1920, "height": 1080, "ocr_available": true,
"failsafe": true, "game_mode": false}Mouse Control
POST /api/mouse
action | Required params | Optional params | Description |
|
|
| Move cursor to absolute position |
|
|
| Click at position |
|
|
| Scroll wheel (positive=up) |
|
|
| Drag between two points |
|
| โ | Press and hold mouse button |
|
| โ | Release held mouse button |
# Click at center of screen
curl -X POST http://127.0.0.1:8745/api/mouse -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"click","x":960,"y":540,"button":"left"}'
# Right-click
curl -X POST http://127.0.0.1:8745/api/mouse -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"click","button":"right","x":960,"y":540}'
# Scroll down
curl -X POST http://127.0.0.1:8745/api/mouse -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"scroll","clicks":-3}'Keyboard Control
POST /api/key
action | Required params | Description |
|
| Press and release a key |
|
| Hold a key down (tracked for watchdog) |
|
| Release a held key |
|
| Key combination (e.g. |
|
| Type text (Unicode, layout-independent) |
Optional param | Default | Description |
| โ | Window handle to verify focus (409 if mismatch) |
| 0.03 | Delay between characters for |
# Press Enter
curl -X POST http://127.0.0.1:8745/api/key -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"press","key":"enter"}'
# Ctrl+C
curl -X POST http://127.0.0.1:8745/api/key -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"hotkey","keys":["ctrl","c"]}'
# Type text (Turkish characters supported)
curl -X POST http://127.0.0.1:8745/api/key -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"type","text":"Merhaba dรผnya"}'
# Hold W key down (for walking in games)
curl -X POST http://127.0.0.1:8745/api/key -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"down","key":"w"}'OCR (Screen Reading)
POST /api/ocr
Converts on-screen text to machine-readable format.
Param | Type | Default | Description |
| array | โ |
|
{
"ok": true,
"text": "Hello World\nFile Edit View",
"lines": ["Hello World", "File Edit View"],
"items": [
{"text": "Hello World", "x": 960, "y": 40},
{"text": "File Edit View", "x": 100, "y": 15}
]
}# Full screen OCR
curl -X POST http://127.0.0.1:8745/api/ocr -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{}'
# Region-only (faster, ~10x for small regions)
curl -X POST http://127.0.0.1:8745/api/ocr -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"region":[0,0,800,100]}'Vision Access (Image Models)
Three endpoints for models that can consume images:
Endpoint | Description |
| Single JPEG frame (raw or base64) |
| MJPEG live stream |
| Text-based motion detection (no vision needed) |
GET /api/vision/frame
Param | Default | Description |
| 1.0 | Downscale factor (0.5 = half size) |
| 0 | 1 for greyscale |
| 80 | JPEG quality (20-95) |
| โ |
|
| โ |
|
# Half-size greyscale frame as base64 (for text-only models)
curl "http://127.0.0.1:8745/api/vision/frame?scale=0.5&gray=1&format=base64" \
-H "X-Auth-Token: $TOKEN"GET /api/stream
MJPEG live stream. Drop into <img src> or consume frame-by-frame.
Param | Default | Description |
| 10 | Frames per second (1-30) |
| 70 | JPEG quality |
| 1.0 | Downscale factor |
| โ |
|
POST /api/vision/diff
Text-based motion detection โ no vision model required.
Body | Description |
| Compare against last stored frame |
| Store current frame for next comparison |
| Compare against provided previous frame |
{
"ok": true,
"changed": true,
"changed_pct": 12.5,
"bbox": [100, 200, 400, 350],
"tiles": [
{"row": 2, "col": 4, "pct": 35.2, "center": [1000, 390]}
]
}Window Management
GET /api/windows
List all visible windows.
{
"ok": true,
"windows": [
{
"hwnd": 123456,
"title": "My Application",
"process": "app.exe",
"pid": 7890,
"focused": true,
"rect": [0, 0, 1920, 1080],
"desktop": 1
}
]
}POST /api/window
action | Required | Optional | Description |
|
| โ | Bring window to foreground |
|
|
| Safe close via WM_CLOSE |
|
| โ | Force kill (task-manager style) |
|
| โ | Set always-on-top |
|
| โ | Remove always-on-top |
|
| โ | Maximise window |
# Focus a window
curl -X POST http://127.0.0.1:8745/api/window -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"hwnd":12345,"action":"focus"}'
# Safe close (with title verification)
curl -X POST http://127.0.0.1:8745/api/window -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"close","hwnd":12345,"expect_title":"Notepad"}'
# Kill process
curl -X POST http://127.0.0.1:8745/api/window -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"kill","hwnd":12345,"pid":7890}'POST /api/launch
Spawn an application, open a URL, or open a local file. Exactly one of
app | url | file. Never runs through a shell: app is a plain command
name resolved on PATH ([A-Za-z0-9._+-]+), url/file go through
xdg-open.
Launch policy: interpreter and executor names (
python*,node,sh/bash/cmd/powershell,env,xargs,sudo,curl, โฆ) are refused with 400 โ/api/launchis for GUI applications, not a remote code-execution endpoint.
Field | Type | Description |
| string | Command name; must exist on |
| string |
|
| string | Absolute path to an existing file |
| list | Arguments for |
| string | Also wait for a window whose title contains it |
| number | Wait for |
{"ok": true, "pid": 4321, "window": {"hwnd": ..., "title": "..."}}With expect_title, window is the match or null (spawn succeeded, no
window yet) โ the HTTP status stays 200 either way.
curl -X POST http://127.0.0.1:8745/api/launch -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"app":"firefox","expect_title":"Mozilla Firefox","timeout":15}'GET /api/window/wait
Block until a window whose title contains title (case-insensitive
substring) appears, then return it. timeout default 10 s, max 30 s;
200 with the window, or 408 OPERATION_TIMEOUT.
curl -H "X-Auth-Token: $TOKEN" \
"http://127.0.0.1:8745/api/window/wait?title=Notepad&timeout=10"Focus-Free (Background) Control
Read and control windows without stealing focus โ the user keeps working on their main desktop.
Linux (X11) note: background control there is focus-first โ the target window is focused, then input is sent globally (focus stealing). Only background capture is truly focus-free. See Known limitations.
GET /api/window/capture
Capture a window via PrintWindow (works even on another virtual desktop).
Param | Description |
| Window handle |
| 1 = client area only |
| 1 = return OCR text instead of image |
# Capture window as PNG
curl "http://127.0.0.1:8745/api/window/capture?hwnd=12345" \
-H "X-Auth-Token: $TOKEN" -o window.png
# Capture + OCR in one call
curl "http://127.0.0.1:8745/api/window/capture?hwnd=12345&ocr=1" \
-H "X-Auth-Token: $TOKEN"POST /api/window/post
Send input to a window, choosing the delivery path automatically.
action | Description |
| Type text (Unicode-safe) |
| Send a key press |
| Send a key combination |
| Click at client coordinates |
| Scroll the window |
| Drag inside the window |
Optional mode parameter controls routing:
mode | Behavior |
| Decided by input-mode probe (see below) |
| Force PostMessage path (window keeps focus/z-order) |
| Force focus + SendInput path |
# Type into a background Notepad
curl -X POST http://127.0.0.1:8745/api/window/post -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"hwnd":12345,"action":"type","text":"Hello from background!"}'Routing rules (mode=auto):
postmessageโ classic Win32 app: background PostMessage, no focus change.uiaโ WinUI/UWP/XAML surface (single DirectX canvas, no Win32 child controls): posted messages are silently swallowed, so the window is focused and the action is replayed through SendInput (client coords converted to screen). This is the documented fallback for modern apps.focusedโ window is already foreground: focused SendInput path.invalidโ HTTP 409; not a reachable top-level window.
GET /api/window/input-mode
Classify how a window receives input before posting to it. Returns one of
focused | postmessage | uia | invalid.
curl "http://127.0.0.1:8745/api/window/input-mode?hwnd=12345" \
-H "X-Auth-Token: $TOKEN"WinUI note: New Notepad (and other XAML-hosted apps) has no classic child Edit control to post to โ the whole UI is one DirectX surface.
input-modereportsuiafor these;/api/window/postthen automatically uses the focused SendInput path./api/window/childrenremains useful for classic apps with real child controls.
GET /api/window/children
List child controls of a window (class name + title + hwnd).
curl "http://127.0.0.1:8745/api/window/children?hwnd=12345" -H "X-Auth-Token: $TOKEN"Virtual Desktops
GET /api/desktops
List all virtual desktops.
POST /api/desktop
action | Params | Description |
|
| Switch to desktop N |
| โ | Create a new desktop |
curl http://127.0.0.1:8745/api/desktops -H "X-Auth-Token: $TOKEN"
curl -X POST http://127.0.0.1:8745/api/desktop -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"switch","number":2}'Game Mode
action | Params | Description |
|
| Lock cursor to center, enable game input |
|
| Rotate camera (relative mouse) |
| โ | Release cursor + all held input |
| โ | Keep-alive for long holds |
# Start game mode
curl -X POST http://127.0.0.1:8745/api/game -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"start","sensitivity":12}'
# Look right
curl -X POST http://127.0.0.1:8745/api/game -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"move","dx":50,"dy":0}'
# Hold W to walk forward
curl -X POST http://127.0.0.1:8745/api/key -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"down","key":"w"}'
# ... later ...
curl -X POST http://127.0.0.1:8745/api/key -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"up","key":"w"}'
# Stop game mode
curl -X POST http://127.0.0.1:8745/api/game -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"stop"}'Safety Endpoints
GET /api/held
Returns currently held keys/buttons and watchdog status.
{
"ok": true,
"keys": ["w", "shift"],
"buttons": ["left"],
"game_mode": true,
"idle_seconds": 5.2,
"watchdog_count": 0,
"last_watchdog": null
}POST /api/release_all
Emergency: release everything (held keys, mouse buttons, game-mode cursor lock).
curl -X POST http://127.0.0.1:8745/api/release_all -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{}'๐ค For AI Agents
A dedicated, comprehensive guide for AI agents (LLMs, vision models, automation frameworks) is available in AGENT_GUIDE.md.
Prefer loading this as a skill instead of browsing docs? Install the Skill version.
It covers:
Environment routing โ find Windows vs Linux (X11/Wayland) first
Perceive-act loop (read โ plan โ act โ verify)
Focus guard (
expect_hwnd) to prevent wrong-window accidentsApp automation and game control workflows
Linux (X11) usage: slow-OCR batching, capture semantics, game-mode caveats
Vision access for image-capable models
Text-based motion detection
Bandwidth optimization
Complete curl examples
MCP Support (One-Click Cloud Agents)
Model Context Protocol (MCP) turns this project into a plug-and-play toolbox for any MCP-capable agent: Claude Desktop, Claude Code, Cursor, VS Code Copilot Agent mode, custom cloud agents โ no custom glue code, no curl scripts. The agent discovers and calls the tools natively.
How it works
MCP agent (cloud or desktop)
โ MCP protocol (stdio or streamable-HTTP)
โผ
mcp_server.py โ thin wrapper: tools โ HTTP calls, token auto-read
โ REST + X-Auth-Token (localhost only)
โผ
server.py โ the single source of truth:
auth, locks, watchdog, focus guard, all safety rulesmcp_server.py adds no new powers โ every safety mechanism
(auth token, input/read locks, watchdog, Alt+F4 block, focus guard,
failsafe) stays enforced by server.py.
Setup
pip install mcp # optional dependency (see requirements.txt)
python server.py # start the REST server first (it writes .token)The MCP server auto-reads the token from .token (or the
SCREEN_CONTROL_TOKEN env var) โ zero configuration.
Desktop agents (stdio transport)
Claude Desktop โ claude_desktop_config.json:
{
"mcpServers": {
"screen-control": {
"command": "python",
"args": ["C:/path/to/screen-control/mcp_server.py"]
}
}
}Claude Code: claude mcp add screen-control -- python C:/path/to/screen-control/mcp_server.py
Cursor / VS Code: add the same entry to their MCP config files.
Remote / cloud agents (streamable-HTTP transport)
python mcp_server.py --http --port 8751
# MCP endpoint: http://127.0.0.1:8751/mcpThe HTTP transport is token-protected: every request must carry the
X-Auth-Token header (same token as the REST server). Query-string tokens
(?token=...) are rejected by design โ URLs leak into proxy/tunnel
logs, browser history and shared links, and this token grants full desktop
control. Clients that cannot send custom headers should run a local stdio
mcp_server.py instead. Only GET /health is open, for liveness probes.
DNS-rebinding protection is disabled on this transport deliberately โ
tunneled requests arrive with a foreign Host header, and the rebinding
threat is already covered by the token guard.
For a cloud agent, expose it through a tunnel:
cloudflared tunnel --url http://127.0.0.1:8751
# โ prints a https://<random>.trycloudflare.com URLThen configure the agent's MCP connection with <tunnel-url>/mcp plus the
token from .token as a header (X-Auth-Token).
Headerless connectors (scoped keys)
For clients that cannot send custom headers (e.g. web connectors that only take an endpoint URL), create a scoped API key โ a persistent, optionally time-limited credential โ and embed it in the URL path:
# Create a 24-hour scoped key (requires the server to be running)
curl -X POST http://127.0.0.1:8745/api/keys -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"create","name":"spark","expires_in_hours":24,"scopes":["mcp"]}'
# Connector endpoint becomes:
# https://<tunnel-url>/mcp/<scoped-key>Design guarantees (SC-06):
The master session token is refused in URLs (403) โ only scoped keys may travel there
Keys carry scopes (
rest,mcp): a key minted with{"scopes":["mcp"]}cannot call the REST API at all, and any scoped key is refused on admin endpoints (/api/keys,/api/session*) โ those accept the master token onlyScoped keys expire automatically; expired keys authenticate nothing
Scoped keys are revocable by name at any moment via
POST /api/keys({"action":"revoke","name":"spark"}) โ revocation takes effect immediately on every endpointThe
.apikeysfile stores only SHA-256 hashes, never raw keys, and is written with0600permissions
โ ๏ธ A tunnel exposes PC control to the internet. Keep the token secret, prefer short-lived tunnels and scoped keys for headerless connectors, and stop the server when not in use.
One-Command Startup (launcher, tunnel opt-in)
start-server.bat automates the whole setup and prints a paste-ready
scoped key for your cloud agent:
Downloads
cloudflared.exefrom a pinned release and verifies its SHA-256 against Cloudflare's published checksum (no mutablelatestURL, no unverified binary)Stops leftover instances from a previous run
Starts the REST server (port 8745) and the MCP HTTP server (port 8751)
Waits until both are healthy (
/tokenand/healthprobes)Starts the quick tunnel only when you opt in with
start-server.bat --tunnel, extracts its public URL fromtunnel.log, and prints the summary:
============================================================
ALL SYSTEMS RUNNING
============================================================
Local REST API : http://127.0.0.1:8745
Local MCP : http://127.0.0.1:8751/mcp
Public MCP URL : https://<random>.trycloudflare.com/mcp
------------------------------------------------------------
PASTE INTO YOUR CLOUD AGENT (MCP connector settings)
------------------------------------------------------------
Endpoint : https://<random>.trycloudflare.com/mcp
Header : X-Auth-Token: <24-hour scoped key "launcher">
(the master token is NOT shown; revoke anytime)
------------------------------------------------------------Without --tunnel nothing is exposed to the internet โ the launcher is a
local-only startup. The pasted credential is a 24-hour mcp-scoped key
(minted locally, revocable via POST /api/keys {"action":"revoke",...}).
stop-server.bat stops all three (REST, MCP, tunnel) in one go.
Available tools (16)
Category | Tools |
Perception |
|
Mouse / keyboard |
|
Windows |
|
Game mode |
|
Which transport for whom
Consumer | Transport | Command |
Claude Desktop / Cursor / VS Code (local) | stdio |
|
Claude Code | stdio |
|
Cloud / remote agents | streamable-HTTP |
|
Note: This project targets MCP Python SDK 2.x (
MCPServerAPI). With SDK 1.x, replace the import withfrom mcp.server.fastmcp import FastMCP, ImageandMCPServerwithFastMCP.
Security Model
Threat: Malicious Web Pages (CSRF)
Even bound to 127.0.0.1, a malicious page in the browser can trigger
non-preflighted requests (text/plain fetch, HTML form POST) to localhost.
The browser blocks the response but not the request โ the server
would still execute the command.
Mitigation: Every request requires X-Auth-Token. A foreign page
cannot read this token (Same-Origin Policy), so it cannot authenticate.
Additional layers:
POST requests must use
Content-Type: application/json(415 otherwise)This blocks form-encoded and text-plain POSTs even if the token leaked
Host header trust (DNS rebinding): when bound to loopback, requests carrying a non-loopback
Hostheader are refused with421โ a rebinding page that resolves its domain to127.0.0.1cannot read/tokenor call the API/tokenand/responses carryCache-Control: no-storeso the credential is never persisted by browsers or proxies
Threat: Stuck Keys / Game Mode Lock
In game mode, ClipCursor pins the cursor to a 2ร2 box โ the classic
pyautogui failsafe (cursor to top-left) does not work.
Mitigations:
Physical
Esc/Alt+Tabโ real hardware input; this API cannot block it, and it always worksPOST /api/release_allโ instant release of everythingWatchdog (automatic) โ 30 s of server-side inactivity with held input triggers automatic release
Threat: Wrong Window Typing
Mitigations:
expect_hwndguard on/api/keyโ if the foreground window doesn't match, typing is refused with 409The focused path of
/api/window/postverifies the focus after the focus switch and before any synthetic input (409 on mismatch) โ input is never replayed into whatever window happens to be foregroundfocus_window()raises on failure instead of silently returning
Threat: Dangerous Key Combos
Mitigation: Blocked at the API level (403) on every delivery path โ
the direct /api/key route, the background /api/window/post route
(PostMessage), and the focused fallback route share one safety policy
(control._assert_allowed):
Alt+F4โ the only banned Alt combo (Alt+Tab, Alt+menu are legitimate)Win key โ prevents Start menu, task switching
Ctrl+Alt+Delโ system security screenShift+Deletestyle โ prevents permanent deletion
Threat: Killing System Processes
Mitigations:
The process name is resolved from the PID directly (Win32 toolhelp snapshot), not from the visible-window inventory โ windowless/background system processes get the same protection as visible ones
Critical system processes are blacklisted (default-deny for unknown PIDs):
winlogon.exe,csrss.exe,smss.exe,services.exe,lsass.exe,svchost.exe,system,registry,dwm.exeOptional
expect_processconfirmation: a mismatch aborts the kill with409โ protects against killing a newly-reused PID
Threat: Resource Exhaustion (rogue agent / DoS)
A token-holding but misbehaving client should not be able to exhaust memory or starve the input lock.
Mitigations:
MAX_CONTENT_LENGTH= 1 MB โ oversized request bodies are rejected (413)regionwidth/height/area andscaleare bounded (400 otherwise)textpayloads are capped at 10,000 characters per input callMJPEG streams are capped at 10 concurrent clients (429 beyond that)
Pillow decompression-bomb limit is set for client-supplied images
Network Access
The server binds to 127.0.0.1 by default. To expose it to the network:
python server.py --host 0.0.0.0 # โ ๏ธ anyone on the network can control this machineGame Mode Guide
Setup
# 1. Focus the game window
curl -X POST http://127.0.0.1:8745/api/window -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"hwnd":GAME_HWND,"action":"focus"}'
# 2. Start game mode
curl -X POST http://127.0.0.1:8745/api/game -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"start","sensitivity":12}'Camera Look
# Look right
curl -X POST http://127.0.0.1:8745/api/game -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"move","dx":50,"dy":0}'
# Look down
curl -X POST http://127.0.0.1:8745/api/game -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"move","dx":0,"dy":30}'Movement
# Walk forward (hold W)
curl -X POST http://127.0.0.1:8745/api/key -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"down","key":"w"}'
# ... walk for a while ...
# Release W
curl -X POST http://127.0.0.1:8745/api/key -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"up","key":"w"}'Minecraft-Specific
# Place block (right-click)
curl -X POST http://127.0.0.1:8745/api/mouse -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"click","button":"right","x":960,"y":540}'
# Break block (hold left-click)
curl -X POST http://127.0.0.1:8745/api/mouse -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"down","button":"left"}'
# ... after breaking ...
curl -X POST http://127.0.0.1:8745/api/mouse -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"up","button":"left"}'
# Select hotbar slot
curl -X POST http://127.0.0.1:8745/api/key -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"press","key":"1"}'
# Open inventory
curl -X POST http://127.0.0.1:8745/api/key -H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" -d '{"action":"press","key":"e"}'Suitability
Game Type | Suitable? | Notes |
Minecraft (building) | โ Yes | Place blocks, walk, mine |
Minecraft (PvP) | โ No | Too slow for fast combat |
Turn-based games | โ Yes | Ample time for readโactโverify |
RPG / adventure | โ Yes | Inventory, dialogue, exploration |
Fast FPS | โ No | Reaction time insufficient |
Puzzle games | โ Yes | Click-based, read-heavy |
Vision Access Guide
For Image-Capable Models
If the consuming model can process images, use the vision endpoints directly:
GET /api/vision/frame?scale=0.5&gray=1&quality=70This returns a single JPEG that the model can analyze for:
Game HUD elements (health, mana, inventory)
On-screen text (menus, chat, tooltips)
Visual scene understanding (blocks, entities, terrain)
For Text-Only Models
Use the diff endpoint for motion detection without vision:
POST /api/vision/diff {"grab":"gray"} โ first call: stores frame
POST /api/vision/diff โ subsequent calls: returns diffThe response tells you where things changed (tile coordinates) and how much (percentage), which is sufficient for:
Detecting that an action had an effect
Locating moving elements on screen
Tracking animation state changes
Bandwidth Optimization
Approach | Payload | Use Case |
| ~500 KB | Full detail |
| ~50 KB | Good for most vision models |
| ~10 KB | Maximum compression |
| ~1 KB | Text-only agents |
| Variable | Focus on specific area |
Troubleshooting
"OCR engine not installed"
pip install rapidocr-onnxruntimeServer won't start (port in use)
# Find the process using port 8745
netstat -ano | findstr ":8745"
# Kill it
taskkill /PID <pid> /F"Focus mismatch" (409) when typing
The foreground window changed between the focus call and the type call.
Solution: always pass expect_hwnd and verify focus before typing.
Window not found
The window may have been closed or may be a system window that
EnumWindows doesn't expose. Try:
curl http://127.0.0.1:8745/api/windows -H "X-Auth-Token: $TOKEN"Game mode cursor stuck
Use POST /api/release_all or press Esc / Alt+Tab physically.
High OCR latency
OCR on a full 1920ร1080 screen can take from a few seconds up to ~30 s depending on your CPU and on-screen complexity. Use a region โ small crops are typically 10ร faster:
{"region": [0, 0, 800, 100]}Turkish characters not appearing
The system uses SendInput + KEYEVENTF_UNICODE which is layout-independent.
If characters still don't appear, the target app may not support Unicode
input โ try POST /api/window/post with action: "type" instead.
Linux: server exits immediately with "Wayland display server detected"
Expected on a Wayland session โ the backend fails fast with
UNSUPPORTED_DISPLAY_SERVER (501) instead of half-working. Log out, choose
the X11 session ("Cinnamon on Xorg") at the login screen, then start the
server again. See Linux (X11).
Linux: "xdotool is not installed or not on PATH" (501)
The X11 helper tools are missing. Install them (or re-run the installer):
sudo apt install xdotool wmctrlProject Structure
screen-control/
โโโ server.py # Flask HTTP server + all API endpoints
โโโ core/ # PlatformBackend interface + standardized errors
โ โโโ backends.py # Abstract backend + lazy discovery
โ โโโ errors.py # ApiError envelope + error codes
โโโ backends/ # OS implementations behind PlatformBackend
โ โโโ windows.py # Reference backend (moved from control.py)
โ โโโ linux.py # X11 backend: xdotool/wmctrl + mss + uinput (Phase 5)
โ โโโ imageops.py # Shared PIL helpers (frame diff, JPEG, scaling)
โ โโโ uinput.py # Virtual input device for Linux game mode
โ โโโ macos.py # Fail-closed stub (ROADMAP Phase 7)
โ โโโ fake.py # In-memory backend for tests
โ โโโ forbidden.py # Shared blocked-key policy
โโโ control.py # Compatibility shim re-exporting backends.windows
โโโ tests/unit/ # Offline unit + integration tests (no real input)
โโโ mcp_server.py # MCP server (stdio + streamable-HTTP) โ thin wrapper over the API
โโโ sdk/
โ โโโ screen_control.py # Python SDK client (pip-installable style)
โโโ index.html # Bundled web UI (live view + control panels)
โโโ docs/images/ # README assets (demo GIF captured by the API itself)
โโโ requirements.txt # Python dependencies
โโโ start-server.bat # One command: REST + MCP (+ tunnel with --tunnel) (Windows)
โโโ stop-server.bat # Stop all three processes
โโโ install-linux.sh # One-command Linux setup (apt, venv, uinput check)
โโโ start-server.sh # Linux launcher (.venv/bin/python server.py)
โโโ test-security.py # Security + game-mode test suite (34 checks)
โโโ test-linux.py # Live Linux X11 acceptance suite (7 items)
โโโ test-game.py # Live game-mechanics test (app launch โ draw โ safe close)
โโโ test-endtoend.py # End-to-end test: open Notepad โ type โ save โ verify
โโโ .github/workflows/ # CI: runs the security suite on every push
โโโ AGENT_GUIDE.md # AI agent integration guide (separate from this file)
โโโ README.md # This file
โโโ .token # Auto-generated auth token (gitignored)Testing
Prerequisites
The server must be running:
cd screen-control
python server.pySecurity test suite
Tests authentication, blocked key combos, window management, safe close, critical process protection, and game mode โ all non-destructive.
cd screen-control
python test-security.pyExpected output:
== Token Authentication ==
โ Missing token -> 401
โ Wrong token -> 401
โ Correct token -> 200
โ Non-JSON POST -> 415
== Blocked Key Combos ==
โ Alt+F4 blocked (403)
โ Win key blocked (403)
โ Win+D blocked (403)
โ Delete blocked (403)
== Window List ==
โ Windows list requires GET
โ Window list is non-empty โ 8 windows
โ Exactly one focused window
== Safe Close Verification ==
โ Wrong title aborts close
== Critical Process Protection ==
โ System process (pid 4) rejected (403)
โ pid 0 rejected (403)
== Game Mode ==
โ Game mode started
โ Relative camera look
โ Game mode stopped
== Watchdog (dry run) ==
โ Held state returns ok
โ Watchdog count reported
========================================
RESULT: 19 passed, 0 failedLive game-mechanics test
Launches a real application (mspaint or notepad), performs hold-to-draw game mechanics, verifies via pixel analysis, then safely closes with "Don't Save" dialog handling.
cd screen-control
python test-game.pyNote: This test launches a real application. It handles cleanup automatically (sends WM_CLOSE and clicks "Don't Save" if a dialog appears).
Live Linux acceptance test (Linux X11 only)
Seven-item live check of the Linux backend: mouse move/click, typing +
hotkey, screenshot, OCR, window list/focus, game mode (uinput) and the
native-game item (printed as SKIP โ no Linux game is installed). Needs a
running server and a real X11 session; every helper window is pid-unique and
only those are ever focused or clicked.
cd screen-control
./start-server.sh & # server must be running
.venv/bin/python test-linux.py # โ "RESULT: 6 passed, 0 failed"; item 7 prints SKIPContributing
Fork the repository
Create a feature branch
Make your changes
Test on a Windows machine
Submit a pull request
Code Style
Python: PEP 8, type hints, docstrings on all public functions
Docstrings: English, Google style
Error messages: English, descriptive
Comments: English, explain why not what
License
MIT License. See LICENSE for details.
Built with โค๏ธ for local automation and AI agent research.
Available Tools
16 toolsclose_windowA
Close a window safely (WM_CLOSE after verification โ never blind Alt+F4). Pass expect_title/expect_process to refuse (409) if the window changed.
Inputs: hwnd (required), expect_title, expect_process. Returns: result
focus_windowB
Bring a window to the foreground (focus it).
Inputs: hwnd (required). Returns: result
gameB
Game mode for FPS-style control. action: start (clip cursor to center) | move (relative camera look by dx,dy pixels * sensitivity) | stop | heartbeat (keep-alive during long holds). Combine with keyboard() down/up for WASD and mouse(action='down'/'up') for shooting/building.
Inputs: action (required), dx, dy, sensitivity. Returns: result
get_heldA
List currently held keys/buttons and watchdog status.
Inputs: no named parameters. Returns: result
get_infoA
Server/PC status: screen size, monitors, OCR availability, failsafe and game-mode state.
Inputs: no named parameters. Returns: result
keyboardA
Control the keyboard. action: press | hotkey | type | down | up. press: key name (enter, f11, a...); hotkey: keys=["ctrl","s"]; type: Unicode-safe text. expect_hwnd refuses (409) the action if the foreground window differs โ use it to avoid typing into the wrong app.
Inputs: key, keys, text, action, +2 more. Returns: result
list_windowsA
List visible top-level windows: hwnd, title, process name, pid.
Inputs: no named parameters. Returns: result
motion_diffA
Text-only change detection between two snapshots: which tiles of the screen changed and their clickable centers. Use to verify an action had an effect or to spot movement without OCR/vision.
Inputs: region. Returns: result
mouseB
Control the mouse. action: move | click | scroll | drag | down | up. click uses x,y (optional = current pos); drag goes (x1,y1)->(x,y); scroll uses 'clicks' (negative = down). Physical-pixel coordinates.
Inputs: x, y, x1, y1, +4 more. Returns: result
ocr_screenA
Read the screen as text with coordinates (OCR). Best for menus, dialogs, editors, chat โ anything text-heavy. Returns lines plus per-item centers for clicking. 'region' is an optional "x,y,w,h" crop.
Inputs: region, scan_focus. Returns: result
release_allA
Release every held key and button (emergency reset). Safe to call anytime.
Inputs: no named parameters. Returns: result
screenshotA
Capture the screen as an image (for vision-capable models). 'region' = "x,y,w,h"; 'scale' 0-1 shrinks to save bandwidth; 'quality' 1-100.
Inputs: scale, region, monitor, quality.
window_capture_ocrA
Capture a background window WITHOUT focusing it; with ocr=1 (default) returns its text directly โ read other apps' content while the user works.
Inputs: hwnd (required), ocr. Returns: result
window_childrenA
List child controls of a window (class name, title, hwnd). Useful for classic Win32 apps with real child controls (e.g. an Edit box) โ target the child hwnd in window_post. Modern WinUI/UWP apps have no classic children; use window_input_mode to detect them.
Inputs: hwnd (required). Returns: result
window_input_modeA
Classify how a window receives input BEFORE posting to it: postmessage (classic Win32) | uia (WinUI/UWP: focus+SendInput fallback) | focused (already foreground) | invalid (dead window).
Inputs: hwnd (required). Returns: result
window_postB
Send input to a window in the background. action: type | key | hotkey | click | scroll. mode: auto (recommended โ routes WinUI/UWP apps through the focused SendInput path automatically) | background | focused. Note: 'uia' routing focuses the window (unavoidable for modern apps).
Inputs: hwnd (required), action (required), x, y, +4 more. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelogโฆ
TDQS
Scored across 16 tools
Each tool targets a distinct mechanismโscreen capture, OCR, motion detection, global input, window-specific input, window introspection, and game mode. Potentially similar tools like ocr_screen and window_capture_ocr are cleanly separated by foreground screen versus background window. No two tools appear to do the same job.
Most tools follow a readable snake_case convention with verb-first names like list_windows, focus_window, close_window, and release_all. A few noun-style names like mouse, keyboard, and game, plus window_post and window_capture_ocr, are minor deviations but still clear and predictable.
Sixteen tools is on the higher end but each earns its place across capture, OCR, input, window management, and game mode. The count feels slightly heavy but remains well-scoped for a desktop automation server.
Core workflows are well covered: screen capture, OCR, change detection, global and background input, window discovery, focusing, posting, and closing. Minor gaps like querying the current cursor position or window geometry are absent but most operations have workarounds.
Maintenance
Related MCP Connectors
Connect ChatGPT, Claude, Cursor or VS Code to your Windows PC: files, terminal, browser, apps.
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Connect AI assistants to your approved computer for files, commands, browser and desktop tasks.
Web scraping, browser automation, screenshots and AI data extraction for AI agents via MCP.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceMCP server that enables Claude to control your computer, similar to Anthropic's computer use but easy to set up locally.4,740 npm400MIT
- AlicenseAqualityDmaintenanceEnables LLM agents to capture screenshots, control mouse/keyboard, and manage windows on desktop platforms, primarily Windows, via an MCP server.161MIT
- AlicenseAqualityCmaintenanceAllows AI clients to see and control Windows 10/11 desktops via MCP, with screenshots, UI Automation, Chrome CDP, keyboard/mouse, and terminal using semantic element targeting.30726 npmMIT
- AlicenseNot gradedqualityCmaintenanceLocal MCP server for Gateway-managed computer use that exposes computer.* tools with desktop control, OCR, and user-visible safety overlays.6 npm1MIT