dsh-windows-mcp
Verifieddsh-windows-mcp · v0.1.0 · MIT · Web UI
Windows desktop automation for DeepSeek Harness — plugs CursorTouch/Windows-MCP (screenshot, UI automation, input, clipboard, processes, registry) into DSH through the official MCP client bridge.
Install
dsh plugin add dsh-windows-mcp Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Creators
Readme
dsh-windows-mcp
给 DeepSeek Harness 接上 Windows 桌面自动化 —— 让 DSH 的 agent 能"看见"你的屏幕并操作你的电脑。
本插件把 CursorTouch/Windows-MCP 接到 DSH 上,做法是挂载 DSH 本体自带的那座 MCP 客户端桥:不重新实现协议客户端,也不重复打包 MCP SDK。插件本身是一个 carrier bundle(只有补丁、没有自己的服务),agent 能用的一切能力都来自官方那座桥。
DSH agent
└─ 工具调用 mcp__windows__Screenshot
└─ @deepseek-ai/dsh-mcp-client (DSH 内置,由本插件的补丁行挂载)
└─ uvx [email protected] serve (stdio 子进程)
└─ 你的桌面:UIA 树 / Win32 输入 / 屏幕采集
agent 能拿到什么
装好插件且 Windows-MCP 可启动后,工具列表里会出现:
| 工具 | 作用 |
|---|---|
mcp__windows__Screenshot |
截屏;图片会作为真正的图片附件进入对话 |
mcp__windows__Snapshot |
抓取无障碍树(纯文本,不花图片 token) |
mcp__windows__DisplayInventory |
枚举显示器及其几何信息 |
mcp__windows__Click / Move / Scroll |
鼠标输入 |
mcp__windows__Type / Shortcut |
键盘输入 |
mcp__windows__Wait / WaitFor |
等待固定时长,或等到某个界面条件成立 |
mcp__windows__Scrape |
从窗口里抽取文本 |
mcp__windows__MultiSelect / MultiEdit |
批量选中元素 / 批量编辑 |
mcp__windows__Clipboard |
读写剪贴板 |
mcp__windows__Process |
枚举、启动、结束进程 |
mcp__windows__Notification |
读取通知 |
mcp__windows__Registry |
读写注册表 |
mcp__windows__ControlStatus |
控制环状态。无法关闭——上游强制保留 |
mcp__windows__App |
启动/切换应用。默认排除(上游只在英文版 Windows 上稳定支持) |
mcp__windows__PowerShell / FileSystem |
默认排除——DSH 已有 shell 与文件工具 |
另外本插件自带一个工具 windows_mcp_doctor:当 mcp__windows__* 工具缺失时,用它查原因。
输入框工具行里还会多出一颗 Computer Use 胶囊(就在"访问模式"旁边):显示当前真正注册了几个桌面工具,并在重启后记住你的选择(状态文件:~/.dsh/dsh-windows-mcp.state.json)。它默认是关闭的——全新安装不会把桌面交给 agent,直到你亲手点亮这颗胶囊。
关掉它是一道硬约束,不是提示:桥本身照常运行,但从下一步开始,每个 mcp__windows__* 工具都会从模型的工具表里消失;模型即便仍然报得出名字,调用也会在分发时被拒绝——对所有会话和子智能体同时生效,无需重启。重新打开后立即恢复;windows_mcp_doctor 始终报告当前开关状态。
已实测:Windows 11 + DSH 桌面版 0.2.0-rc.2 下,桥那侧的服务公布 18 个工具 (上游 21 个减去这里排除的 3 个),启动后约 1.5 秒就绪;每个工具都以
mcp__windows__<工具名>出现在模型的工具表里。
前置条件
- Windows 10/11。
- DeepSeek Harness 桌面版,且内置
@deepseek-ai/dsh-mcp-client桥(0.2.0-rc.2 及以上)。 - 运行 DSH 的那个进程能在他自己的
PATH上找到 uv(uvx靠它拉起 Windows-MCP)。即使没在PATH上,插件也会额外搜索%USERPROFILE%\.local\bin。 - 想让 agent 真正看到截图,需要支持图片输入的模型。
首次启动 vs 之后每次启动
uvx 第一次运行时会为 windows-mcp 建一个隔离环境,所以首次启动要下载几十 MB 的
Python 依赖,慢网下可能要好几分钟;桥每次启动只等大约一分钟然后重试,因此冷启动可能要
试几次工具才会出现。
依赖装好之后服务本身很快 —— 本机实测(Windows 11)约 1.5 秒就绪。想从第一次 DSH 启动就这么快,先手动装一次:
uv tool install windows-mcp # 没有时间限制,跑一次即可
然后把该行的 command 指向装好的命令(command: windows-mcp),写法见
从自己的 profile 覆盖这一行——config 要整块重写,
补丁是替换不是深合并。之后每次启动都会复用 uv 建好的环境。
安装
- 打开 DSH 桌面版 → 设置 → 插件。
- 添加本 bundle,目标可以是包名、仓库地址(
github:helloHub1212/dsh-windows-mcp)或本仓库的本地目录。 - 重启 DSH,让新的补丁层在启动时合成。
非 Electron 的 profile 也可以用 CLI 完成同样的事:
dsh plugin --profile <profile> add github:helloHub1212/dsh-windows-mcp
Electron 独占
desktopprofile,CLI 对它任何命令都会被拒绝(连只读 dump 也不行)。desktop请走图形界面。
在应用里直接装依赖
Windows-MCP 本身是个 Python 程序,所以 设置 → 插件 → dsh-windows-mcp 这一页现在会显示依赖状态并直接帮你装:
- 依赖 ——
已安装 0.8.8/ 未安装 / 未找到 uv; - 下载并安装 —— 跑一次
uv tool install windows-mcp@<锁定版本>,安装输出实时显示在页面上,过程中可以取消; - 装完之后,插件会自己把桥那一行写进你 profile 的
cordis.patch.yml(先做带时间戳的备份,并用成对标记包住,可重复执行)——这样桥启动的是装好的可执行文件,而不是拿uvx去赌冷缓存。重启 DSH 生效。
它写进去的就是 换成固定的解释器 里那条行;把标记之间的块删掉就回到 uvx。启用 bundle 之后弹的提示用的是同一个面板。
面板上还会显示 写入目标:手动写入会落到哪个 cordis.patch.yml,也就是这个宿主启动的那个 profile(dsh --profile web 启动的 web 宿主同样适用)。如果本插件装在多个 profile 里、而宿主没有报告自己启动的是哪一个,插件不会猜:它什么都不写并直接说明——给运行 DSH 的进程设 DSH_WINDOWS_MCP_PROFILE=<profile 名>(或 profile 的绝对路径)再重试。
验证
windows_mcp_doctor
它会打印解析到的 uv/uvx/python、%USERPROFILE%\.windows-mcp 的状态、实际生效的 bridge 行,以及真正注册成功的 mcp__windows__* 工具名。然后对 agent 说:
截图我的桌面,告诉我屏幕上有什么。
配置
默认值都在 cordis.patch.yml,下面这些通过 windows-mcp-bridge 那一行的 env 调整。
| 变量 | 本插件默认 | 作用 |
|---|---|---|
WINDOWS_MCP_SCREENSHOT_SCALE |
0.75 |
截图缩放,0.1–1.0。对图片 token 开销影响最大的一个开关。 |
WINDOWS_MCP_DISABLE_FLASH |
1 |
关掉上游每次截屏时那圈橙色"控制权已接管"边框。 |
WINDOWS_MCP_SCREENSHOT_BACKEND |
auto |
采集后端;覆盖前请先读上游文档。 |
WINDOWS_MCP_MAX_TREE_ELEMENTS |
500 |
Snapshot 返回的无障碍树元素上限。 |
WINDOWS_MCP_WATCHDOG |
off |
上游看门狗。默认关,因为它的 UIA 事件泵有可能把整个进程带崩(上游 #332)。 |
ANONYMIZED_TELEMETRY |
false |
上游默认开启(PostHog)。本插件关掉。 |
从自己的 profile 覆盖这一行
不要改插件自己的文件——在你 profile 的 $DSH_HOME/profiles/<profile>/cordis.patch.yml 里按 id 覆盖即可,它在 bundle 行之后合成,因此优先级更高。
补丁是整块替换 config,不是深合并。 loader 的应用方式是 target[key] = value(dsh-app-boot 里的 applyEntryPatches),漏写哪个键就等于删掉哪个键:serverName 必填(它决定所有工具名)、transport 必填、stdio 形态下 command 必填、streamable-http 形态下 url 必填。id 不存在、或 name 与目标不匹配的补丁会被跳过并告警,而不是报错。
# $DSH_HOME/profiles/<profile>/cordis.patch.yml —— 完整的一行
- id: windows-mcp-bridge
config:
serverName: windows
transport: stdio
command: uvx
args: [[email protected], serve, --exclude-tools, "App,PowerShell,FileSystem"]
toolCallTimeoutMs: 120000
failOnStartupError: false
reconnect: { enabled: true, initialDelayMs: 500, maxDelayMs: 30000, maxAttempts: 10 }
env:
ANONYMIZED_TELEMETRY: "false"
WINDOWS_MCP_DISABLE_FLASH: "1"
WINDOWS_MCP_SCREENSHOT_SCALE: "0.5"
--exclude-tools 的工具名是一个逗号分隔的参数("App,PowerShell,FileSystem"),而 ControlStatus 始终保留——上游没有提供排除它的方式。
换成固定的解释器(不用 uvx)
uvx 每次启动都会重新解析包。要可复现,就装一次(uv tool install windows-mcp)或用任何一个已经装了它的 Python,然后改上面那份完整 config 里的 command/args:
- id: windows-mcp-bridge
config:
serverName: windows
transport: stdio
command: windows-mcp # 或者 C:\...\python.exe + args: [-m, windows_mcp, serve, ...]
args: [serve, --exclude-tools, "App,PowerShell,FileSystem"]
toolCallTimeoutMs: 120000
failOnStartupError: false
reconnect: { enabled: true, initialDelayMs: 500, maxDelayMs: 30000, maxAttempts: 10 }
env: { ANONYMIZED_TELEMETRY: "false", WINDOWS_MCP_DISABLE_FLASH: "1", WINDOWS_MCP_SCREENSHOT_SCALE: "0.75" }
换成常驻 HTTP 服务
Windows-MCP 也能作为后台服务运行。上游的 windows-mcp install 会注册一个 ONLOGON 计划任务,在 127.0.0.1:8000 上提供 streamable-http;把这一行改成对应形态即可——这个形态用 url,没有 command/args/env:
- id: windows-mcp-bridge
config:
serverName: windows
transport: streamable-http
url: http://127.0.0.1:8000/mcp/ # 上游打印的就是这个地址,结尾斜杠属于上游
toolCallTimeoutMs: 120000
failOnStartupError: false
reconnect: { enabled: true, initialDelayMs: 500, maxDelayMs: 30000, maxAttempts: 10 }
这个形态没有 env 字段,所以遥测与截屏闪框的默认值不再生效:想要同样效果,就在启动服务时自己带上 ANONYMIZED_TELEMETRY=false 和 WINDOWS_MCP_DISABLE_FLASH=1。
好处是跨 DSH 重启存活、省掉每次启动开销,代价是有一个比应用活得更久的进程。两个需要留意的上游限制:install 会把计划任务绑到当时使用的解释器上(从临时 uvx 环境安装会注册出一个指向 uv 缓存目录、可能被回收的任务——请改用 uv tool install windows-mcp 或固定 venv);非 loopback 地址在缺少 --auth-key/--oauth-client-id 时会拒绝启动(除非显式 --allow-insecure-remote)。
排障
| 现象 | 原因与处理 |
|---|---|
完全没有 mcp__windows__* 工具 |
跑 windows_mcp_doctor。要么 DSH 进程的 PATH 里没有 uvx,要么首次冷下载还没结束。查 DSH 宿主日志里的 mcp-client(windows) 行。 |
| 升级后工具消失了 | 工具名是 mcp__<serverName>__<tool>。改 serverName 会改掉全部工具名(并打破 prompt 缓存前缀)。 |
| 截图返回的是文本 | 当前模型不接受图片输入,或你的 harness 配置里关掉了附件。上游的图片只有在准入成功时才会被投影。 |
App 工具报错或没反应 |
上游明确说它只在英文版 Windows 上可靠;本插件默认已排除。 |
| DSH 启动明显变慢 | 桥会在启动时拉起 Windows-MCP(而且先起一个一次性的探测进程)。可以把该行设 enabled: false;failOnStartupError: false 保证 DSH 其余部分不受影响。 |
| 截图里的字看不清 | 把 WINDOWS_MCP_SCREENSHOT_SCALE 提到接近 1.0;上游截图上限是 1920×1080。 |
安全
装上它,等于把鼠标、键盘、剪贴板、进程和注册表交给模型。请按"交出这个桌面会话的控制权"来评估。
设计上做了与没做的事:
- 默认不监听网络。 默认行走 stdio:管道连接的子进程,不是监听端口。
- 子进程环境会清密。 桥启动 MCP 子进程时会先做环境清洗:名字匹配
KEY|PASSWORD|SECRET|TOKEN的变量、以及所有DSH_*变量都会被删掉,然后才合并配置里的env。所以凭据必须显式写进该行的env,不能指望继承。 - 本插件不发送遥测。 上游自己的 PostHog 上报已在默认配置里显式关闭。
- 远程提供不是隐藏默认值。 若你切到 HTTP,上游会强制 loopback 主机过滤,非 loopback 且无鉴权时拒绝启动。
- 本插件自己的路由没有鉴权。
/dsh-windows-mcp/state、/prepare、/prepare/cancel、/bridge由和 UI 同一个 web 服务器提供,自身不做 token 校验。所以装了本插件的 DSH web 宿主不要用非 loopback 的--host暴露:能访问到它的人可以触发安装、或改写某个 profile 的补丁层。
原理
DSH 插件本质是 loader 补丁,而补丁行可以挂载位于 Electron app.asar 里的包——loader 会从桌面版安装锚点解析官方 @deepseek-ai/* 名字。第三方代码不能 import 这些包,但可以在补丁里点名它们,因为挂载发生在 loader 内部,而不是插件代码内部。这就是本包的全部诀窍:
- insert:
- id: windows-mcp-plugin
name: dsh-windows-mcp # lib/index.js:doctor 工具 + 启动审计
- id: windows-mcp-bridge
name: "@deepseek-ai/dsh-mcp-client" # 内置桥,按 Windows-MCP 配置
config: { transport: stdio, command: uvx, args: [[email protected], serve, ...] }
由此带来的几点值得知道:
- 集成的版本敏感性只有一个方向:bridge 的配置 schema 属于 DSH,不属于本插件。
package.json声明补丁,怎么读由 DSH 决定。 - 图片投影是桥的功能:MCP 图片块会被存成 DSH 附件并以原生图片内容呈现;音频与嵌入资源会退化成诊断文本。
- MCP prompts 不被桥支持(资源可以按需读取)。
开发
npm install
npm test # node --test,包含对补丁文件的真实 YAML 解析
npm run check # node --check lib/index.js
想在不碰任何真实 profile、也不重启 DSH 的前提下看到合成后的配置,用 dump 工具:
# 一次性:建一个影子 profile,复用真实 profile 的 node_modules
mkdir $env:USERPROFILE\.dsh\profiles\dtest
copy $env:USERPROFILE\.dsh\profiles\desktop\package.json $env:USERPROFILE\.dsh\profiles\dtest\
cmd /c mklink /J $env:USERPROFILE\.dsh\profiles\dtest\node_modules $env:USERPROFILE\.dsh\profiles\desktop\node_modules
npm run dump
目录结构:
cordis.patch.yml 集成本体:两行 insert
lib/index.js 宿主半边:windows_mcp_doctor + 启动审计(零依赖)
test/plugin.test.mjs 补丁合成测试 + 恶意 ctx 测试
scripts/dump-config.mjs 面向影子 profile 的合成调试脚本
tools/ 零依赖调试探针(不发布到 npm)
欢迎贡献;请保持 lib/index.js 无运行时依赖,并保持 apply() 永不抛错。
致谢与许可
MIT —— 见 LICENSE。
- 真正干活的是 CursorTouch/Windows-MCP(MIT),本插件只负责接线。
- MCP 客户端桥属于 DeepSeek Harness,本仓库不重新分发它。
- 与 DeepSeek 官方及 Windows-MCP 作者均无隶属关系。