Skip to main content
Glama

mcp-windows-debug

CI TypeScript License: MIT

这是一个 TypeScript/Node.js MCP 服务器,通过 stdio 接入 OpenCode,为模型在 Windows 机器上提供眼睛和双手:它可以读取项目文件、捕获截图、移动鼠标和敲击键盘,并针对目标应用程序运行自动调试循环。

安全性是整个设计的核心。一个独立的原生 C++ 看门狗进程会安装全局低级键盘和鼠标钩子,这样即使在模型注入输入时,人类也始终可以点击受保护的中止按钮。Node MCP 服务器和看门狗是两个独立的进程,因此卡住的 Node 事件循环无法冻结你的输入,也无法悄然让安全层失效。每个操作都要经过三道关卡:限流器、新鲜度检查和窗口范围守卫。详细信息见下文的安全模型一节。

这是一个仅支持 Windows 的 v1 版本。macOS 和 Linux 后端将在以后通过相同的 provider 接口接入;它们目前尚未实现。

快速开始

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

安装

先决条件:

  • Node.js 20 或更高版本,外加 npm

  • Windows 10 或 11

  • 管理员访问权限,仅在运行看门狗时需要(见下文)

安装依赖并构建 TypeScript:

npm install
npm run build

npm run build 运行 tsc 并生成 dist/index.js,这是 OpenCode 启动的入口点。

接下来,构建看门狗。它是一个用 MSVC 编译的 C++ Win32 控制台应用,不涉及 CMake、MSBuild 或 MinGW:

cd src\watchdog
build.bat

build.bat 需要 VS2019 Build Tools(MSVC 14.29)和 Windows SDK。工具链路径已硬编码在脚本中,因此它期望它们位于默认安装位置。输出是 src\watchdog\watchdog.exe,Node 服务器在运行时相对于项目根目录定位该文件。

看门狗必须以提升的权限运行。全局低级钩子拒绝从非提升进程中安装。有两种方式满足此要求:

  1. 从提升权限的终端启动 OpenCode,这样生成的看门狗会继承提升的权限。

  2. 在开始调试会话之前,自己以管理员身份预先启动看门狗。

在此构建版本中,服务器无法自行请求 UAC 提升。无法连接到一个已提升权限的看门狗的调试会话会失败并返回 ELEVATION_REQUIRED;而未提升权限的看门狗运行时会打印 ERROR_ACCESS_DENIED 并以退出码 1 退出,而不是默默地什么都不做。

OpenCode 配置

在 OpenCode 配置(opencode.json)的 mcp 键下添加一个 windows-debug 条目。注意键是 mcp,而不是 mcpServers:

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

将 <abs-path> 替换为此项目的绝对路径,使用正斜杠,这样 JSON 就不需要转义。例如,如果项目位于 G:\工程开发\AI全场景图形化调试,命令将变为:

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

command 是 argv 标记的数组。environment 映射默认为空;每次会话的看门狗令牌由服务器自己生成,并通过进程环境传递给看门狗,因此你无需在此设置任何内容。

用法

调试会话具有固定的流程:注册受保护的中止按钮,启动会话,让模型执行自动调试循环,然后结束会话。

注册中止按钮。 会话不能以零个受保护区域启动。将一个或多个屏幕矩形作为 regions({ x, y, w, h, id },物理像素)传递给 start_debug_session。目标是任何已注册区域内部的注入输入都会被看门狗阻止。人类输入始终通过,因此该区域是一个有保证的物理中止区域,模型无法触及。在会话生命周期内,区域只能追加;启动后刻意没有任何方法可以移除或移动某个区域。

启动会话。 start_debug_session 会生成或附加看门狗,注册每个区域,并启动心跳。编排器开始将当前前台窗口作为调试目标进行监控。传入 sandbox: 'desktop' 可以在私有 Win32 桌面上运行注入(基于 PostMessage,不会触碰用户真实的鼠标/键盘),而不是使用 SendInput(它会移动真实光标)。sandbox: 'rdp' 已预留,但尚未在 v1 中实现。

