Skip to content

ui-locate-mcp

Verified

ui-locate-mcp · v0.7.0 · MIT · Web UI

Lightweight local visual grounding engine exposed as agent tools

Install

dsh plugin add ui-locate-mcp

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Tags

Readme

ui-locate-mcp

English · 简体中文

npm License: MIT DSH MCP plugin

在本机屏幕上按文字查找界面元素,返回可用于点击的像素坐标。它也提供定位后点击、输入、滚动和验证的组合工具,适合需要操作桌面界面的 DSH agent。

检测、OCR 和动作服务在本机运行。首次准备环境需要下载 Python 依赖和检测模型;模型约 80 MB。常驻服务负责推理,MCP 进程负责转发请求。

快速开始

  1. 在 DSH「插件 → 添加插件」输入 ui-locate-mcp,安装并启用。
  2. 在设置中打开 ui-locate 运行环境,选择目录和后端,点击「准备环境」。也可以调用 ui_locate_setup。
  3. 等待环境准备完成,再连接或重新启用 mcp-ui-locate;若 DSH 提示需要重启,按提示操作。
  4. 先调用 health,再尝试 locate_text(text="保存")。

这个 bundle 包含 MCP 客户端、Host 运行环境管理插件和 Client 设置页。npm 安装只取得代码,不会自动备齐 Python 环境和模型。

环境要求

  • 当前 bundle 的 MCP 启动路径按 Windows 配置;不要把 Python 核心的跨平台能力当作 bundle 的跨平台安装保证。
  • Python 项目要求 Python 3.12+。设置页使用宿主能找到的 Python 创建独立环境;找不到可用解释器时,先检查桌面安装附带的运行时。
  • 默认后端是 DirectML;另有 cuda 和 cpu。CUDA 需要相应的 NVIDIA 环境,依赖体积更大。切换后端需要重建环境。
  • package.json 目前没有声明 engines.dsh。不能据此断言所有 DSH 版本都兼容;本包需要宿主提供工具注册、MCP 客户端及设置页服务。

命令行安装到 Web profile:

dsh plugin --profile web add ui-locate-mcp

命令行操作前关闭对应的 DSH 实例,完成后重启。Desktop 用户优先使用插件页;管理 desktop profile 时使用该桌面安装自带的 CLI 和相同的 DSH_HOME。

工具

工具 用途
locate_text 按文字查找匹配元素及其中心坐标
find_all 返回同名或相似文字的多个候选
detect_elements 枚举画面中检测到的元素
ui_locate_marks 带编号框(可叠加带名字的网格)的截图,让模型选编号而不是估像素
ui_locate_act 定位后执行点击、输入、滚动等动作,并尝试验证
ui_locate_steps 串行执行一组步骤,返回失败位置
ui_locate_windows 列出顶层窗口(标题、句柄、客户区、是否前台)
ui_locate_diff 上次调用之后屏幕哪里变了,回矩形(不回图、不花视觉 token)
ui_locate_watch 录几秒,回一张关键帧拼图,只贴变化区域
ui_locate_frames / ui_locate_frame 列出或取回近期动作帧
list_monitors 显示器尺寸、原点和索引
health 检查服务是否就绪
ui_locate_setup 准备或重建 Python 环境与模型

前十二项由 MCP 服务提供,最后两项由 Host 插件提供;实际调用名称可能带宿主添加的命名空间。

locate_text(text="保存", monitor="primary")
ui_locate_act(text="保存", action="click", monitor="primary")

没有稳定文字的目标(游戏物品、工具栏图标、地图单位)先标注,再按编号操作:

ui_locate_marks(monitor="primary")          # 带编号框的截图
ui_locate_act(mark=17)                       # 点 #17,坐标由检测器算
ui_locate_marks(box="1200,40,1500,90")       # 放大一条小按钮(最多 4 倍)
ui_locate_marks(grid=8)                      # 没框出来?选一格,比如 D3
ui_locate_marks(box="D3", grid=4)            # 放大那一格,再选编号或更小的格
ui_locate_act(cell="B2")                     # 点某一格的中心

除了检测器的框,编号还包括纯几何规则找出的「成排成列、同尺寸」格子(物品栏、标签页、技能栏、表格,kind: "cell"),这类东西 UI 检测器在游戏里通常认不出。编号只属于生成它的那张图;带上 mark_set 可拒绝过期的编号。

坐标使用屏幕绝对位置,多显示器可能返回负坐标。monitor 可为 primary、索引字符串、all、window:<标题> 或 hwnd:<句柄>。界面移动后应重新定位,不要长期复用旧坐标。

