mcpField
D
desktop-mcp

desktop-mcp

本地服务
github.com/jaimenbell生产力011 周前更新

关于 desktop-mcp

desktop-mcp 是用于观察和控制本地桌面的 Windows 专用 MCP 服务。各工具组分别受配置控制,鼠标和键盘输入默认关闭。

主要功能

  1. 01将屏幕截图保存为 PNG 文件
  2. 02列出并检查窗口
  3. 03聚焦、调整大小、最小化和还原窗口
  4. 04发送鼠标和键盘输入
  5. 05使用 ffmpeg 录制屏幕

适用场景

  1. 01检查桌面上可见的窗口
  2. 02为桌面任务排列窗口
  3. 03在明确启用后自动执行鼠标和键盘操作
  4. 04录制屏幕

MCP 相关

该服务通过本地 stdio MCP 主机提供桌面观察、窗口管理、输入和录屏工具。窗口、输入和录屏工具组需通过环境变量显式启用;输入默认关闭。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"jaimenbell-desktop": {
"command": "uvx",
"args": [
"desktop-mcp"
]
}
}
}
启动命令uvx desktop-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypidesktop-mcp0.1.1

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

desktop-mcp

PyPI MCP Registry License: MIT tests CI

用于控制 Windows 桌面的 MCP 服务:支持截图、窗口管理、鼠标/键盘输入和 ffmpeg 屏幕录制,并通过配置按工具组启用(默认关闭 input)——按照与 mcp-factory 和 rag-mcp 相同的标准打造:独立的 pyproject、fastmcp 服务、内容可靠的 README,以及完整的测试套件。

快速入门

pip install desktop-mcp
// ~/.claude.json (or any MCP-host stdio client config)
{
  "mcpServers": {
    "desktop-mcp": {
      "command": "desktop-mcp"
      // or: "command": "python", "args": ["-m", "desktop_mcp"]
    }
  }
}

window/input/record 工具组由环境变量控制——除非你明确启用,否则 input 会保持关闭。完整列表请参阅下方的环境变量。

工具组

组工具默认状态
observescreenshot、list_windows、get_active_window、window_info始终开启
windowfocus_window、move_resize_window、minimize_window、restore_window由环境变量控制;除非设置 DESKTOP_MCP_ENABLE_WINDOW=1,否则关闭
inputmouse_move、mouse_click、mouse_drag、mouse_scroll、key_press、hotkey、type_text由环境变量控制,默认关闭——需要设置 DESKTOP_MCP_ENABLE_INPUT=1
recordrecord_start、record_status、record_stop由环境变量控制;除非设置 DESKTOP_MCP_ENABLE_RECORD=1,否则关闭

已禁用的工具组会返回结构化的 policy_refusal 错误(不会静默地不执行任何操作,也不会崩溃)。输入操作还受到频率限制(默认每分钟 60 次,可通过 DESKTOP_MCP_RATE_LIMIT_PER_MIN 调整)——超过上限会返回结构化的 rate_limited 错误。

这是纵深防御:运行框架级别的权限提示是第一道关卡,但除非服务自身的环境变量明确启用相应功能,否则服务会拒绝输入、窗口和录制操作。因此,即使运行框架配置错误或权限过宽,也无法启用操作人员未选择为此进程开启的功能。

安全

注册 desktop-mcp 前请阅读此部分。这是一个桌面控制服务;它可能对你的机器造成的影响已在此明确列出,以便你做出知情决定。坦诚说明影响范围正是本节的目的。

  • observe 组(screenshot、窗口枚举)始终启用,且无法禁用。 任何能够访问此服务的调用方都可以捕获机器上任意可见窗口的内容,包括密码管理器、身份验证器/双重身份验证应用、助记词、银行页面或私人消息。screenshot 返回的是写入临时目录的 PNG 文件路径(默认路径为 %TEMP%\desktop-mcp-scratch),而不是内嵌像素数据,因此捕获的屏幕内容也会持续保存在磁盘上,直到该目录被清空。请将临时目录视为敏感内容,并且只在你信任的机器和运行环境中运行此服务。
  • DESKTOP_MCP_ENABLE_INPUT=1 会授予向当前焦点窗口注入按键和鼠标操作的权限——这相当于远程代码执行。 启用 input 组后,调用方可以在当前获得焦点的窗口(终端、浏览器或管理工具)中输入命令、按下快捷键并操控鼠标。出于这个原因,默认情况下此功能处于关闭状态;只有在你明白这等于把键盘交给调用方时才启用。禁用时,每个输入工具都会返回结构化的 policy_refusal(绝不会静默执行操作)。
  • 最小权限: 除非具体任务需要,否则请保持 input、window 和 record 组关闭;将此服务部署在可信主机上;除非你已接受启用的 input 组可以操控高权限窗口,否则不要以提升的权限(管理员身份)运行它。

上述环境变量门控、默认关闭的 input 组、结构化拒绝和速率上限均为强制执行的控制措施;本节直言不讳地说明了按设计仍可访问的内容。

