WorkBuddy 的 Windows Control MCP — 项目总结与积分消耗深度分析

一句话总结:成功将 Codex Computer Use 的 Windows 桌面控制能力移植到 WorkBuddy MCP 框架,功能更全(36 个工具 vs 原版约 30 个),但积分消耗是同等操作的 40-50 倍。根因在于架构差异——Codex 是多模态模型原生"看"屏幕,而 MCP 是文本模型通过 base64 图片"读"屏幕。

从零开发 WorkBuddy Windows Control MCP:36 个工具让 AI 操控任意桌面应用


目录

  1. 项目概况
  2. 架构对比:为什么积分消耗天差地别
  3. 实测积分消耗数据
  4. 优化方案
  5. 使用建议

1. 项目概况

成果

指标 数值
MCP 工具总数 36 个
测试通过率 10/10 (100%)
在线 MCP 验证 36/36 工具全部可用
代码量 ~1400 行 Python
依赖 mcp SDK, uiautomation, pywin32, PIL, easyocr, opencv, psutil

工具分类

类别 数量 代表性工具
截屏与视觉 8 screenshot, observe_screen, extract_text (OCR), find_text, find_image
鼠标 4 click, move_mouse, drag_mouse, scroll
键盘 4 type_text, press_key, hotkey, type_unicode
窗口管理 7 list_windows, focus/move/resize/minimize/maximize/close_window
UI Automation 6 get_ui_tree, find_element, click_element, set_element_value
剪贴板 2 get/set_clipboard
进程 3 run_program, list_processes, kill_process
工具 2 wait, batch_actions

文件位置

~/.workbuddy/skills/windows-control/
├── server.py          # MCP 服务器(1400 行)
└── SKILL.md           # WorkBuddy 技能文档
~/.workbuddy/mcp.json  # MCP 配置(windows-control 条目)

超越 Codex 原版的增强

  • OCR 双引擎:pytesseract 优先 + easyocr 后备(无需系统安装 Tesseract)
  • 图像搜索find_image 用 OpenCV 模板匹配定位屏幕元素
  • 文字搜索find_text 用 OCR 定位文字并返回坐标
  • 完整窗口管理:移动/缩放/最小化/最大化/关闭
  • 进程管理:启动/列出/终止进程
  • 批量操作batch_actions 一次执行多个工具调用


2. 架构对比:为什么积分消耗天差地别

2.1 Codex Computer Use 的工作方式

用户指令 "点击保存按钮"
    │
    ▼
┌─────────────────────────────────────────────┐
│        Codex 多模态 VLM (单次 API 调用)       │
│                                             │
│  1. 截取屏幕 → 像素直接进入视觉编码器         │
│     (像素数据不进入文本上下文,0 token 开销)   │
│                                             │
│  2. VLM 视觉推理:                          │
│     "我看到桌面,保存按钮在坐标 (x, y)"       │
│                                             │
│  3. 执行工具调用:computer(action=click, x, y) │
│                                             │
│  【单次调用总 token 消耗: ~5K】               │
└─────────────────────────────────────────────┘

关键点:Codex 的模型原生支持视觉输入。截图作为像素直接输入视觉编码器,不经过文本 tokenizer。模型"看"到屏幕就像人眼看屏幕一样自然,不产生 token 开销。

2.2 WorkBuddy MCP 的工作方式

用户指令 "点击保存按钮"
    │
    ▼
┌──────────────────────────────────────────────────────┐
│          回合 1: 截图 (screenshot)                     │
│                                                      │
│  AI 发送: { tool: "screenshot" }                     │
│  服务器返回: base64 PNG 图片 (~528KB → ~180K tokens)   │
│  【回合 1 token 消耗: ~200K (含系统上下文)】            │
│                                                      │
├──────────────────────────────────────────────────────┤
│          回合 2: AI 分析截图                           │
│                                                      │
│  AI 思考: "我看到桌面上有一个保存按钮..."               │
│  AI 输出: ~1K tokens                                  │
│  【回合 2 token 消耗: ~30K (上下文膨胀)】               │
│                                                      │
├──────────────────────────────────────────────────────┤
│          回合 3: 点击 (click)                         │
│                                                      │
│  AI 发送: { tool: "click", x: 500, y: 300 }          │
│  服务器返回: "clicked at (500, 300)"                  │
│  【回合 3 token 消耗: ~15K】                          │
│                                                      │
├──────────────────────────────────────────────────────┤
│          回合 4: AI 确认                              │
│                                                      │
│  AI 输出: "已点击保存按钮"                              │
│  【回合 4 token 消耗: ~10K】                          │
└──────────────────────────────────────────────────────┘

