Skip to main content
Glama

mcp-windows-debug

CI TypeScript License: MIT

A TypeScript/Node.js MCP server that plugs into OpenCode over stdio and gives the model eyes and hands on a Windows machine: it reads project files, captures screenshots, moves the mouse and types keys, and runs an auto-debug loop against a target application.

Safety is the point of the whole design. A separate native C++ watchdog process installs global low-level keyboard and mouse hooks so a human can always click a protected abort button, even while the model is injecting input. The Node MCP server and the watchdog are two independent processes, so a stalled Node event loop cannot freeze your input or silently drop the safety layer. Every action flows through three gates: a governor, a freshness check, and a window-scoping guard. Details are in the Security model section below.

This is a Windows-only v1. macOS and Linux backends plug in later behind the same provider interfaces; they are not implemented yet.

Quick start

git clone https://github.com/wgm66/mcp-windows-debug.git
cd mcp-windows-debug
npm install && npm run build
cd src\watchdog && build.bat   # build the C++ watchdog (MSVC required)
node dist\index.js --validate-config  # verify your OpenCode config

Related MCP server: Desktop Commander MCP Server

Installation

Prerequisites:

  • Node.js 20 or newer, plus npm

  • Windows 10 or 11

  • Administrator access, needed only to run the watchdog (see below)

Install dependencies and build the TypeScript:

npm install
npm run build

npm run build runs tsc and produces dist/index.js, which is the entry point OpenCode launches.

Next, build the watchdog. It is a C++ Win32 console app compiled with MSVC, no CMake, MSBuild, or MinGW involved:

cd src\watchdog
build.bat

build.bat requires the VS2019 Build Tools (MSVC 14.29) and the Windows SDK. The toolchain paths are hardcoded in the script, so it expects them at their default install locations. The output is src\watchdog\watchdog.exe, which the Node server locates relative to the project root at runtime.

The watchdog must run elevated. Global low-level hooks refuse to install from a non-elevated process. Two ways to satisfy this:

  1. Start OpenCode from an elevated terminal, so the spawned watchdog inherits elevation.

  2. Pre-start the watchdog as admin yourself before starting a debug session.

The server cannot request UAC elevation on its own in this build. A debug session that cannot reach an elevated watchdog fails with ELEVATION_REQUIRED, and a non-elevated watchdog run prints ERROR_ACCESS_DENIED and exits with code 1 rather than silently doing nothing.

OpenCode configuration

Add a windows-debug entry under the mcp key in your OpenCode config (opencode.json). Note the key is mcp, not mcpServers:

{
  "mcp": {
    "windows-debug": {
      "type": "local",
      "command": ["node", "<abs-path>/dist/index.js"],
      "environment": {}
    }
  }
}

Replace <abs-path> with the absolute path to this project, using forward slashes so the JSON needs no escaping. For example, if the project lives at G:\工程开发\AI全场景图形化调试, the command becomes:

"command": ["node", "G:/工程开发/AI全场景图形化调试/dist/index.js"]

The command is an array of argv tokens. The environment map is empty by default; the per-session watchdog token is generated by the server itself and passed to the watchdog over the process environment, so you do not need to set anything here.

Usage

A debug session has a fixed shape: register protected abort buttons, start the session, let the model work through the auto-debug loop, then end the session.

Register abort buttons. A session cannot start with zero protected regions. Pass one or more screen rectangles to start_debug_session as regions ({ x, y, w, h, id }, physical pixels). Injected input aimed inside any registered region is blocked by the watchdog. Human input always passes, so the region is a guaranteed physical abort area the model cannot reach. Regions are append-only for the session lifetime; there is deliberately no way to remove or move one after start.

