给Claude Code配上DeepSeek,调用kimicu控制电脑

题接上一篇《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-cuKimi 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_windowget_app_stateclickscroll

致命影响

缺的 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.jsonenabledTools
  • MCP server 实际 声明的工具:用 Python 直接对 kimi-cu.exe mcp 发 JSON-RPC tools/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

  1. launch_app("calc.exe") 打开计算器
  2. list_apps 定位计算器窗口(ApplicationFrameHost 下 title="计算器")
  3. get_app_state(window_id, mode="full")snapshot_id + 无障碍树
  4. 用正则从树里解析按钮中心坐标:按钮 name="九" class="Button" rect=x,y w x h → 中心 (x+w/2, y+h/2)
  5. 依次 click(snapshot_id, x, y):清除 → 九 → 乘以 → 九 → 等于
  6. get_app_state(mode="text") 读到 "显示为 81"
  7. 收尾 turn_ended 结束调用状态(隐藏 overlay,不杀进程)

关键坑:press_key 不支持 * 字符(报 unsupported key: *),所以乘法要用 click 点"乘以"按钮,不能靠键盘输入。

5.2 Chrome 搜索 DeepSeek

  1. activate_window(chrome窗口) 激活(若最小化,先激活再观察,否则 mode="full" 会报 "target window is minimized")
  2. get_app_state(mode="full")snapshot_id + 树,解析地址栏的中心坐标
  3. click 地址栏(真实鼠标,触发 overlay)→ 输入内容 type_text(snapshot_id, x, y, text, clear=true) → 输入回车 press_key "Enter"
  4. 等加载后 get_app_state(mode="text")visible_text 提取结果

5.3 收尾惯例

每次操作完必须调用 turn_ended 结束 Computer Use turn 并隐藏 overlay------不是杀进程 。 然后用 p.stdin.close() 让 MCP 连接优雅退出(server 检测到 EOF 自动退出)。

6. 坑与细节清单

  1. MCP stdio 是"换行分隔 JSON-RPC":每行一个 JSON 对象
  2. 测试代理不能 printf | node proxy.js :代理是常驻进程(要转发子进程),管道等不到 EOF 会挂起;用 Python subprocess + 线程读 + 按 id 匹配响应,最后显式关闭
  3. get_app_state 三种 mode 的区别:full(截图 + ax)、image(仅截图)、ax(仅 UIA 树,无截图)、text(仅可见文本,最轻)。click 的坐标必须是带截图的 snapshot(full/image)的 screenshot_pixels;用 ax 的坐标可能坐标系统不对(报 out of bounds)
  4. 窗口最小化时 full/image 报错 "target window is minimized before get_app_state screenshot",先 activate_window 再重试一次
  5. Git Bash 的路径转换坑:taskkill /F /IM kimi-cu.exe 会把 /F 转成 F:/,需加 MSYS_NO_PATHCONV=1 前缀或用 PowerShell
  6. Windows 控制台编码:Python 打印 UTF-8 中文乱码,用 PYTHONIOENCODING=utf-8
  7. kimi-cu 进程构成:主 agent(常驻,stop-agent 停)、overlay 窗口进程、每个 MCP 连接一个 kimi-cu.exe mcp 实例。退出要分层处理
  8. 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 代理

  1. 建目录:<HOME>.cowork\mcp\kimi-cu-proxy
  2. 4.3 的 proxy.js4.4 的 config.json、README 放进去
  3. 确认本机 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哥,你这么做事情不太行吧!

相关推荐
小当家.1052 小时前
深入理解 ReAct Agent:从原理到 Java 实战
java·react.js·agent·react·架构设计·agent设计
阿里云云原生2 小时前
从创建到发布:一套基于 AgentLoop 的 AI Agent Skill 持续调优工程链路
agent
geminigoth2 小时前
Spring AI Alibaba 入门开发一(备份)
java·人工智能·spring
DigitalOcean2 小时前
AI 应用成本怎么算?从推理费用到完整 TCO 拆解
llm·agent
liguochuan002 小时前
AI 写代码越来越快,为什么项目却越来越难维护?
人工智能
冬奇Lab2 小时前
代码库知识库系列(12):Git 历史是第四条检索路径
人工智能
空堂与归2 小时前
复杂推理总翻车、Prompt 被注入怎么办?六种进阶技术从 CoT 到 ReAct 实战全解析
人工智能
u0102789402 小时前
GPT 与 Gemini:综合能力与场景适配性测评
人工智能
lucas_AI2 小时前
Q-CueGraph:你的多模态大模型会 zoom,但真的知道该看哪儿吗?
人工智能·算法