只对一个窗口操作

给 ui_locate_marks、ui_locate_act、ui_locate_diff 传 window=(标题或其中一段,或句柄):

  • 抓图先走 Windows Graphics Capture:直接从合成器拿窗口画面,游戏被聊天窗口盖住也能抓到,GPU 渲染的内容也在,裁成客户区。每个窗口保持一个常驻会话(空闲 15 秒关闭),watch / wait 连续抓几乎零开销。WGC 失败或全黑时退到 PrintWindow,再退到按屏抓再裁。UI_LOCATE_WINDOW_CAPTURE / "window_capture":auto(默认)、wgc、printwindow、screen。WGC 需要 windows-capture 包,插件用 --no-deps 安装(它的元数据要求 opencv-python,和 opencv-python-headless 冲突)。Win10 上窗口周围可能出现黄色捕获边框,Win11 会关掉。
  • 发输入前先把目标窗口切到前台(SendInput 只送给前台窗口)。不给 window= 时,鼠标动作会切到点击点下面的窗口;focus="off" 关闭。结果里 performed.focus 报告是否成功。
  • 用 window= 标注的编号会记住这个窗口,之后 ui_locate_act(mark=…) 自动切前台、按窗口验证。

等待与验证

verify="screen" 且不给 settle_ms 时,动作后等画面停下来再比对(32px 网格差分,最多 1.5 秒;结果里有 settle.stable / elapsed_ms),不再固定等 220ms。验证结果会列出变化区域 regions;平均差被稀释、但目标旁边有一块明显变化时也算生效(by: "region")。action="wait" 不给文字 = 等画面静止。动作前会先静置约 80ms 量一下画面自己在动多少(水面、粒子、视频);这类画面(verify.noise.animated)上阈值随噪声抬高,本来就在动的格子不计,点空白动态背景不会再报 verified: true。

先看几秒再动手

很多操作的结果没法从一张截图预判(地图会不会动、怪往哪走、技能是否在冷却)。ui_locate_watch 连录几秒(duration_ms、fps),用网格差分挑关键帧,只回一张图:第一帧全景,之后每个关键帧只贴变化区域的裁片,标着时间和屏幕坐标。画面不动只回一帧;几乎每帧都在变的格子(水面、粒子、时钟)当作环境噪声不计(结果里的 ambient)。ui_locate_act(..., watch_ms=2000) 在输入发出前开录,动作和 settle 都结束(且录满 watch_ms)才停,动作过程本身也录进去,「看 → 做 → 看」一次调用完成。regions 模式的拼图最后补一张末帧全景,各关键帧的变化区域用框标出,方向和距离一眼可见。

ui_locate_marks 默认增量:同一块屏或同一个窗口,先和上一次比差分,没变就整份复用;变化不到 30% 时只对变化区域(以及跨在边界上的元素)重跑检测和 OCR。返回里 incremental.mode 是 reuse / partial / full;编号每次都重新分配。partial 之前先预估开销(incremental.estimated_cost:area_frac、text_frac、partial_ms 对比 full_ms,并用上一次 partial 的实测耗时校准)。OCR 开销跟着文字走、不跟面积走,所以文字密集页上变化压在文字上时直接走 full(reason: partial_not_cheaper)。incremental=false 返回 {mode: full, forced: true}。

配置与数据目录

Host 行 ID 是 ui-locate-update,MCP 行 ID 是 mcp-ui-locate。

Host 配置 默认 说明
pythonSync true 将环境中的 Python 包同步到 bundle 声明的版本
runtimeDir 空 Python 环境、状态与日志目录
modelDir 空 模型目录,可复用已有模型
backend 空 沿用已保存选择;首次默认 DirectML

默认运行目录按 UI_LOCATE_HOME → DSH_HOME/ui-locate → LOCALAPPDATA/ui-locate 选择。目录留空可跟随便携版的数据目录;显式绝对路径需要自行维护。

Python 服务还识别 UI_LOCATE_MODEL、UI_LOCATE_MODEL_DIR、UI_LOCATE_PROVIDER 和 UI_LOCATE_PORT,详见 config.py。MCP 默认连接本机 7788 端口。给模型的图统一是 JPEG 质量 90、色度不降采样(4:4:4),彩色小字不会糊;视觉 token 只看像素尺寸,不看文件大小。UI_LOCATE_JPEG_QUALITY 可改质量。

抓屏方式

UI_LOCATE_CAPTURE(或状态目录 runtime.json 里的 "capture")决定怎么截图:

值 方式 什么时候用
auto(默认) DXGI → WGC → GDI,失败或全黑就换下一个,并按屏记住上次成功的方式 绝大多数情况
dxgi Desktop Duplication 最快;能抓独占全屏的 D3D 游戏
wgc Windows Graphics Capture(需要 dxcam[winrt]) 混合显卡笔记本上 DXGI 报 UNSUPPORTED 时
gdi BitBlt 兼容性最好;全屏游戏常抓成全黑

health 的 screen.capture 会显示每块屏上次用的方式。记住的降级后端每 30 秒会重新试一次 DXGI,一帧抽风不会让这块屏永久降级。HTTP 请求(/marks、/act、/steps、/diff、/detect)也可以带 "capture": "gdi" 之类,只对这一次生效。

目标窗口以管理员运行而服务不是时,Windows 会静默丢弃模拟输入(UIPI)。health.integrity 显示服务自己的级别,/windows 显示每个窗口的,对这种窗口的动作会返回 uipi.blocked: true 和 warning。

游戏里的输入

全屏游戏常用 Raw Input / DirectInput 读鼠标键盘,桌面程序认的那套它不认。下面两项可以每次调用单独指定(pointer=、keys_mode=),也可以全局设:

设置 取值 什么时候用
UI_LOCATE_POINTER / "pointer" absolute(默认)、relative 全屏游戏里点了没反应、光标不动。relative 像真鼠标一样把光标推过去,移动期间临时关掉加速并按回读闭环修正;结果里 tracking: false 表示游戏锁住了系统光标,位置是按 1:1 估算的
UI_LOCATE_KEYS / "keys" vk(默认,同时填扫描码)、scancode DirectInput 游戏按键没反应

action="hold" 按住键 duration_ms 毫秒(走路、蓄力)。纯键盘动作不需要目标,屏幕验证改为整屏比对。

更新

插件本身由 DSH 插件页更新,本包不再自带更新器。 依赖是 registry 形式 (ui-locate-mcp),插件页那一行就会出现原生更新按钮,走宿主自己的插件管理器。

本包只负责宿主不管的那一半:npm 包装到新版之后,venv 里那份 Python 包还是旧的, 所以每次启动会比对版本并 pip install --no-deps 重装一次(可用 pythonSync 关掉)。 放在启动时也自带容错 —— 这一次失败不影响 JS 侧已经装好,下次会再试。

0.5.x 及更早的版本里自己维护过一整套更新器(读版本列表 + 调 installBundle)。它被删掉 是因为和插件页的按钮是两条并行链路:各自判断什么是最新,而且它装完会把依赖写法 改回 github:,插件页的按钮随即消失。历史核对见更新机制审计。

排障与使用边界

  • MCP 启动失败:先检查运行环境是否准备完成、虚拟环境 Python 是否存在,再重连 MCP。
  • 动作结果中的 ok 表示执行流程完成;只有对应的验证结果才能说明界面是否变化。verified: false 或 null 时不要当作操作成功。
  • 桌面权限、前台焦点、DPI 和应用框架会影响输入与截图。定位命中也不保证目标接受合成输入。
  • 不同 ONNX Runtime 后端共用同名 Python 包;换后端应重建,避免叠装。
  • OCR 有漏检和误识别;重要动作后检查画面或目标文字。

开发

python tests/check_bundle.py
node --test tests/
python -m unittest discover -s tests -p "test_*.py"

Python 测试需要相应依赖;真实模型和桌面冒烟还需要准备好的环境。历史性能与算法排障记录已移到技术笔记,不作为当前机器的性能承诺。

当前 release.yml 按版本标签或手动指定标签发布 npm。发布时需保持 package.json 与 pyproject.toml 的版本一致。

相关项目

@citydirector 的其它 DeepSeek Harness(DSH)项目:

项目 类型 用途
DSH-build 构建 DSH 的 Windows 便携版 / 桌面版绿色构建,每天跟随上游打补丁、冒烟、发布
dsh-remote-access-proxy 插件 在手机、平板或其它电脑上用浏览器访问 DSH Web GUI
deepinfra-fusion-proxy 插件 DeepInfra Standard / Flex 按会话切换与自动回退
dsh-loop-rescue 插件 模型复读时从流内切断、剪掉循环并自动续跑
dsh-pwsh-plugin 插件 常驻 pwsh 会话工具(pwsh_run),附带给 bash 补写边界的 WSL 垫片
dsh-session-manager 离线工具 离线升级、归档、回收站、清洗循环、修复烂尾 / 隐藏会话

许可证

MIT