Start the session. start_debug_session spawns or attaches the watchdog, registers every region, and starts the heartbeat. The orchestrator begins monitoring the current foreground window as the debug target. Pass sandbox: 'desktop' to run injection on a private Win32 desktop (PostMessage-based, user's real mouse/keyboard untouched) instead of SendInput (which moves the real cursor). sandbox: 'rdp' is reserved but not implemented in v1.

The auto-debug loop. While the session is active, the orchestrator polls the target window for changes: title, rectangle, foreground status, and optionally a screenshot-signature diff. When a trigger fires, it captures a fresh screenshot and exposes it as the debug://context resource. The client (OpenCode) polls debug://context, decides what to do, and calls execute_action with that decision. The orchestrator never decides actions on its own; it only executes client decisions, and only after the governor, freshness, and safety gates all pass.

End the session. end_debug_session sends SHUTDOWN, kills the watchdog if it does not respond within one second, releases any held modifier keys, and returns to IDLE. If the MCP process dies without a clean shutdown, the watchdog's dead-man switch removes the hooks on its own (see the Security model section).

Tools

Ten tools are registered.

Tool

Purpose

read_file

Read a text file from an absolute path; binary files return base64.

list_directory

List the immediate entries of a directory.

capture_window

Capture a window by exact title as a PNG; empty title means the frontmost window.

mouse_click

Click at logical screen coordinates with a given button.

mouse_move

Move the cursor to logical screen coordinates.

key_press

Press a key, optionally holding modifiers.

type_text

Type a text string as keyboard input.

start_debug_session

Spawn or attach the watchdog and register protected abort regions. Accepts optional sandbox: 'desktop' for isolated PostMessage injection.

end_debug_session

End the active session and shut down the watchdog.

execute_action

Execute a client-decided action inside the active session.

inspect_element

Enumerate visible UI elements (name, role, rect, enabled) via UIAutomation tree walker.

The four input tools (mouse_click, mouse_move, key_press, type_text) all route through the safety layer's injectGuarded gate. Calling them with no active session returns NO_ACTIVE_SESSION. Calling them while the cursor or keyboard focus is outside the target window returns WINDOW_SCOPE_VIOLATION.

Resources

Three resources are registered.

URI

Content

screenshot://full

PNG capture of the primary monitor.

screenshot://monitor/{index}

PNG capture of a specific monitor by 0-based index.

debug://context

JSON snapshot of the auto-debug loop: status, target, trigger, screenshot, governor state.

Governor limits

The orchestrator enforces a fixed throttle on interventions:

  • 5 second cooldown between actions

  • 6 interventions per minute

  • auto-pause after 3 consecutive failures

  • hard 30-minute session cap, after which the session auto-ends

Rejections for cooldown, rate limit, or pause are throttling, not failures. Only a stale-state refusal or an injection error counts toward the 3-failure pause.

Security model

What this design guarantees, and what it does not.

Dual-process isolation. The Node MCP server and the native watchdog are separate processes. A stuck Node event loop cannot block the hooks or drop the safety layer, because the watchdog runs its own message loop.

Dead-man switch. The watchdog listens on a named pipe and treats any byte as a heartbeat. If no heartbeat arrives for more than 2 seconds, it calls UnhookWindowsHookEx on both hooks and exits cleanly. Combined with the removal grace period, hooks come down within 3 seconds of MCP death, so a crashed or killed server never leaves input blocked. This is the fail-safe contract; it is not a sub-second guarantee.

Window scoping. Every injection is refused unless a session is active and the cursor and keyboard focus are inside the session target window.

Secure-desktop handling. If the OS switches to the secure desktop (UAC prompt or lock screen), the orchestrator pauses and refuses injection with zero input attempted.

Append-only audit. Every file read, injected action, screenshot request, and intervention decision is logged to an append-only audit log. Keystroke content and file content are never written to it.

What it does NOT guarantee. Read this part carefully, because these are the honest residual risks.

  • Injected-input filtering is not absolute blocking. The watchdog blocks input carrying the LLKHF_INJECTED / LLMHF_INJECTED flags when the destination falls inside a protected region. That stops machine-injected input, which is what SendInput produces. It does not stop every possible input source. Another process could theoretically synthesize non-flagged input by other means, and that input would pass the filter. This tool does not claim absolute physical blocking. Treat the abort button as a strong, best-effort safety net, not a mathematical guarantee.

  • It is a remote-control primitive in the worst case. The full tool surface is file read plus screenshot capture plus keyboard and mouse injection. If an attacker or a misbehaving model controls it, that is the capability they get. Use it on a machine and against windows you are willing to have that surface pointed at.

  • Antivirus and EDR can flag it. Global low-level hooks and SendInput injection are exactly the techniques remote-access tools and keyloggers use. Expect false positives from AV/EDR products, including the watchdog being quarantined or killed mid-session. The dead-man switch makes that safe (hooks come down), but it will interrupt sessions. See Troubleshooting.

  • Elevation widens the surface. The watchdog needs admin to install global hooks, so a session runs with an elevated process in the picture. Do not run it on a machine where that exposure is unacceptable.

No keystroke or button content is ever read or logged by the watchdog; only the injected flag and the cursor destination are inspected. Transport is the local named pipe only. There is no TCP, no network listener, no remote control.

Troubleshooting

Antivirus or EDR flags the watchdog. Add an exclusion for src\watchdog\watchdog.exe (or the project directory) in your AV/EDR console. The durable fix is code signing: a signed binary is far less likely to be quarantined. If the watchdog gets killed mid-session, the session transitions to IDLE and all input tools are refused until a new start_debug_session.

Windows detaches the hook (LowLevelHooksTimeout). Low-level hook procedures have a hard execution budget, controlled by HKCU\Control Panel\Desktop\LowLevelHooksTimeout (default 300 ms). If the hook proc runs too long, Windows silently removes it. The watchdog keeps its hook proc well under 100 ms, so this should not trigger in normal use. If you see hooks dropping on a heavily loaded machine, the problem is system load or interference from another low-level hook, not this tool.

Clicks land at the wrong place on a multi-monitor or mixed-DPI setup. Coordinates are mapped between logical and physical pixels using per-monitor DPI. On mixed-DPI multi-monitor setups there is a known limitation: the logical to physical conversion passes logical coordinates to a call that expects physical pixels. It is harmless at 96 DPI but can drift on scaled monitors. If a click misses, capture a screenshot first, read the target coordinates from it, and prefer working on the primary monitor.

A UAC prompt appears, or injection silently fails. The watchdog runs elevated, so spawning it can surface a UAC prompt. If you cancel it, the session fails with ELEVATION_REQUIRED. The server cannot re-request elevation on its own in this build, so pre-start the watchdog as admin before starting the session, or launch OpenCode from an elevated terminal.

ERROR_ACCESS_DENIED when running the watchdog manually. This is the expected behavior for a non-elevated shell. The watchdog refuses to run without admin and prints ERROR_ACCESS_DENIED with exit code 1, so there is no silent no-op. Run it from an elevated PowerShell instead.

Session recording

Sessions can be recorded as JSON transcripts for later replay. The recorder hooks into the audit log and captures every tool call (name, args, result, timestamp) without keystroke content (data minimization). Transcripts are saved to .omo/recordings/session-<id>.json.

# A session transcript can be replayed programmatically:
node -e "const { SessionRecorder } = require('./dist/recording'); SessionRecorder.replay('.omo/recordings/session-xxx.json', async (call) => { console.log(call.toolName, call.args); })"

UIAutomation (accessibility API)

The inspect_element tool enumerates visible UI elements via the UIAutomation tree walker (competitor parity with terminator-mcp-agent and Windows MCP Inspector). In v1, this is a stub that returns elements from the injected deps seam; full COM interop requires a native N-API addon (future work). The UIAutomationProvider class implements InputProvider but throws UIAutomationError for injection methods in v1 — use SendInput or PostMessage paths for actual injection.

F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A standalone MCP server for Windows desktop control, enabling screenshots, mouse and keyboard input, app launch, window/display management, and clipboard access via natural language.
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that gives AI agents human-like control over Windows via visual perception and simulated mouse and keyboard input, enabling automation of any application without APIs.
    59
    2
    MIT

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wgm66/mcp-windows-debug'

If you have feedback or need assistance with the MCP directory API, please join our Discord server