一次简单操作总消耗: ~255,000 tokens
vs Codex CC: ~5,000 tokens
────────────────────────────────
差距: 约 51 倍

2.3 根因总结

维度 Codex Computer Use WorkBuddy MCP 差距
模型类型 多模态 VLM(原生视觉) 文本 LLM(图片=base64文本) 本质差异
截图开销 0 token(像素直入视觉编码器) ~180K tokens(528KB PNG → base64)
工具调用次数 1 次(截图+推理+操作合一) 3-5 次(截图→分析→定位→操作→确认) 3-5x
单次上下文 固定(视觉 token 为固定嵌入) 线性增长(每轮累积历史) 上下文逐轮膨胀
每次操作消耗 ~5K tokens ~200-300K tokens 40-60x

一句话:Codex 的模型"看"屏幕,MCP 的模型"读"屏幕图片的文字表示。前者是视觉,后者是翻译。


3. 实测积分消耗数据

3.1 单工具调用 token 估算

基于测试数据 + 标准 tokenizer 估算(1 token ≈ 4 字节 base64 或 4 字符文本):

工具 返回数据大小 估算 token 积分消耗(约)
screenshot 528KB PNG → 704KB base64 ~180,000 巨额
screenshot (半分辨率 JPEG Q60) 127KB → 169KB base64 ~43,000 中等
observe_screen 完整 UI 树 JSON + 截图 ~100,000 巨额
list_windows 26 窗口详情 JSON ~10,000
extract_text (OCR) 全屏文字 (~3KB) ~1,000 极小
list_processes (全量) 104KB JSON ~26,000 中等
get_ui_tree 控件树 JSON (depth=2) ~5,000
get_clipboard / press_key / click <1KB ~200 可忽略

3.2 开发+测试阶段的累计消耗

在本次开发会话中,我们执行了:

阶段 操作 估算 token
开发阶段 代码编写、MCP 握手测试 ~50K
离线测试 10 项 Python 测试脚本 0(本地执行)
在线 MCP 测试 screenshot (595KB PNG) ~190K
在线 MCP 测试 get_screen_size + cursor + windows + clipboard ~15K
在线 MCP 测试 observe_screen (UI树+截图) ~100K
在线 MCP 测试 list_processes (全量 104KB) ~26K
在线 MCP 测试 get_ui_tree + find_element + get_window_text ~15K
在线 MCP 测试 extract_text (OCR) ~2K
在线 MCP 测试 set_clipboard + focus_window ~5K
累计 ~400K+ tokens

注意:这只是 MCP 工具本身的 token 消耗。再加上每轮对话的系统上下文(~15K/轮)和历史累积,实际消耗更高。


4. 优化方案

4.1 立即可行的优化(降低 70-80% 消耗)

A. 截图压缩(最大优化点)

当前 take_screenshot() 返回全分辨率 PNG(528KB)。改为:

def take_screenshot(region=None, hwnd=None, quality=60, scale=1.0):
    """quality: JPEG quality 1-100; scale: 0.25-1.0"""
    # ... grab image ...
    if scale < 1.0:
        img = img.resize((int(img.width*scale), int(img.height*scale)))
    buf = io.BytesIO()
    img.save(buf, format="JPEG", quality=quality)
    return buf.getvalue()

效果

配置 大小 Token 节省
PNG 全分辨率(当前) 528KB 180K
JPEG Q80 全分辨率 560KB 191K -6%(JPEG不适合截图)
JPEG Q50 全分辨率 394KB 134K 26%
JPEG Q60 半分辨率 127KB 43K 76%
JPEG Q40 1/4 分辨率 ~40KB ~13K 93%

注:JPEG 对截图(大量文字+UI 元素)压缩率不如 PNG。半分辨率才是真正的大头节省。