能力说明表

以下每项声明均对应实现该功能的文件及验证它的测试——每项能力都有对应的实现和测试作为依据。

声明实现验证方式
将屏幕截图(显示器/区域/窗口)保存为 PNGdesktop_mcp/groups/observe.py::screenshottests/test_observe.py::TestScreenshot,实时测试:tests/test_live_smoke.py::test_live_screenshot_real_png
枚举窗口/获取活动窗口/按标题查找窗口desktop_mcp/groups/observe.pytests/test_observe.py::TestListWindows、TestGetActiveWindow、TestWindowInfo
聚焦/移动并调整窗口大小/最小化/还原窗口desktop_mcp/groups/window.pytests/test_window.py
鼠标移动/点击/拖动/滚动、按键/快捷键、输入文本desktop_mcp/groups/input_tools.pytests/test_input.py(仅模拟 pyautogui——参见「限制」)
通过 ffmpeg gdigrab 录制屏幕,设定时长硬上限,并支持正常停止desktop_mcp/groups/record.pytests/test_record.py,实时测试:tests/test_live_smoke.py::test_live_record_real_mp4
输入组默认关闭,禁用时会结构化拒绝请求desktop_mcp/config.py::group_enabled、gatedtests/test_config.py::TestGroupEnabled、tests/test_input.py::TestGateDisabledByDefault
限制输入操作速率(默认每分钟 60 次)desktop_mcp/config.py::TokenBucket、RateLimiterRegistrytests/test_config.py::TestTokenBucket、tests/test_input.py::TestRateLimit
DPI 感知初始化(per-monitor-v2),确保缩放显示器上的 mss/pyautogui 坐标一致desktop_mcp/config.py::ensure_dpi_awarenesstests/test_config.py::TestDpiAwareness(仅验证幂等性;不会自动测试视觉坐标是否一致——参见「限制」)
执行任何鼠标操作前,先根据虚拟桌面边界验证坐标desktop_mcp/groups/input_tools.py::_validate_pointtests/test_input.py(越界情况)
孤儿保护:启动新录制器前,先终止崩溃进程遗留的过期录制器desktop_mcp/groups/record.py::_orphan_guardtests/test_record.py::TestRecordStart::test_orphan_guard_kills_stale_recorder

限制(使用前请阅读)

  • UIPI(用户界面特权隔离)——保护窗口句柄,而非输入。中等完整性级别的进程(本服务,除非你提升其权限)无法操作由更高完整性级别(已提升权限/管理员)进程拥有的窗口:focus_window、move_resize_window、minimize_window 和 restore_window 会通过 pygetwindow 的窗口句柄 API(desktop_mcp/groups/window.py)执行,Windows 会在 UIPI 下阻止这些操作,本服务会将其报告为结构化的 window_action_failed 错误,并指出 UIPI,不会静默地什么也不做。 键盘/鼠标输入工具也受 UIPI 限制——而且更糟的是,它们会静默失败。type_text、hotkey、key_press 和鼠标操作(desktop_mcp/groups/input_tools.py)通过 pyautogui 执行,其 Windows 后端实际调用的是旧版 keybd_event/mouse_event Win32 函数(而非 SendInput——pyautogui 曾尝试使用 SendInput,后来又恢复为较旧的调用;参见已安装软件包中的 _pyautogui_win.py)。根据 Microsoft 自己的文档,UIPI 通常适用于合成输入:“[应用程序] 仅允许向完整性级别相同或更低的应用程序注入输入”(MSDN SendInput 参考文档);关键在于,“GetLastError 和返回值都不会表明失败是由 UIPI 阻止造成的。”keybd_event/mouse_event 是无返回值的旧版调用,完全没有失败信号,因此 pyautogui(以及本服务)在原理上都无法检测到拦截:如果焦点位于已提升权限的窗口,这些工具会报告 {"ok": true},但 Windows 会静默丢弃注入的按键/点击——没有异常,没有错误字段,目标也收不到任何输入。这比上面的窗口句柄路径更糟,后者至少会引发结构化的 window_action_failed 错误并指出 UIPI。不存在代码层面的绕过方法,也没有其他解决办法;只有提升本服务的权限(或完全不启用输入组),而本项目不会这样做,也不建议这样做。操作人员应将任何可能获得焦点的已提升权限应用视为本服务输入工具无法触及且不会发出提示,而不是认为存在能让输入通过的漏洞。 可能的未来增强(尚未实现):注入输入前检测前台窗口的完整性级别,并返回结构化拒绝,而不是错误地返回 {"ok": true}——这是跟踪中的 v2 构想,并非当前功能。
  • **DPI 缩放。**本服务会在启动时设置每显示器 v2 DPI 感知,因此在经过缩放的显示器上,mss 像素坐标和 pyautogui 点坐标应当一致。此引导逻辑只经过了幂等性/不崩溃的单元测试——尚未通过自动化测试验证其在实际多 DPI、多显示器环境中的坐标一致性;如果你的目标显示器缩放比例不是 100%,应进行抽查。
  • **UAC 安全桌面。**当 Windows 切换到安全桌面时(UAC 权限提升提示、Ctrl+Alt+Del、锁屏界面),在普通桌面上运行的进程——包括本服务——都无法查看或与其交互。截图会显示切换前普通桌面上的内容;输入调用则完全无法到达安全桌面。
  • **仅限单台计算机和本地使用。**没有网络传输,也不支持远程控制。仅通过 stdio,由同一台计算机上的 MCP 主机启动。
  • **本仓库自身注册时默认关闭输入组。**请参阅 ~/.claude.json 中的 desktop-mcp 条目——其中未设置 DESKTOP_MCP_ENABLE_INPUT。是否启用是操作人员针对每次注册做出的主动选择,并非代码变更。
  • pyautogui 安全保护。FAILSAFE=True 是有意设置的:操作过程中若将光标猛地移到屏幕角落,pyautogui 会引发异常并中止调用。这可能会中断正在执行的 mouse_drag。这被视为可接受的 v1 行为(参见计划中的开放问题)——这是刻意设计的人为紧急停止机制,并非错误。
  • **无 OCR/视觉分析。**截图为原始 PNG;解读其内容是使用方的工作,而非本服务的工作。
  • **无剪贴板工具。**因涉及凭据相关操作,此功能推迟到 v2,并将采用独立的安全设计。
  • **未注册到 mcp-factory hub。**本项目作为独立仓库发布(自带 pyproject,使用自有的免虚拟环境、系统级 Python 3.12 安装方式),与 rag-mcp 模式一致。Hub/注册表集成是 v2 候选功能。

