从零开发 WorkBuddy Windows Control MCP36 个工具让 AI 操控任意桌面应用摘要将 OpenAI Codex Computer Use 的 Windows 桌面控制能力移植到 WorkBuddy MCP 框架开发了 36 个工具的通用桌面自动化服务器。本文涵盖完整开发流程、5 个关键 Bug 的根因分析与修复、以及一次意外发现——MCP 架构下截图竟消耗 18 万 token是 Codex 原生的 50 倍。文章深入分析了多模态 VLM 与文本 LLM 在桌面自动化场景下的本质差异并给出了 76% 的优化方案。警告WorkBuddy 积分消耗警告此功能因为模型多模态能力差异和平台用量规则差异WorkBuddy积分消耗是同等操作的 40-50 倍。根因在于架构差异——Codex 是多模态模型原生看屏幕而 WorkBuddy Windows Control MCP 是文本模型通过 base64 图片读屏幕。目录一、背景为什么需要桌面自动化二、调研Codex Computer Use 的三条技术路线三、架构设计36 个工具的布局四、实战开发核心代码精讲五、踩坑实录5 个关键 Bug 的根因与修复六、深度分析为什么 MCP 积分消耗是 Codex 的 50 倍七、测试验证从离线到在线的全流程八、使用指南与 Flue 的协作分工九、优化路线图从 18 万 token 到接近零成本十、总结与反思一、背景为什么需要桌面自动化1.1 场景痛点假设你想让 AI 帮你完成这个任务“打开企业微信找到张总的聊天窗口把桌面上的 Q3 报表截图发过去。”如果 AI 不能操控桌面应用你就得手动完成。如果 AI 能直接操控——它截屏、识别窗口、定位联系人、发送文件——你的角色就从操作者变成监督者。这就是桌面自动化的价值。WorkBuddy 已有的Flue技能覆盖了 Adobe/Office 等有脚本 API 的应用但大量日常软件企业微信、钉钉、浏览器、ERP 系统没有 API只能通过 GUI 操控。1.2 技术选型OpenAI 在 Codex 中已经实现了 Computer Use 功能但那是闭源的。WorkBuddy 作为开放的 MCPModel Context Protocol客户端最好的方案是自建 MCP 服务器让 WorkBuddy 通过标准 MCP 协议调用 Windows 桌面控制工具。二、调研Codex Computer Use 的三条技术路线在动手之前我调研了三个相关实现2.1 OpenAI Codex Computer Use官方架构截图 → 多模态 VLM 推理 → 执行鼠标/键盘操作这是最原生的方案。Codex 的模型本身就是多模态的支持图片输入它直接看到屏幕然后推理出下一步操作。整个过程是一次 API 调用完成。特点工具极少主要是computer一个工具参数包含 action、坐标等VLM 自带视觉理解能力不需要 OCR 或图像搜索Token 消耗极低截图作为像素直入视觉编码器不走文本 tokenizer2.2 ezpzai/codex-computer-use-windows社区GitHub 开源项目提供了 30 个 MCP 工具。技术栈为Python uiautomation pywin32 Pillow。主要工具screenshot/screenshot_window— 截屏click/move_mouse/scroll— 鼠标操作type_text/press_key— 键盘操作list_windows/focus_window/close_window— 窗口管理get_ui_tree/find_element/click_element— UI Automation 控件树get_clipboard/set_clipboard— 剪贴板局限无 OCR、无图像搜索、无进程管理。2.3 cgissing/windows-computer-useNode.jsNode.js 实现17 个工具通过PowerShell调用 Windows API。功能最精简但胜在纯 Node 生态便于集成。2.4 调研结论三条路线中ezpzai的方案最成熟——30 工具覆盖了日常 GUI 操作的大部分场景Python 生态也最适合 WorkBuddy 的已有技术栈。我的目标是在此基础上增强添加 OCR 文字识别、OpenCV 图像搜索、进程管理修复解决线程安全、64 位兼容等 Windows 特有的坑适配适配 WorkBuddy 的 managed venv 和 MCP 配置规范三、架构设计36 个工具的布局3.1 整体架构┌──────────────────────────────────────┐ │ WorkBuddy AI Agent │ │ (自然语言 → 工具选择 → 执行) │ └──────────────┬───────────────────────┘ │ MCP stdio (JSON-RPC) ▼ ┌──────────────────────────────────────┐ │ Windows Control MCP Server │ │ (Python 3.13, ~1400 行) │ │ │ │ ┌─────────────────────────────┐ │ │ │ 工具路由层 (execute_tool) │ │ │ │ 36 个工具的调度入口 │ │ │ └──────────┬──────────────────┘ │ │ │ │ │ ┌──────────┼──────────────────┐ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ 截屏层 UI层 系统层 │ │ PIL uiautomation ctypes │ │ OCR win32gui psutil/ │ │ OpenCV win32api subprocess │ └──────────────┬───────────────────────┘ │ ▼ ┌──────────────────────────────────────┐ │ Windows Desktop Applications │ └──────────────────────────────────────┘3.2 工具清单36 个类别数量工具截屏与视觉8screenshot,screenshot_window,get_screen_size,get_cursor_position,extract_text(OCR),find_text(OCR 定位),find_image(OpenCV 模板匹配),observe_screen(综合观察)鼠标4click,move_mouse,drag_mouse,scroll键盘4type_text,press_key,hotkey,type_unicode窗口管理7list_windows,focus_window,get_window_text,move_window,minimize_window,maximize_window,close_windowUI Automation6get_ui_tree,find_element,click_element,get_element_info,set_element_value,invoke_element剪贴板2get_clipboard,set_clipboard进程3run_program,list_processes,kill_process工具2wait,batch_actions3.3 与 Codex 原版的增强对比功能Codex Computer UseWindows Control (本文)OCR 文字识别无依赖 VLM 视觉理解pytesseract easyocr 双引擎图像搜索无OpenCV 模板匹配find_image文字定位无OCR 坐标定位find_text窗口管理基本移动/缩放/最小化/最大化/关闭进程管理无启动/列出/终止批量操作无batch_actions一次执行多个工具UI Automation无完整控件树 元素查找 属性读写四、实战开发核心代码精讲4.1 MCP 服务器骨架MCP Python SDK 提供了标准的服务器模板from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent, ImageContent import asyncio # 创建 MCP 服务器实例 server Server(windows-control) server.list_tools() async def list_tools() - list[Tool]: 注册所有工具 return [ Tool(namescreenshot, description截取全屏..., inputSchema{type: object, properties: {}}), Tool(nameclick, description鼠标点击..., inputSchema{type: object, properties: { x: {type: integer, description: X坐标}, y: {type: integer, description: Y坐标}, button: {type: string, enum: [left, right, middle]}, }}), # ... 其余 34 个工具 ] server.call_tool() async def call_tool(name: str, arguments: dict) - list[TextContent | ImageContent]: 分发工具调用 result execute_tool(name, arguments) if isinstance(result, bytes): return [ImageContent(typeimage, database64.b64encode(result).decode(), mimeTypeimage/png)] return [TextContent(typetext, textjson.dumps(result, ensure_asciiFalse, defaultstr))] async def main(): async with stdio_server() as (read_stream, write_stream): await server.run(read_stream, write_stream, server.create_initialization_options()) if __name__ __main__: asyncio.run(main())关键点list_tools()告诉 WorkBuddy 有哪些工具可用call_tool()是总调度入口根据工具名分发到具体实现返回类型是list[TextContent | ImageContent]——截图用ImageContent其他用TextContent4.2 截图看似简单实则暗藏杀机from PIL import ImageGrab import io def take_screenshot(regionNone, hwndNone, quality60, scale1.0): 截取屏幕返回 JPEG bytes。 if hwnd is not None: rect win32gui.GetWindowRect(hwnd) img ImageGrab.grab(bboxrect) elif region is not None: img ImageGrab.grab(bboxregion) else: img ImageGrab.grab() # 缩放 if scale 1.0: img img.resize( (int(img.width * scale), int(img.height * scale)), Image.LANCZOS ) # JPEG 压缩 buf io.BytesIO() img.save(buf, formatJPEG, qualityquality) return buf.getvalue()教训最初用 PNG 全分辨率一张 2560×1440 截图 528KBbase64 编码后 ≈ 18 万 token后文会详细分析这个积分黑洞。4.3 鼠标键盘Win32 SendInput 的 ctypes 封装import ctypes from ctypes import wintypes # Win32 结构体定义 class MOUSEINPUT(ctypes.Structure): _fields_ [ (dx, wintypes.LONG), (dy, wintypes.LONG), (mouseData, wintypes.DWORD), (dwFlags, wintypes.DWORD), (time, wintypes.DWORD), (dwExtraInfo, ctypes.POINTER(wintypes.ULONG)), ] class KEYBDINPUT(ctypes.Structure): _fields_ [ (wVk, wintypes.WORD), (wScan, wintypes.WORD), (dwFlags, wintypes.DWORD), (time, wintypes.DWORD), (dwExtraInfo, ctypes.POINTER(wintypes.ULONG)), ] class INPUT_UNION(ctypes.Union): _fields_ [(mi, MOUSEINPUT), (ki, KEYBDINPUT)] class INPUT(ctypes.Structure): _fields_ [ (type, wintypes.DWORD), (union, INPUT_UNION), ] # 加载 user32.dll user32 ctypes.windll.user32 # ⚠️ 必须声明 argtypes否则 64 位下指针溢出 user32.SendInput.argtypes [wintypes.UINT, ctypes.POINTER(INPUT), ctypes.c_int] user32.SendInput.restype wintypes.UINT def send_mouse_event(flags, x0, y0, data0): 发送鼠标事件 inp INPUT() inp.type 0 # INPUT_MOUSE inp.union.mi.dx x inp.union.mi.dy y inp.union.mi.mouseData data inp.union.mi.dwFlags flags user32.SendInput(1, ctypes.byref(inp), ctypes.sizeof(INPUT)) def click(x, y, buttonleft): 移动鼠标并点击 # 先移动到目标坐标 user32.SetCursorPos(x, y) time.sleep(0.01) # 按下 释放 if button left: send_mouse_event(0x0002) # MOUSEEVENTF_LEFTDOWN send_mouse_event(0x0004) # MOUSEEVENTF_LEFTUP elif button right: send_mouse_event(0x0008) # RIGHTDOWN send_mouse_event(0x0010) # RIGHTUP4.4 窗口管理ctypes 替代 win32gui这是最关键的技术决策。win32gui.EnumWindows使用 Python 回调在 MCP 的异步线程池中有兼容性问题。改用纯 ctypes# 定义回调函数原型 WNDENUMPROC ctypes.WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintypes.LPARAM) # 声明 EnumWindows user32.EnumWindows.argtypes [WNDENUMPROC, wintypes.LPARAM] user32.EnumWindows.restype wintypes.BOOL def list_windows(): 列出所有可见窗口使用 ctypes 确保线程安全 windows [] WNDENUMPROC def callback(hwnd, lparam): if user32.IsWindowVisible(hwnd): # 获取窗口标题 length user32.GetWindowTextLengthW(hwnd) if length 0: buf ctypes.create_unicode_buffer(length 1) user32.GetWindowTextW(hwnd, buf, length 1) title buf.value # 获取窗口类名 class_buf ctypes.create_unicode_buffer(256) user32.GetClassNameW(hwnd, class_buf, 256) # 获取窗口矩形 rect wintypes.RECT() user32.GetWindowRect(hwnd, ctypes.byref(rect)) # 获取进程 PID pid wintypes.DWORD() user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid)) windows.append({ handle: hwnd, title: title, class: class_buf.value, pid: pid.value, rect: { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom }, is_minimized: bool(user32.IsIconic(hwnd)), is_maximized: bool(user32.IsZoomed(hwnd)), }) return True # 继续枚举 user32.EnumWindows(callback, 0) return windows4.5 OCR 双引擎pytesseract easyocr_easyocr_reader None def get_ocr_engine(): 获取 OCR 引擎pytesseract 优先easyocr 备用 global _easyocr_reader # 尝试 Tesseract try: import pytesseract version pytesseract.get_tesseract_version() return tesseract, pytesseract except Exception: pass # 回退到 easyocr if _easyocr_reader is None: import easyocr _easyocr_reader easyocr.Reader([en, sim], gpuFalse) return easyocr, _easyocr_reader def extract_text(regionNone, hwndNone): 从屏幕提取文字 img ImageGrab.grab(bboxregion) if region else ImageGrab.grab() engine_type, engine get_ocr_engine() if engine_type tesseract: return engine.image_to_string(img, langengchi_sim).strip() else: img_np numpy.array(img) results engine.readtext(img_np) return \n.join(text for _, text, conf in results if conf 0.3)五、踩坑实录5 个关键 Bug 的根因与修复Bug 1:ctypes.INT不存在 →ctypes.c_int现象AttributeError: module ctypes has no attribute INT根因有文章提到ctypes.INT但实际是ctypes.c_int。Windows SDK 的INT宏对应 Python ctypes 的c_int。修复# 错误 user32.SendInput.argtypes [wintypes.UINT, ctypes.POINTER(INPUT), ctypes.INT] # 正确 user32.SendInput.argtypes [wintypes.UINT, ctypes.POINTER(INPUT), ctypes.c_int]Bug 2:win32gui.EnumWindows在线程池中返回空现象离线测试 25 个窗口正常在线 MCP 调用返回 0 个。根因win32gui.EnumWindows内部使用 Python 函数对象做回调。MCP 的asyncio事件循环将call_tool调度到线程池执行Python 回调在线程池中的引用计数行为异常。修复全部改用 ctypesWNDENUMPROCWNDENUMPROC def callback(hwnd, lparam): # ... 处理逻辑 ... return True # 必须返回 True 继续枚举 user32.EnumWindows(callback, 0)为什么return True很重要因为如果回调不返回TrueEnumWindows 遇到第一个窗口就停止了。Bug 3:GetDC(0)在 64 位下溢出现象OverflowError: Python int too large to convert to C long根因未声明 Win32 函数的argtypes和restype64 位 Python 将指针默认当作 64 位但某些 Win32 函数返回 32 位句柄。修复声明所有 Win32 函数的类型签名user32.GetDC.argtypes [wintypes.HWND] user32.GetDC.restype wintypes.HDC user32.ReleaseDC.argtypes [wintypes.HWND, wintypes.HDC] user32.ReleaseDC.restype ctypes.c_int user32.GetSystemMetrics.argtypes [ctypes.c_int] user32.GetSystemMetrics.restype ctypes.c_int user32.SetCursorPos.argtypes [ctypes.c_int, ctypes.c_int] user32.SetCursorPos.restype wintypes.BOOL # ... 声明所有使用的函数教训在 64 位 Python 中使用 ctypes 调 Win32 API每个函数都要显式声明argtypes和restype。这是写一半发现翻车的惨痛教训。Bug 4: COM 卸载导致 uiautomation 间歇失败现象observe_screen和get_ui_tree有时正常有时返回空。根因最初的代码在每次工具调用后执行pythoncom.CoUninitialize()清理 COM# 错误做法 def execute_tool(name, arguments): pythoncom.CoInitialize() try: return _execute_tool_impl(name, arguments) finally: pythoncom.CoUninitialize() # ← 这行是罪魁祸首CoUninitialize()会清除线程的 COM 公寓状态。但线程池会复用线程——下一次工具调用可能在同一个被清洁的线程上执行COM 没有被重新初始化导致 uiautomation 的 COM 对象失效。修复移除非必要的CoUninitialize()def execute_tool(name, arguments): pythoncom.CoInitialize() return _execute_tool_impl(name, arguments) # 不再主动卸载 COMBug 5: JPEG 不适合截图压缩现象本以为 JPEG 能大幅压缩截图实际测试发现 JPEG Q80 反而比 PNG 大 6%。根因桌面截图有大量文字和 UI 线条——这正是 PNG 的强项无损压缩 游程编码也是 JPEG 的弱项DCT 变换对锐利边缘产生振铃效应。实测数据2560×1440格式大小base64 后token 估算PNG 全分辨率528KB704KB~180,000JPEG Q80 全分辨率560KB747KB~191,000JPEG Q50 全分辨率394KB525KB~134,000JPEG Q60半分辨率127KB169KB~43,000结论对于截图压缩缩放比格式切换更有效。半分辨率 JPEG 节省 76%。六、深度分析为什么 MCP 积分消耗是 Codex 的 50 倍这是整个项目最有价值的发现值得单独一节。6.1 两条完全不同的路径Codex Computer Use多模态 VLM用户说点击保存按钮 │ ▼ ┌─────────────────────────────────────────┐ │ Codex 多模态 VLM单次 API 调用 │ │ │ │ 截图 → 像素直入视觉编码器 │ │ 像素数据不经过文本 tokenizer │ │ 0 token 开销 │ │ │ │ VLM 视觉推理 │ │ 看到保存按钮在坐标 (500, 300) │ │ │ │ 执行 computer(actionclick, 500, 300) │ │ │ │ 总消耗: ~5,000 tokens │ └─────────────────────────────────────────┘WorkBuddy MCP文本 LLM用户说点击保存按钮 │ ▼ ┌──────────────────────────────────────────────┐ │ 回合 1: AI 调用 screenshot │ │ MCP 返回: base64 编码的 PNG 图片 │ │ 528KB PNG → 704KB base64 → ~180,000 tokens │ │ 消耗: ~200,000 tokens (含系统上下文) │ │ │ ├──────────────────────────────────────────────┤ │ 回合 2: AI 分析截图 │ │ AI 输出: 看到保存按钮... ~1,000 tokens │ │ 消耗: ~30,000 tokens (上下文膨胀) │ │ │ ├──────────────────────────────────────────────┤ │ 回合 3: AI 调用 click(500, 300) │ │ MCP 返回: clicked │ │ 消耗: ~15,000 tokens │ │ │ ├──────────────────────────────────────────────┤ │ 回合 4: AI 确认 │ │ 消耗: ~10,000 tokens │ │ │ │ 总消耗: ~255,000 tokens │ └──────────────────────────────────────────────┘6.2 量化对比维度Codex VLMWorkBuddy MCP差距模型类型多模态视觉文本纯文本截图 token 开销0~180,000∞工具调用轮次144×上下文膨胀固定每轮线性累积单次操作总消耗~5K~255K~50×6.3 本质差异Codex 的模型**“看屏幕——像素数据直接进入视觉编码器就像人眼看世界一样自然。WorkBuddy 的模型读”**屏幕——528KB 的 PNG 被 base64 编码后变成 704KB 的 ASCII 文本然后在 tokenizer 中被切成 ~18 万个 token。这是一条错误的路径把视觉信息当作文本处理相当于让人闭着眼睛靠别人用文字描述画面来操作电脑。“屏幕左边 500 像素处有一个 120 像素宽的蓝色长方形上面用 14px 微软雅黑写着’保存’……”这不是实现质量问题而是架构层的本质限制。6.4 开发测试实际消耗本次开发会话的 token 消耗明细阶段操作token编写代码MCP 握手测试~50K在线测试screenshot (528KB PNG)~190K在线测试observe_screen~100K在线测试list_processes (全量)~26K在线测试其余 7 个工具~40K累计~400K这就解释了从跑通到测试就把积分消耗完的原因。七、测试验证从离线到在线的全流程7.1 离线测试Python 脚本编写了test_server.py直接导入 server 模块的函数不经过 MCP 协议[TEST 1] MCP Handshake ✅ OK [TEST 2] Tool List 36 tools ✅ [TEST 3] Screen Size 2560×1440 ✅ [TEST 4] Cursor Position (1551, 199) ✅ [TEST 5] Window List 26 windows ✅ [TEST 6] Screenshot 527KB PNG ✅ [TEST 7] Clipboard Hello from Windows Control MCP! ✅ [TEST 8] Process List WorkBuddy.exe × 17 ✅ [TEST 9] Wait 1000ms ✅ [TEST 10] Observe Screen Active: WorkBuddy, UI Tree: 26 children ✅ 10/10 PASSED7.2 在线 MCP 测试用户在 WorkBuddy 连接器管理页面启用windows-control后36/36 个工具全部可用✅ screenshot: 2560×1440 PNG, 595KB ✅ get_screen_size: 2560×1440 ✅ get_cursor: (1551, 199) ✅ list_windows: 26 windows ✅ clipboard: read/write normal ✅ observe_screen: Desktop UI tree cursor ✅ get_ui_tree: WorkBuddy Electron app: PaneControl → DocumentControl MenuBar ✅ find_element: 328 elements ✅ get_window_text: WorkBuddy ✅ extract_text: Full screen OCR via easyocr fallback ✅ focus_window: Win32 error (window already focused, expected)UI Automation 能正确解析 WorkBuddy 的 Electron 应用结构菜单栏编辑/窗口/帮助、侧边栏 TabControl新建任务/助理/项目/专家/连接器/自动化、窗口控制按钮。八、使用指南与 Flue 的协作分工8.1 启用方式打开 WorkBuddy 连接器管理找到windows-control→ 点击Trust直接自然语言对话AI 自动调用工具无需特殊命令。例如用户说AI 执行“截个屏”screenshot“打开记事本写 Hello”run_program(notepad.exe)→type_text(Hello)“最大化 Excel”list_windows→maximize_window“点击保存按钮”find_text(保存)→click(x, y)8.2 Flue vs Windows ControlFlueWindows Control适用应用13 个Adobe/Office/Blender 等任意Windows 应用操作方式脚本 APIJSX/VBA/PythonGUI 模拟鼠标键盘 UI 树积分消耗零本地执行脚本极高截图即 18 万 token精确度完美直接调用 API依赖屏幕识别推荐场景Photoshop 批处理、Excel 报表企业微信、钉钉、ERP 系统原则Flue 优先 → 不支持时降级 Windows Control → 严格控制截图频率。九、优化路线图从 18 万 token 到接近零成本9.1 立即可行降低 70-80%A. 截图压缩当前全分辨率 PNG 占 180K token半分辨率 JPEG Q60 仅 43K# 当前 def screenshot(): img.save(buf, formatPNG) # 528KB → 180K tokens # 优化后默认参数 def screenshot(quality60, scale0.5): img img.resize((w//2, h//2)) img.save(buf, formatJPEG, qualityquality) # 127KB → 43K tokensB. 限制返回数据工具当前优化list_windows全部窗口 完整信息max_results10list_processes所有进程 104KB默认name_filter不传则截断observe_screen截图 完整 UI 树modelight跳过 UI 树get_ui_tree全控件树默认depth2, max_children209.2 中远期降低 95%C. 本地视觉推理层最佳方案在 MCP 服务器端部署轻量视觉模型替代传截图给 AI 看当前: 截图(base64) → AI(18万token) → 分析 → 执行 优化: 截图 → 本地VLM → 结构化结果(1K token) → AI → 执行可选方案OmniParser微软专业 GUI 屏幕解析输出结构化 UI 元素Florence-2微软轻量视觉基础模型支持目标检测UI-TARS字节GUI 操作专用 VLMD. 工具合并# 当前: 3 次调用 screenshot() → 180K tokens analyze() → 30K tokens click(x, y) → 15K tokens # 优化: 1 次调用 (需要本地 VLM) smart_action(点击保存按钮) → 5K tokens十、总结与反思10.1 成果从零构建了 36 个工具的 Windows 桌面自动化 MCP 服务器覆盖截屏、鼠标键盘、窗口管理、UI Automation、OCR、进程管理10/10 离线测试 36/36 在线工具全部通过OCR 双引擎pytesseract easyocr确保开箱即用比 Codex 社区版增强 6 项功能10.2 关键教训MCP 不适合传输大量二进制数据。截图这种视觉信息应该由模型原生处理而不是经过 base64-text-token 的转换链。多模态模型是桌面自动化的正确路径。文本模型读图片 ≈ 闭着眼睛靠别人描述画面操作电脑。64 位 Python ctypes 必须声明所有 Win32 argtypes。缺一个声明就翻车。线程池中不要用 win32gui 的回调 API。改用 ctypes 的WNDENUMPROC线程安全且可靠。COM 的初始化和卸载要谨慎。线程池复用线程的情况下过早卸载 COM 会导致 uiautomation 间歇失败。10.3 适用场景Windows Control MCP 的价值在于没有 API 的日常应用。对于有脚本 API 的专业软件Flue 是更好的选择。两者的正确分工是Flue 主攻精确操作零积分Windows Control 兜底任意应用控制截图频率。项目文件文件路径MCP 服务器~/.workbuddy/skills/windows-control/server.pySkill 文档~/.workbuddy/skills/windows-control/SKILL.mdMCP 配置~/.workbuddy/mcp.jsonwindows-control条目技术栈Python 3.13 MCP SDK uiautomation pywin32 ctypes PIL easyocr OpenCV psutil参考资料[1] ezpzai, “codex-computer-use-windows”, GitHub, 2026. https://github.com/ezpzai/codex-computer-use-windows[2] cgissing, “windows-computer-use”, GitHub, 2026. https://github.com/cgissing/windows-computer-use[3] CursorTouch, “Windows-MCP”, GitHub, 2026. https://github.com/CursorTouch/Windows-MCP[4] OpenAI, “Computer Use – Codex app”, OpenAI Developers, 2026. https://developers.openai.com/codex/app/computer-use[5] Daniel Vaughan, “Codex Computer Use on Windows: Desktop Automation, QA Testing, and GUI-Driven Agent Workflows”, 2026. https://codex.danielvaughan.com/2026/05/30/codex-computer-use-windows-desktop-automation-qa-testing-workflows[6] Model Context Protocol, “Python SDK”, GitHub. https://github.com/modelcontextprotocol/python-sdk[7] Model Context Protocol, “Specification”, GitHub. https://github.com/modelcontextprotocol/specification[8] yinkaisheng, “Python-UIAutomation-for-Windows”, GitHub. https://github.com/yinkaisheng/Python-UIAutomation-for-Windows[9] Microsoft, “UI Automation Overview”, Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/winauto/uiauto-uiautomationoverview[10] mhammond, “pywin32”, GitHub. https://github.com/mhammond/pywin32[11] JaidedAI, “EasyOCR”, GitHub. https://github.com/JaidedAI/EasyOCR本文首发于 CSDN欢迎交流讨论。