题接上一篇《Kimi 也支持电脑控制了》!
让智能体控制电脑,帮你完成各种操作,在自动化拟人任务和自动化测试中是非常有用的。但是并不是所有的模型和智能体都支持的。
在安装了 Kimi 的电脑控制插件之后,我发现了一个很有意思的事情。

我发现 KimiCode 的电脑控制插件,并不是只有它自家可以用,也支持其他智能体调用。比如明确支持的就有 Claude Code 和 ChatGPT。它已经自动识别了,并且可以一键启用。
除了明确支持的之外,它也提供了其他 Agent 接入的方法。

其实就是只要让其他智能体添加一个 MCP Server 就可以了!
然后我用我自己手搓的智能体试了一下。

没想到真的成功了。
我测试的时候选的还是没有视觉能力的 DeepSeek Flash!用 DS 的好处是成本低啊,成本低啊,成本低啊。
我主要是测试了两个任务。第一个是让它帮我打开计算器,计算一下 9 x 9 等于多少。

这是一个很简单的任务,但是它必须完成一个链路,你需要先打开计算器,然后找到 9 的按键位置,按下按钮,然后找到结果区域,读取结果。是一个完整的操作闭环。
第二个任务是,让它帮我打开 Chrome 浏览器,搜索 DeepSeek,然后帮我读取第一条结果。

也轻松搞定了。
这个 Computer Use 有点搞头,完全免费,而且支持各种 Agent,可以用便宜模型。
我看了一下这个电脑控制插件包含 13 个工具!
| 工具 | 作用 |
|---|---|
list_apps |
按进程列出运行中的桌面应用 |
launch_app |
按路径/名称/AppID 启动应用 |
activate_window |
把已有窗口带到前台(pid/app/window_id 三选一) |
get_app_state |
窗口状态快照(截图 + 无障碍树,产出 snapshot_id),被动不激活 |
click |
真实鼠标点击(元素 index 或截图坐标) |
type_text |
聚焦输入框后剪贴板粘贴输入 |
press_key |
按键/组合键(Enter、Ctrl+A、Alt+F4 等) |
scroll |
滚动(元素或坐标,dy>0 上滚) |
set_value |
UIA 设原生控件值(Value/RangeValue) |
perform_secondary_action |
对原生控件执行 UIA 语义动作(invoke/toggle/expand 等) |
select_text |
选择文本(web/Electron 走真实焦点 + Ctrl+A) |
drag |
真实鼠标拖拽 |
turn_ended |
结束 Computer Use turn、隐藏 overlay、清除 Escape 状态 |
有了这些 工具,可以完成大量的电脑操作任务。
当然,为了让自己的 Agent 和 DeepSeek 去调用这个插件,其实并没有想象的那么轻松,还是又遇到了不少波折。下面我就分享一下踩坑经验吧。成功的结果并没有太大意义,犯过的错误才是让我们进步的关键。
踩坑记录
当我知道KimiCU支持第三方调用的时候,首先是尝试了它明确支持的 ChatGPT(Codex)。
非常顺利:

Codex 做这种活还是非常优雅的。首先通过几个工具的调用确认这个插件已经可用。
已验证:
- 列出桌面应用和窗口:成功,约 0.05 秒返回
- 读取指定窗口状态及中文内容:成功
- 恢复并激活最小化窗口:成功
- 截取指定窗口画面:成功
- 切回 ChatGPT 并关闭控制浮层:成功
然后快速实现了调用计算器的任务,一切都非常顺利。
本来想试一下 Claude Code,但是我的配额已经用完了!
所以我就直接拿自己的 JClaude(有一个版本叫 Cowork 哈哈)来尝试了。
模型是直接选择了 DeepSeek V4 Flash!