自动调试循环。 当会话处于活动状态时,编排器会轮询目标窗口以检测变化:标题、矩形、前台状态,以及可选的截图签名差异。当触发器触发时,它会捕获一张新的截图,并将其作为 debug://context 资源暴露出来。客户端(OpenCode)轮询 debug://context,决定要做什么,然后用该决定调用 execute_action。编排器从不自行决定操作;它只执行客户端的决定,并且只有在限流器、新鲜度检查和安全关卡全部通过之后才会执行。

结束会话。 end_debug_session 发送 SHUTDOWN,如果看门狗在一秒内没有响应则将其终止,释放所有按住的修饰键,然后返回 IDLE。如果 MCP 进程在没有干净关闭的情况下死亡,看门狗的死亡开关会自行移除钩子(参见安全模型一节)。

工具

已注册十个工具。

工具

用途

read_file

从绝对路径读取文本文件;二进制文件返回 base64。

list_directory

列出目录的直接子项。

capture_window

按精确标题将窗口捕获为 PNG;标题为空表示最前面的窗口。

mouse_click

在逻辑屏幕坐标处用指定按钮单击。

mouse_move

将光标移动到逻辑屏幕坐标。

key_press

按下一个键,可选地按住修饰键。

type_text

以键盘输入的形式键入文本字符串。

start_debug_session

生成或附加看门狗,并注册受保护的中止区域。接受可选的 sandbox: 'desktop' 以进行隔离的 PostMessage 注入。

end_debug_session

结束活动会话并关闭看门狗。

execute_action

在活动会话内执行由客户端决定的操作。

inspect_element

通过 UIAutomation 树遍历器枚举可见的 UI 元素(名称、角色、矩形、启用状态)。

四个输入工具(mouse_click、mouse_move、key_press、type_text)都经过安全层的 injectGuarded 关卡。在无活动会话时调用它们会返回 NO_ACTIVE_SESSION。在光标或键盘焦点位于目标窗口之外时调用它们会返回 WINDOW_SCOPE_VIOLATION。

资源

已注册三个资源。

URI

内容

screenshot://full

主显示器的 PNG 截图。

screenshot://monitor/{index}

按从 0 开始的索引获取指定显示器的 PNG 截图。

debug://context

自动调试循环的 JSON 快照:状态、目标、触发条件、截图、限流器状态。

限流器限制

编排器对干预实施固定的限流:

  • 两次操作之间 5 秒冷却

  • 每分钟 6 次干预

  • 连续 3 次失败后自动暂停

  • 30 分钟的硬性会话上限,超过后会话自动结束

因冷却、速率限制或暂停而拒绝属于限流,不是失败。只有状态过期的拒绝或注入错误会计入 3 次失败暂停。

安全模型

该设计保证什么,不保证什么。

双进程隔离。 Node MCP 服务器和原生看门狗是独立的进程。卡住的 Node 事件循环无法阻塞钩子,也无法让安全层失效,因为看门狗运行自己的消息循环。

死亡开关。 看门狗监听一个命名管道,并将任何字节视为心跳。如果超过 2 秒没有心跳到达,它会对两个钩子调用 UnhookWindowsHookEx 并干净地退出。再加上移除的宽限期,钩子会在 MCP 死亡后的 3 秒内被拆除,因此崩溃或被终止的服务器绝不会让输入一直处于被阻塞状态。这是故障安全约定;它不是亚秒级保证。

窗口范围限定。 除非会话处于活动状态,并且光标和键盘焦点位于会话目标窗口内,否则每次注入都会被拒绝。

安全桌面处理。 如果操作系统切换到安全桌面(UAC 提示或锁屏),编排器会暂停并拒绝注入,且不会尝试任何输入。

仅追加审计。 每次文件读取、注入操作、截图请求和干预决策都会记录到仅追加的审计日志中。按键内容和文件内容永远不会被写入其中。