B. 限制返回数据量
工具 当前行为 优化后
list_windows 返回所有窗口的完整信息 加 max_results=10 参数
list_processes 返回全部进程(104KB) 加 name_filter 默认只返回匹配的,否则截断
observe_screen 截图+完整UI树 加 mode="light" 跳过 UI 树,只返回基本信息和低清缩略图
get_ui_tree 全控件树 默认 depth=2, max_children=20
C. 截图缓存

对同一轮对话中的重复截图做缓存(时间戳 + 哈希),避免相同画面重复传输。

4.2 中长期优化(降低 95%+ 消耗)

D. 本地视觉推理层(最佳方案)

在 MCP 服务器端集成一个本地小模型做视觉推理:

用户指令 "点击保存按钮"
    │
    ▼
MCP 服务器: 截图 → 本地视觉模型分析 → 返回结构化结果
    │
    │  "桌面上有这些可点击元素:
    │   - 保存按钮: (500, 300), confidence=0.95
    │   - 取消按钮: (600, 300), confidence=0.92"
    │
    ▼
AI: 执行 click(500, 300)
【总 token: ~5K,接近 Codex 水平】

可选技术方案:

  • OmniParser(微软):专为 GUI Agent 设计的屏幕解析模型,输出结构化 UI 元素
  • UI-TARS(字节):GUI 操作专用 VLM
  • Florence-2(微软):轻量级视觉基础模型
E. 工具合并

将"截图→分析→点击"合并为一个 smart_click(description) 工具,减少往返次数。


5. 使用建议

何时使用 Windows Control MCP

场景 推荐 原因
点击已知坐标的按钮 ✅ 可以 只需 click(x,y),消耗极低
输入文字、按快捷键 ✅ 可以 type_text/press_key 几乎不消耗积分
读写剪贴板 ✅ 可以 纯文本操作,零负担
窗口管理(最大化/最小化) ✅ 可以 只需窗口句柄,轻量
需要看屏幕上有什么 ⚠️ 谨慎 用半分辨率截图或 observe_screen(light)
复杂的 GUI 自动化流程 ❌ 不推荐 多次截图+OCR 会很快耗尽积分
对 Adobe/Office 操作 ❌ 用 Flue Flue 走脚本 API,0 截图开销

最佳实践

  1. 截图优先用低分辨率:在 screenshot 工具中指定 quality=50, scale=0.5(等实现压缩参数后)
  2. 能用 Flue 就用 Flue:有脚本 API 的应用(Adobe, Office, Blender)用 Flue,零积分消耗
  3. 减少"看屏幕"的次数:尽量凭窗口标题、UI 控件树定位,而不是每次都截图
  4. 批量操作:用 batch_actions 合并多次操作为一次调用
  5. 关闭不必要的工具:如果只需要简单操作,在 MCP 配置中 disable 不用的工具

与 Flue 的分工

Flue Windows Control
适用应用 13 个专业应用(Adobe/Office/Blender等) 任意 Windows 应用
操作方式 脚本 API(JSX/VBA/Python) GUI 模拟(鼠标键盘+UI树)
积分消耗 (本地执行脚本) (截图=大量token)
精确度 完美(直接调用API) 依赖屏幕识别
速度 较慢(需要截图/OCR)

规则:优先 Flue → 不支持时降级到 Windows Control → 控制截图频率。


附录:技术细节

关键 Bug 修复记录

问题 修复
ctypes.INT 不存在 → ctypes.c_int
win32gui.EnumWindows 在线程池中返回空 → 改用 ctypes EnumWindows + WNDENUMPROC 回调
GetDC(0) 64位溢出 → 声明 user32.GetDC.argtypes = [wintypes.HWND] 等所有 Win32 函数签名
COM 卸载导致 uiautomation 间歇失败 → 移除 CoUninitialize(),COM 保持在线程中存活
Tesseract 未安装导致 OCR 不可用 → 添加 easyocr 后备引擎(纯 Python,自动下载模型)

测试环境

  • OS: Windows 11
  • 屏幕: 2560×1440
  • Python: 3.13.12 (managed venv)
  • 测试窗口: WorkBuddy, ChatGPT, VS Code, ChatCut, Edge, 豆包, 百度网盘, Affinity Designer
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