为什么要搞这个呢?因为 Codex 和 Claude 它们家的工具和模型,本身就自带电脑操作功能,而且非常强大,并不需要第三方的电脑控制。只有我们自己做的 Agent 和配置第三方模型才需要自己解决电脑控制的问题。
而我这个 JClaude 其实就是套壳了 Claude Code,所以理论也算是在默认支持范围之内,跑起来应该问题不大。
我就把这个配置信息给了它:
makefile
将下面的 MCP Server 加入你的 Agent:
Name: kimi-cu
Type: stdio
Command: C:\Users\tony\AppData\Local\KimiCU\kimi-cu.exe
Args: mcp
JSON:
{
"mcpServers": {
"kimi-cu": {
"args": [
"mcp"
],
"command": "C:\Users\tony\AppData\Local\KimiCU\kimi-cu.exe",
"type": "stdio"
}
}
}
安装非常顺利,基础检查也全部过了。
但是当我尝试让它实现类似的 9 x 9 计算器操作的时候却卡住了。
一卡住,就分析了很久。还好最后 Flash 自己探索出了解决之道。
然后我把整个分析排查过,解决方案,使用教程大家分享一下。
1. 背景:问题是什么
kimi-cu (Kimi Computer Use for Windows)是 Moonshot 出的 Windows 桌面控制 runtime: 通过 MCP 暴露工具,让 AI 能"看"(截图 + UI Automation 树)并"操作"(真实鼠标/键盘)本地 Windows 应用。
插件是薄壳,真正干活的是本地 runtime:
r
`%LOCALAPPDATA%\KimiCU\kimi-cu.exe`
现象:
kimi-cu MCP 装好了、runtime 也健康,但 Claude Code 会话里只加载 9 个工具,缺 4 个 :activate_window、get_app_state、click、scroll。
致命影响:
缺的 get_app_state 是整套工具链的观察入口 。它截图 + 抓无障碍树 + 产出 snapshot_id,其余操作工具(click/type_text/press_key 等)全都强制要求传 snapshot_id。没有它,"观察 → 操作"的标准流程根本启动不了。
2. 根因
kimi-cu 的 4 个工具在 inputSchema 顶层用了 JSON Schema 的 oneOf 组合关键字,而 Anthropic 系客户端不支持工具 schema 顶层出现 oneOf/anyOf/allOf,加载时会静默跳过这些工具。
| 工具 | inputSchema 顶层结构 | Claude Code 是否加载 |
|---|---|---|
activate_window |
oneOf(pid/app/window_id 三选一) |
❌ |
get_app_state |
oneOf(pid/app/window_id 三选一) |
❌ |
click |
oneOf(index / x,y 二选一,含 not/anyOf) |
❌ |
scroll |
oneOf(index / x,y 二选一,含 not/anyOf) |
❌ |
| 其余 9 个 | 顶层无组合器,普通 object | ✅ |
这不是配置问题、不是 runtime 问题、更不是"第三方调用(Cowork)"的问题。
3. 排查方法论(三层对账 + 逐层排除)
这套方法适用于任何"MCP 工具没加载齐"的排查:
① 三层对账
- 插件 manifest 声明的工具白名单(
kimi.plugin.json的enabledTools) - MCP server 实际 声明的工具:用 Python 直接对
kimi-cu.exe mcp发 JSON-RPCtools/list - 客户端会话实际 加载的工具:看会话里
mcp__<server>__*工具数量
② 逐层排除
- 换不同
clientInfo身份(claude-code/cowork-desktop/kimi/inspect)→ server 返回都是 13 个 → 排除 server 按客户端裁剪 - 用不经过宿主(Cowork)的系统独立 Claude CLI 连接 → 还是 9 个 → 排除宿主过滤,锁定 Claude Code 本身
- 导出全部工具的完整
inputSchema逐一对比 → 发现"被跳过 = 顶层有 oneOf"的规律(天然的对照组:type_text/select_text也是"index 或坐标二选一",但没用 oneOf,就正常加载了) - 上网核实 → 确认是 Anthropic API / Claude Code 对顶层组合器的已知限制
牛逼,它还上网核实一下!
我对 DeepSeek 是并没有太高期望的,没想到这个问题被它自己探索出来了,其实我同事也在问 K3 和 GPT 5.6,它们也指出了类似的方向。
4. 解决方案:本地 MCP 代理
核心思路:
在 Claude Code 与 kimi-cu.exe mcp 之间插一层薄代理,只改写 tools/list 响应,把 4 个工具的 oneOf 剥掉。对客户端完全透明,不动 kimi-cu 本体。
css
Claude Code ⇄ proxy.js(Node stdio)⇄ kimi-cu.exe mcp
4.1 原理
- 双向透传 所有 JSON-RPC 消息(
initialize/tools/call/ 通知) - 只拦截
tools/list响应 :按请求 id 匹配响应,对每个工具剥掉inputSchema顶层的oneOf/anyOf/allOf/not,补type:"object",其余字段原样保留 - 后端
kimi-cu.exe路径由代理自己的config.json管理(不依赖官方插件包) - 可选工具过滤:
enabledTools/disabledTools
4.2 目录结构
arduino
C:\Users\tony.cowork\mcp\kimi-cu-proxy\
├── proxy.js 代理主程序(Node.js,零依赖)
├── config.json 配置(后端路径、工具过滤)
├── test-proxy.py 自检脚本
└── README.md
4.3 proxy.js
javascript
#!/usr/bin/env node
'use strict';
const { spawn } = require('child_process');
const fs = require('fs');
const os = require('os');
const path = require('path');
const readline = require('readline');
const PROXY_DIR = __dirname;
let config = {};
try {
config = JSON.parse(fs.readFileSync(path.join(PROXY_DIR, 'config.json'), 'utf8'));
} catch (e) { /* 按默认处理 */ }
function resolveBackendExe() {
const localAppData =
process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
if (config.exePath && typeof config.exePath === 'string' && config.exePath.trim()) {
return config.exePath.trim();
}
if (process.env.KIMI_CU_WINDOWS_EXE && process.env.KIMI_CU_WINDOWS_EXE.trim()) {
return process.env.KIMI_CU_WINDOWS_EXE.trim();
}
return path.join(localAppData, 'KimiCU', 'kimi-cu.exe');
}
function applyToolFilter(tools) {
const enabled =
Array.isArray(config.enabledTools) && config.enabledTools.length ? config.enabledTools : null;
const disabled =
Array.isArray(config.disabledTools) && config.disabledTools.length
? new Set(config.disabledTools) : null;
return (tools || []).filter((t) => {
if (enabled && !enabled.includes(t.name)) return false;
if (disabled && disabled.has(t.name)) return false;
return true;
});
}
// 剥掉 inputSchema 顶层的组合器,让 Claude Code 能加载
function sanitizeSchema(schema) {
if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return schema;
const out = { ...schema };
for (const key of ['oneOf', 'anyOf', 'allOf', 'not']) {
if (Object.prototype.hasOwnProperty.call(out, key)) {
const note = `(原 schema 顶层含 ${key},为兼容 Claude Code 已剥离)`;
out.description = out.description ? `${out.description} ${note}` : note;
delete out[key];
}
}
if (!out.type) out.type = 'object';
if (out.properties === undefined) out.properties = {};
if (out.additionalProperties === undefined) out.additionalProperties = false;
return out;
}
function rewriteToolsResult(msg) {
if (msg.result && Array.isArray(msg.result.tools)) {
msg.result.tools = applyToolFilter(msg.result.tools).map((t) => ({
...t,
inputSchema: sanitizeSchema(t.inputSchema),
}));
}
return msg;
}
const backendExe = resolveBackendExe();
const child = spawn(backendExe, ['mcp'], { stdio: ['pipe', 'pipe', 'inherit'] });
child.on('error', (err) => {
process.stderr.write(`[kimi-cu-proxy] 无法启动后端 ${backendExe}: ${err.message}\n`);
process.exit(1);
});
const toolsListIds = new Set();
readline
.createInterface({ input: process.stdin })
.on('line', (line) => {
if (!line.trim()) return;
let msg;
try { msg = JSON.parse(line); } catch (e) { return; }
if (msg.method === 'tools/list') toolsListIds.add(msg.id);
child.stdin.write(line + '\n');
});
readline
.createInterface({ input: child.stdout })
.on('line', (line) => {
if (!line.trim()) return;
let msg;
try { msg = JSON.parse(line); } catch (e) {
process.stderr.write(`[kimi-cu-proxy] 忽略非 JSON 行: ${line.slice(0, 120)}\n`);
return;
}
if (msg.id !== undefined && toolsListIds.has(msg.id)) {
toolsListIds.delete(msg.id);
msg = rewriteToolsResult(msg);
}
process.stdout.write(JSON.stringify(msg) + '\n');
});
child.on('exit', (code) => process.exit(code || 0));
process.on('exit', () => { try { child.kill(); } catch (e) {} });
process.on('SIGINT', () => process.exit(0));
process.on('SIGTERM', () => process.exit(0));
4.4 config.json
json
{
"exePath": "",
"enabledTools": [],
"disabledTools": []
}
| 字段 | 说明 |
|---|---|
exePath |
后端 kimi-cu.exe 路径。留空依次回退环境变量 KIMI_CU_WINDOWS_EXE → 官方默认 %LOCALAPPDATA%\KimiCU\kimi-cu.exe |
enabledTools |
非空时只暴露列出的工具(默认空 = 全部 13 个) |
disabledTools |
非空时剔除列出的工具(默认空 = 不过滤) |
4.5 注册配置
改 Claude Code 的 MCP 配置。如果改 Claude Code 官方版,就修改用户级 ~/.claude.json。如果修改我们自己的 Agent,就修改 .cowork/.claude.json 里的 mcpServers.kimi-cu:
swift
"kimi-cu": {
"type": "stdio",
"command": "C:\Program Files\nodejs\node.exe",
"args": ["C:\Users\tony\.cowork\mcp\kimi-cu-proxy\proxy.js"]
}
5. 验证
简单代理 MCP 已经写完,接下来就验证一下我们的操作实例了。
5.1 计算器 9 × 9
launch_app("calc.exe")打开计算器list_apps定位计算器窗口(ApplicationFrameHost 下 title="计算器")get_app_state(window_id, mode="full")→snapshot_id+ 无障碍树- 用正则从树里解析按钮中心坐标:
按钮 name="九" class="Button" rect=x,y w x h→ 中心(x+w/2, y+h/2) - 依次
click(snapshot_id, x, y):清除 → 九 → 乘以 → 九 → 等于 get_app_state(mode="text")读到 "显示为 81"- 收尾
turn_ended结束调用状态(隐藏 overlay,不杀进程)
关键坑:
press_key不支持*字符(报unsupported key: *),所以乘法要用 click 点"乘以"按钮,不能靠键盘输入。
5.2 Chrome 搜索 DeepSeek
activate_window(chrome窗口)激活(若最小化,先激活再观察,否则mode="full"会报 "target window is minimized")get_app_state(mode="full")→snapshot_id+ 树,解析地址栏的中心坐标click地址栏(真实鼠标,触发 overlay)→ 输入内容type_text(snapshot_id, x, y, text, clear=true)→ 输入回车press_key "Enter"- 等加载后
get_app_state(mode="text")从visible_text提取结果
5.3 收尾惯例
每次操作完必须调用 turn_ended 结束 Computer Use turn 并隐藏 overlay------不是杀进程 。 然后用 p.stdin.close() 让 MCP 连接优雅退出(server 检测到 EOF 自动退出)。
6. 坑与细节清单
- MCP stdio 是"换行分隔 JSON-RPC":每行一个 JSON 对象
- 测试代理不能
printf | node proxy.js:代理是常驻进程(要转发子进程),管道等不到 EOF 会挂起;用 Pythonsubprocess+ 线程读 + 按 id 匹配响应,最后显式关闭 get_app_state三种 mode 的区别:full(截图 + ax)、image(仅截图)、ax(仅 UIA 树,无截图)、text(仅可见文本,最轻)。click的坐标必须是带截图的 snapshot(full/image)的screenshot_pixels;用ax的坐标可能坐标系统不对(报 out of bounds)- 窗口最小化时
full/image报错 "target window is minimized before get_app_state screenshot",先activate_window再重试一次 - Git Bash 的路径转换坑:
taskkill /F /IM kimi-cu.exe会把/F转成F:/,需加MSYS_NO_PATHCONV=1前缀或用 PowerShell - Windows 控制台编码:Python 打印 UTF-8 中文乱码,用
PYTHONIOENCODING=utf-8 kimi-cu进程构成:主 agent(常驻,stop-agent停)、overlay 窗口进程、每个 MCP 连接一个kimi-cu.exe mcp实例。退出要分层处理skipSchemaValidation: true只绕过本地校验,Anthropic API 层仍拒;治本是把 oneOf 从 server schema 里去掉
7. 全新系统从零部署(step-by-step)
7.1 系统要求
- Windows 10 1903+ / Windows 11,x64;Windows Server 需 Desktop Experience + 交互式会话
- 目标应用以管理员权限运行时,kimi-cu agent 也需同级权限(UIPI 限制)
7.2 安装 kimi-cu runtime
bash
# PowerShell 一键安装
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Invoke-RestMethod 'https://cdn.kimi.com/kimi-computer-use-windows/latest/setup_windows.ps1' | Invoke-Expression"
安装后默认在 %LOCALAPPDATA%\KimiCU\kimi-cu.exe,并自动在后台启动 agent、注册开机自启。 验证:
arduino
"$LOCALAPPDATA/KimiCU/kimi-cu.exe" doctor
# 期望输出含 mcp=true、helper=embedded、agent.running=true
7.3 部署本地 MCP 代理
- 建目录:
<HOME>.cowork\mcp\kimi-cu-proxy - 把 4.3 的
proxy.js、4.4 的config.json、README 放进去 - 确认本机 Node 可用:
node --version(Claude Code 自带 Node;若用独立安装,注意command里写对 node.exe 绝对路径)
7.4 配置 Claude Code 指向代理
编辑 Claude Code 的 MCP 配置,把 kimi-cu 指向代理:
json
"kimi-cu": {
"type": "stdio",
"command": "<node.exe 绝对路径>",
"args": ["<代理 proxy.js 绝对路径>"]
}
备份原配置再改,改完后新会话生效!
其实核心问题就一句话:不兼容。第二句话是:搞个 MCP 做兼容!!
一旦配置好之后,以后就不用管了,直接让它做就可以了!我这次遇到的问题,主要是因为我用了 Claude Code 的缘故,如果你的智能体不是 CC,估计就不会遇到这个问题了,应该会简单很多。
中间部分是让 DS 自己做总结,对普通人阅读文章可能不是太友好,但是细节非常清晰,有很高的实用价值。
工具模型就是那些,以后就是要不断的提升使用技巧了。
另外再说一个很有意思的现象。Kimi 的这个插件,K3 自己调用的时候,出现了调用完成之后不退出调用状态的现象,就是电脑屏幕一直显示"正在使用电脑"。
DeepSeek 也出现了这个问题,而 Codex(GPT 5.6)却做得非常好,第一次接触这个工具,做完之后收得非常干净。
DeepSeek还出现一个问题,他居然说Kimi-cu.exe的签名是
幻方量化科技股份有限公司(Moonshot AI 母公司),DigiCert 时间戳有效------官方文件,不是第三方伪造。
懂得兄弟应该发现问题了。
它把两家公司搞混了,它把自己的母公司搞成了Kimi的母公司。问题是它还言之凿凿说这不是第三方伪造。 经过我的质疑,它坦白,它读取到的签名是乱码,然后直接乱编了一个...!
看不懂,就乱编一个~~哈哈!
D哥,你这么做事情不太行吧!