它不保证什么。 请仔细阅读这一部分,因为这些是如实的残余风险。

  • 注入输入过滤不是绝对拦截。 当目标位置落在受保护区域内时,看门狗会阻止携带 LLKHF_INJECTED / LLMHF_INJECTED 标志的输入。这能阻止机器注入的输入,也就是 SendInput 产生的输入。它不能阻止所有可能的输入来源。理论上,另一个进程可以通过其他方式合成不带标志的输入,而这种输入会通过过滤器。此工具不声称具有绝对的物理拦截能力。请将中止按钮视为一个强有力的、尽力而为的安全网,而不是数学上的保证。

  • 在最坏情况下,它是一个远程控制原语。 完整的工具面包括文件读取、截图捕获以及键盘和鼠标注入。如果攻击者或行为异常的模型控制了它,这就是他们获得的能力。请只在你愿意让该工具面对准的机器和窗口上使用它。

  • 杀毒软件和 EDR 可能会标记它。 全局低级钩子和 SendInput 注入正是远程访问工具和键盘记录器所使用的技术。预计 AV/EDR 产品会产生误报,包括看门狗在会话中途被隔离或终止。死亡开关能保证这种场景下的安全(钩子会被拆除),但这会中断会话。参见故障排查。

  • 提权会扩大暴露面。 看门狗需要管理员权限才能安装全局钩子,因此会话运行时会有提升权限的进程参与其中。不要在不接受这种暴露的机器上运行它。

看门狗从不读取或记录任何按键或按钮内容;它只检查注入标志和光标目的地。传输仅使用本地命名管道。没有 TCP,没有网络监听,没有远程控制。

故障排查

防病毒或EDR标记看门狗。 在您的防病毒/EDR控制台中为 src\watchdog\watchdog.exe(或项目目录)添加排除项。 持久的修复方案是代码签名:签名后的二进制文件被隔离的可能性要小得多。 如果看门狗在会话中途被终止,会话将转换为 IDLE,并且所有输入工具都会被拒绝,直到新的 start_debug_session。

Windows 分离钩子(LowLevelHooksTimeout)。 低级钩子 过程有严格的执行预算,由 HKCU\Control Panel\Desktop\LowLevelHooksTimeout(默认 300 毫秒)控制。如果钩子 过程运行时间过长,Windows 会静默移除它。看门狗将其钩子 过程保持在远低于 100 毫秒,因此在正常使用中不应触发此问题。如果您看到 在负载较高的机器上钩子被丢弃,问题在于系统负载或 另一个低级钩子的干扰,而不是此工具。

在多显示器或混合 DPI 设置下,点击落在错误的位置。 坐标使用每显示器 DPI 在逻辑像素和物理像素之间映射。在混合 DPI 多显示器设置下存在一个已知限制:逻辑 到物理的转换将逻辑坐标传递给一个期望 物理像素的调用。在 96 DPI 下这是无害的,但在缩放显示器上可能会漂移。如果 点击未命中,请先截取屏幕截图,从中读取目标坐标, 并优先在主显示器上工作。

出现 UAC 提示,或注入静默失败。 看门狗以 提升权限运行,因此生成它可能会弹出 UAC 提示。如果您取消它,会话 将以 ELEVATION_REQUIRED 失败。服务器无法在此版本中自行重新请求提升权限, 因此在启动会话之前,请以管理员身份预先启动看门狗, 或从提升的终端启动 OpenCode。

手动运行看门狗时出现 ERROR_ACCESS_DENIED。 这是 非提升 shell 的预期行为。看门狗拒绝在没有 管理员权限的情况下运行,并打印 ERROR_ACCESS_DENIED 且退出代码为 1,因此不会 静默无操作。请改为从提升的 PowerShell 运行它。

会话录制

会话可以录制为 JSON 转录以供后续回放。录制器 挂接到审计日志并捕获每个工具调用(名称、参数、结果、 时间戳),而不包含按键内容(数据最小化)。转录 保存到 .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(辅助功能 API)

inspect_element 工具通过 UIAutomation 树遍历器枚举可见的 UI 元素(与 terminator-mcp-agent 和 Windows MCP Inspector 的竞争对手功能对等)。在 v1 中,这是一个从注入的 依赖接缝返回元素的存根;完整的 COM 互操作需要原生 N-API 插件(未来 工作)。UIAutomationProvider 类实现了 InputProvider,但在 v1 中 对注入方法抛出 UIAutomationError —— 使用 SendInput 或 PostMessage 路径进行实际注入。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    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.
    3
    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.
    19 npm
    3
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A local, dependency-free MCP server that gives AI agents controlled access to the active Windows desktop, enabling automated interaction with applications through screenshots, clicks, typing, and window management.
    75 npm
    MIT