环境变量

变量作用默认值
DESKTOP_MCP_ENABLE_WINDOW启用 window 工具组未设置(关闭)
DESKTOP_MCP_ENABLE_INPUT启用 input 工具组未设置(关闭)
DESKTOP_MCP_ENABLE_RECORD启用 record 工具组未设置(关闭)
DESKTOP_MCP_RATE_LIMIT_PER_MINinput 组的速率上限60
DESKTOP_MCP_SCRATCH_DIR截图/录制文件/pid 文件的写入位置%TEMP%\desktop-mcp-scratch
DESKTOP_MCP_LIVE设为 1 以运行真实硬件冒烟测试(参见“测试”)未设置(跳过)

使用示例

// A tool call from the MCP host, illustrative -- not a shell command.
{"tool": "screenshot", "arguments": {"monitor": 0}}
// -> {"ok": true, "path": "C:\\Users\\...\\Temp\\desktop-mcp-scratch\\screenshot-....png", "w": 3840, "h": 1080, "monitor": 0}

{"tool": "record_start", "arguments": {"fps": 30, "max_duration_s": 30}}
// -> {"ok": true, "path": "...\\recording-....mp4", "pid": 12345, "fps": 30, "max_duration_s": 30}
{"tool": "record_stop", "arguments": {}}
// -> {"ok": true, "path": "...\\recording-....mp4", "bytes": 800560, "duration_s": 3.13}

// input group disabled (default):
{"tool": "mouse_click", "arguments": {"x": 500, "y": 500}}
// -> {"ok": false, "error": {"type": "policy_refusal", "group": "input", "required_env": "DESKTOP_MCP_ENABLE_INPUT", ...}}

测试

CI(.github/workflows/ci.yml)会在每次推送/PR 时运行此测试套件(使用 windows-latest,因为 pywin32/PyGetWindow 是仅适用于 Windows 的依赖项, 无法安装在 Linux 运行器上),并在上方的 Tests 徽章与测试套件实际报告的结果 不一致时使构建失败——参见 scripts/check_readme_counts.py。

# unit suite (mocked backends, no real screen/input/recording touched)
python -m pytest -q

# handshake check -- prints every registered tool name
python scripts/list_tools.py

# real-hardware smokes (real screenshot PNG, real ~3s screen recording;
# never input-injection -- see safety rails above)
DESKTOP_MCP_LIVE=1 python -m pytest -q -k live_screenshot
DESKTOP_MCP_LIVE=1 python -m pytest -q -k live_record

安装

pip install -r requirements.txt   # or: pip install .
# deps: fastmcp==3.4.2, mss==10.2.0, pyautogui==0.9.54, PyGetWindow==0.0.9, pywin32==312
# also requires ffmpeg + ffprobe on PATH for the record group

在 ~/.claude.json 中注册为 desktop-mcp(stdio,system Python312, 启用了 observe+window+record 组,环境中不包含 input 组)。

商业支持

由 Jaimen Bell 维护。如需生产环境 MCP 集成、定制服务或 Agent 可靠性方面的支持,请访问 jaimenbell.dev。

正在构建自己的 MCP 服务?MCP Starter Kit 提供模板、构建指南,以及开发并发布此工具时积累的实战经验。

mcp-name: io.github.jaimenbell/desktop-mcp

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。