Skip to content

第23课 · 用 MCP 让任何 AI 都能看图

给 AI 接上一个识图插座:小黑把 vision 插头插进 MCP 万能插座

本节要点

  • 承接第 22 课:上一节用「observer 子代理」给 DeepSeek 加识图能力,但那依赖 oh-my-opencode-slim 插件
  • 本节讲一个更通用的办法:配置一个 Vision MCP,任何支持 MCP 的 AI 工具(Claude Code、OpenCode)都能用,Windows 和 Mac 都适用
  • 什么是 MCP?一句话:AI 的「万能插座」,工具做成 MCP 插头,任何 AI 即插即用
  • 一段现成指令:复制粘贴给 AI,它交互式问你三个问题,自动创建识图工具并注册
  • ⚠️ 无论 Claude Code 还是 OpenCode,装好 MCP 后都必须退出重启才能生效
  • 配好后,AI 遇到图片会自动调用 analyze_image 工具识别

1. 承接:为什么还要学第二种方式?

第 22 课我们讲了让 DeepSeek 能看图的第一种方式——给 oh-my-opencode-slim 插件配一个 observer 子代理。它能用,但有一个限制:依赖那个插件

这一节讲第二种方式:配置一个 Vision MCP。它的好处是更通用——

对比observer 子代理(第22课)Vision MCP(本课)
依赖必须装 oh-my-opencode-slim 插件不依赖任何插件
适用OpenCode / Claude Code(装了插件的)任何支持 MCP 的 AI 工具
模型要求视觉 且 支持 tool calling只要支持视觉

简单说,MCP 方案是「一次配置,到处通用」。


2. 先搞懂:MCP 是什么?

配置之前,先花一分钟搞懂 MCP 是什么。不懂也没关系,你可以直接跳到下一节复制指令——AI 会帮你搞定一切。但了解一下,对你以后用 AI 有帮助。

MCP = AI 的「万能插座」

想象你的电脑有各种各样的插头:USB、Type-C、老式圆孔……每个都不一样。如果你想给 AI 接一个新的外部工具(比如看图、查数据库、发邮件),以前得每个 AI 单独写一套对接代码,很麻烦。

MCP(Model Context Protocol,模型上下文协议)就是一个统一的「插座标准」。 只要工具做成 MCP 的插头,任何支持 MCP 的 AI 都能即插即用,不用重复开发。

💡 你不用学 MCP 的细节。你只需要知道:有这么个东西,AI 能帮我们写 MCP、配 MCP。我们告诉它「我要一个能识图的 MCP」,它就帮我们做好插头、插上插座。这也是用 AI 的一个重要思路——不用啥都会,知道有啥、会让 AI 帮你做就行

不懂就问 AI

如果你看完还是不太理解,直接问 AI。在 Claude Code 里有个特别好用的命令 /btw(by the way 的缩写),可以不打断主会话地问 AI 一个问题:

在 Claude Code 里输入:/btw 请用通俗易懂的语言给我介绍一下什么是 MCP

它会在旁边给你解释,不会打断它正在干的主活儿。问完按左上角 Esc 键就回到主会话。

AI 是你最好的老师

你不会的概念、不懂的报错、想了解的工具,都可以直接问 AI。这比百度搜出来的垃圾信息靠谱多了。


3. 准备:一个支持视觉的 API Key

和第 22 课一样,你需要一个支持看图的模型 API Key。推荐用你平时在用的平台(任意一个):

  • 阿里云百炼(上一节用的,有 qwen-vl 系列视觉模型)
  • 硅基流动(聚合多个开源模型,便宜)
  • 其他有多模态模型的平台都行

如果你第 22 课已经申请过阿里云百炼的 API Key,直接复用那个就行,不用重新申请。还没申请的,回第22课第4节看流程。


4. 核心:复制这段指令,粘贴给 AI

这是本课的重头戏。把下面整段指令复制,粘贴给你正在用的 OpenCode 或 Claude Code 会话。

它会像安装向导一样,问你三个问题,然后自动帮你:创建识图工具 → 注册到你的 AI 工具 → 让你测试。

markdown
# 任务:配置一个 Vision MCP(让 AI 能看图)

## 背景
主模型不支持图片(如 DeepSeek)。配置一个本地 Vision MCP server,提供 `analyze_image` 工具:它把图片发给视觉模型,拿到文字描述返回给主模型。配好后这个 AI 工具就具备看图能力,任何支持 MCP 的工具都能用。

## 硬性要求(配错就跑不起来)
1. **Node.js ≥ 18**(推荐 20+),先检测,不够就停下来让我升级
2. `package.json` 必须有 `"type": "module"`——MCP SDK 只支持 ESM
3. `index.js` 里 import SDK 的路径必须带 `.js` 后缀
4. 视觉模型只需支持「图像输入」即可
5. **Claude Code 和 OpenCode 的 MCP 配置字段格式不同,不能混用**(见 Step 5)

## 执行步骤

### Step 1:向我确认三件事
-**哪个 AI 工具**里用?(Claude Code / OpenCode / 两个都要)
- 视觉模型用**哪家服务商**?(阿里云百炼 / 硅基流动 / OpenAI / 智谱 / 其他)
- **API Key** 是多少?

### Step 2:检测 OS + Node 版本
- 检测 OS(Mac/Linux 用 `bash`+`curl`;Windows 用 PowerShell+`Invoke-RestMethod`
-`node -v`,低于 18 就停下来让我先升级
- 确定 MCP server 存放路径:
  - Mac/Linux:`~/.vision-mcp/`
  - Windows:`%USERPROFILE%\.vision-mcp\`

### Step 3:拉取服务商模型列表,选最新的视觉模型
**(a)** 用 API Key 请求 `{baseURL}/models`(带 `Authorization: Bearer {apiKey}`)。各 baseURL:
- 阿里云百炼:`https://dashscope.aliyuncs.com/compatible-mode/v1`
- 硅基流动:`https://api.siliconflow.cn/v1`
- 智谱:`https://open.bigmodel.cn/api/paas/v4`
- OpenAI:`https://api.openai.com/v1`

```bash
# Mac / Linux
curl -s "{baseURL}/models" -H "Authorization: Bearer {apiKey}"
```
```powershell
# Windows PowerShell
Invoke-RestMethod -Uri "{baseURL}/models" -Headers @{Authorization="Bearer {apiKey}"}
```

**(b)** 筛名字含 `vl`/`vision`/`vlm`/`4o`/`llava` 的模型,排除纯文本/embedding/tts。

**(c)** **查官方文档**确认候选支持「图像输入」:
- 阿里云百炼:`https://help.aliyun.com/zh/model-studio/getting-started/models`
- 硅基流动:`https://docs.siliconflow.cn/cn/userguide/capabilities/multimodal-vision`
- 智谱:`https://open.bigmodel.cn/dev/howuse/model`

**(d)****版本最新、参数量较大**的(如 `qwen3-vl` > `qwen2.5-vl``-max`/`-plus` 优先于 `-flash`/`-lite`)。把选择和依据告诉我。⚠️ 没有视觉模型就停下来让我换服务商。

### Step 4:创建 MCP server

**(a)** 创建 Step 2 的目录,进入它。

**(b)** 写入 `package.json`
```json
{
  "name": "vision-mcp-server",
  "version": "1.0.0",
  "type": "module",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.29.0",
    "zod": "^3.23.0"
  }
}
```

**(c)** 写入 `index.js`(完整代码,直接写入,API Key/模型/地址都走环境变量):
```javascript
#!/usr/bin/env node

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
import fs from 'fs';
import path from 'path';

const API_KEY = process.env.VISION_API_KEY;
const BASE_URL = process.env.VISION_BASE_URL;
const MODEL = process.env.VISION_MODEL;

if (!API_KEY || !BASE_URL || !MODEL) {
  console.error('缺少环境变量 VISION_API_KEY / VISION_BASE_URL / VISION_MODEL');
  process.exit(1);
}

const MIME = {
  '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',
  '.gif': 'image/gif', '.webp': 'image/webp', '.bmp': 'image/bmp',
};

const server = new McpServer({ name: 'vision-server', version: '1.0.0' });

server.tool(
  'analyze_image',
  '分析图片内容并返回文字描述。支持本地文件路径或图片URL。',
  {
    image_url: z.string().describe('图片的本地路径或URL,如 /Users/x/photo.png 或 https://example.com/a.jpg'),
    prompt: z.string().optional().describe('想问的问题,如"识别图中的文字"。不填则默认描述整张图'),
  },
  async ({ image_url, prompt }) => {
    const question = prompt || '请详细描述这张图片的内容。';
    try {
      let url = image_url;
      // 本地文件 → base64 data URL
      if (!url.startsWith('http') && !url.startsWith('data:')) {
        const fp = path.resolve(url);
        if (!fs.existsSync(fp)) {
          return { content: [{ type: 'text', text: `文件不存在: ${fp}` }] };
        }
        const mime = MIME[path.extname(fp).toLowerCase()] || 'image/png';
        url = `data:${mime};base64,${fs.readFileSync(fp).toString('base64')}`;
      }
      // 调用视觉模型 API
      const res = await fetch(`${BASE_URL}/chat/completions`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${API_KEY}` },
        body: JSON.stringify({
          model: MODEL,
          messages: [{
            role: 'user',
            content: [
              { type: 'image_url', image_url: { url } },
              { type: 'text', text: question },
            ],
          }],
          max_tokens: 2000,
        }),
      });
      if (!res.ok) {
        return { content: [{ type: 'text', text: `API错误(${res.status}): ${await res.text()}` }] };
      }
      const data = await res.json();
      const text = data.choices?.[0]?.message?.content || '模型未返回内容';
      return { content: [{ type: 'text', text }] };
    } catch (e) {
      return { content: [{ type: 'text', text: `出错: ${e.message}` }] };
    }
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);
```

**(d)** `npm install`,然后跑 `node index.js`——不报错、不退出(挂着)就说明正常,`Ctrl+C` 停掉。

### Step 5:注册到 AI 工具(字段格式不同,别抄混)

准备四个值:`INDEX_PATH`(index.js 绝对路径,Windows 在 JSON 里用 `\\``/`)、`VISION_API_KEY``VISION_BASE_URL``VISION_MODEL`

#### 情况 A:Claude Code
用命令注册(用户级,全局可用,JSON 用单引号包裹):
```bash
claude mcp add-json --scope user vision '{"type":"stdio","command":"node","args":["INDEX_PATH"],"env":{"VISION_API_KEY":"你的key","VISION_BASE_URL":"你的baseURL","VISION_MODEL":"你的模型ID"}}'
```
报错就退回:在项目根目录创建 `.mcp.json`,内容同下表 Claude Code 列。

#### 情况 B:OpenCode
没有 CLI 命令,编辑配置文件(Mac/Linux `~/.config/opencode/opencode.json`;Windows `%USERPROFILE%\.config\opencode\opencode.json`),在 `mcp` 字段加入:
```jsonc
{
  "mcp": {
    "vision": {
      "type": "local",
      "command": ["node", "INDEX_PATH"],
      "enabled": true,
      "environment": {
        "VISION_API_KEY": "你的key",
        "VISION_BASE_URL": "你的baseURL",
        "VISION_MODEL": "你的模型ID"
      }
    }
  }
}
```

#### 字段差异对照(最易出错)
| 字段 | Claude Code | OpenCode |
|------|------------|----------|
| 类型 | `"type": "stdio"` | `"type": "local"` |
| 命令 | `"command":"node"` + `"args":["路径"]` 分开 | `"command":["node","路径"]` 合并 |
| 环境变量 | `"env"` | `"environment"` |
| 启用 | 默认启用 | 必须 `"enabled": true` |

两个工具都要的话,A 和 B 都做一遍。

### Step 6:测试
- 重启工具(配置改动要重启生效),会话里 `/mcp` 确认 vision 已连接
- 让我准备一张测试图(Mac/Linux `/tmp/test.png`;Windows `$env:TEMP\test.png`),然后对 AI 说:
  ```
  用 analyze_image 工具分析这张图片:<图片路径>
  ```
- 成功标志:AI 调用了 analyze_image 工具,返回了图片描述

### Step 7:排查(失败时按顺序检查)
1. `node -v` ≥ 18?
2. `package.json``"type": "module"`?(报 `require` 错就是没有)
3. `node index.js` 能启动?(看 import 路径是否带 `.js`、依赖装好没)
4. 报「缺少环境变量」?→ env/environment 没写对
5. `/mcp` 里没有 vision?→ 字段格式错了,对照上面差异表(多半是 Claude/OpenCode 抄混了)
6. 返回「API错误 401」?→ Key 错或过期
7. 返回其他 API 错误?→ 模型 ID 拼错或不支持图像,回 Step 3

## 完成后报告给我
- OS、Node 版本、MCP server 路径
- 选了哪个视觉模型、为什么
- 注册到哪个工具、配置片段(key 打码)
- 测试是否通过、AI 有没有调用 analyze_image、描述准不准
- 给我一个以后让 AI 看图的使用示例

它会怎么引导你

把指令发出去后,它会问你三个问题,你照着回答就行:

  1. 「在哪个 AI 工具里用?」 → OpenCode / Claude Code / 两个都要
  2. 「视觉模型用哪家服务商?」 → 比如「阿里云百炼」
  3. 「API Key 是多少?」 → 把你申请的 key 粘贴给它

然后它会自动去拉取这家服务商有哪些模型、判断哪些是多模态的、创建识图工具、注册到你的 AI 工具。

想更快?直接告诉它用哪个模型

它会联网去查哪个模型合适,这一步要花一两分钟。如果你已经知道用哪个多模态模型(比如阿里云百炼的 qwen-vl-max),回答时直接说:

「阿里云百炼,用 qwen-vl-max,API Key 是 sk-xxx」

它就跳过联网查询,直接配置,几秒钟搞定。


5. 配置过程的小技巧

配置时 AI 会跑一堆命令(装依赖、写文件、注册),这几个技巧能让你看得更清楚、更省心:

OpenCode:打开「自动接受权限」和「显示思考」

OpenCode 每执行一个命令都会问你要不要允许,点多了很烦。打开设置:

  1. 点 OpenCode 的设置(齿轮图标)
  2. 找到**「自动接受权限」**,打开——命令就不用每次确认了
  3. 找到**「显示推理摘要 / 显示思考」**,打开——你能看到 AI 的思考过程,知道它在干嘛,不会干等

Claude Code:用 /btw 不打断主会话问问题

Claude Code 有个特别好用的命令 /btw(by the way)。配置要等一会儿,你想问它「进度怎么样」「MCP 是什么」,又不想打断它正在干的活,就:

输入 /btw 现在进度怎么样了?

它会在旁边回答你,不影响主进程。问完按左上角 Esc 键回到主会话。

终端粘贴图片:Mac 也是 Ctrl+V

测试识图时要往终端里粘贴图片。注意一个坑:

  • 不管你是 Mac 还是 Windows,在终端里粘贴都是按 Ctrl + V
  • Mac 用户千万别按 Cmd + V(那是系统级的粘贴,在终端里不一定管用)

这个很多人第一次会按错。


6. ⚠️ 装好后必须重启才能生效

这一步特别重要,很多人配完不重启,直接测试,发现「怎么没生效」——其实配置没问题,只是没重启。

无论你用的是 Claude Code 还是 OpenCode

MCP 配置完成后,必须把 AI 工具完全退出再重新打开,新装的 MCP 才会被加载。直接在原来的会话里测试是测不出来的。

  • OpenCode:关掉窗口重新启动
  • Claude Code:退出(/exit 或关掉终端)重新进入

重启后,在会话里输入 /mcp,你应该能看到列表里多了一个 vision——说明加载成功了。


7. 测试:让 DeepSeek 看图

重启确认 vision 出现在 MCP 列表后,新开一个会话测试:

  1. 随便截一张图(或复制一张网上的图)
  2. 在终端里用 Ctrl + V(Mac 也是)粘贴给 AI
  3. 让它「识别一下图片内容」

如果配置成功,你会看到:DeepSeek(依然是那个便宜的文本模型)遇到图片后,会自动调用 analyze_image 这个 MCP 工具去识别,然后把图片内容告诉你。

💡 怎么确认它真的用了 MCP? 看它的执行过程,会出现「调用 analyze_image 工具」这样的字样。说明它不是靠主模型自己看的(它看不了),而是把图交给了你配的识图工具。


8. 如果你同时配了 observer 子代理

如果你第 22 课也配了 observer 子代理,这里有个小情况要知道:

测试识图时,AI 可能会先尝试调用 observer 子代理(因为上一节课配过)。如果你这台电脑没配好 observer,或者你想只用 MCP 这一种方式,可以把 observer 禁用掉:

  • 在 oh-my-opencode-slim 配置里,把 observer 加回 disabled_agents
  • 或者直接告诉 AI:「把 observer 子代理禁用,我只想用 MCP 识图」

这样 AI 遇到图片就只会调用 MCP 的 analyze_image,不会再去试 observer。

💡 两种方式选一个就行:observer 子代理(第22课)和 Vision MCP(本课)都能让 DeepSeek 看图,没必要两个都开。建议用本课的 MCP 方式,更通用。


9. 三种方式总结

到这里,让 DeepSeek(或其他纯文本模型)能看图,我们已经讲了三种方式

方式做法适用推荐度
① 直接用多模态模型把主模型换成支持看图的(如智谱 GLM、Kimi 等)任何工具⭐⭐⭐ 最省事,原生支持
② observer 子代理给 oh-my-opencode-slim 配一个识图子代理(第22课)装了该插件的⭐⭐ 受插件限制
③ Vision MCP(本课)配一个识图 MCP 工具,任何 AI 都能用任何支持 MCP 的工具⭐⭐⭐ 最通用

💡 如果预算允许,最推荐的还是方式 ①——直接用多模态模型,它原生就能看图,最省心。方式 ② 和 ③ 是给「想继续用便宜的 DeepSeek」的人准备的补救方案。


10. 常见问题与避坑

10.1 MCP 装好了,但粘贴图片不生效?

这是群里高频问题。Vision MCP 设计的入口是图片路径或 URL,不是直接拖图片附件。

如果粘贴图片后 AI 没调用 analyze_image,最稳妥的做法是:

  1. 把图片保存到本地,比如 /tmp/test.png(Mac/Linux)或 $env:TEMP\test.png(Windows)
  2. 对 AI 说:「用 analyze_image 工具分析这张图片:/tmp/test.png

💡 多模态模型(如 Kimi、GLM)通常可以直接粘贴图片;但 DeepSeek + MCP 识图时,给路径是最稳的,避免 opencode 丢弃附件。

10.2 /mcp 里看不到 vision?

如果重启后输入 /mcp 没有 vision,按这个顺序排查:

  1. 真的重启了吗? 不是关标签页,是完全退出 AI 工具再重开
  2. 字段格式错了吗? Claude Code 用 "type":"stdio" + "args",OpenCode 用 "type":"local" + "command",别混用
  3. node index.js 能单独跑起来吗? 不能的话看报错:Node 版本不够、package.json"type":"module"、import 路径没写 .js
  4. 路径写对了吗? Windows 路径在 JSON 里用 \\/

10.3 阿里云百炼 vs 硅基流动,哪个更好?

两家都能用,差异主要是:

对比阿里云百炼硅基流动
模型qwen-vl 系列,文档全开源模型多,选择多
价格按量,稳定通常更便宜
新手友好度更推荐需要自己会挑模型

建议新手先用阿里云百炼跑通,熟悉后再尝试硅基流动省钱。

群友验证的硅基流动模型

Zidi King 大二子弟 Ai 实测:硅基流动调用 Qwen3.5-397B 视觉模型,一天约 100 张图,月消费约 14 元,效果与课程方案相当。如果你在硅基流动里挑花了眼,可以先试试这个模型。

10.4 已经配了第22课的 observer,两个会冲突吗?

不会冲突,但可能「打架」——AI 遇到图片可能先尝试调 observer。如果你只想用 MCP:

  • 在 oh-my-opencode-slim 配置里把 observer 加回 disabled_agents
  • 或者直接告诉 AI:「禁用 observer 子代理,只用 MCP 识图」

两门课二选一即可,没必要两个都开。

10.5 识图「昨天能用,今天又不行」?

有群友反映:配好 vision MCP 当天测试正常,第二天又识别不了图片。这是个反复出现的坑。

根因:AI 有时会「自作聪明」——它觉得 read 工具也能读图片,就先调用了 read,而不是走你的 vision MCP,结果当然识别失败。换句话说,不是 MCP 配置坏了,而是 AI 没选择走 MCP 这条路

根治办法:把「读图任务都用 vision MCP 完成」这条规则写进全局 agents.md(不是项目级的,是全局的,这样每个项目都生效)。这样 AI 以后碰到图片就会老老实实走 MCP,不会再跑去用 read

💡 经验:配 MCP 这类「时好时坏」的问题,多半是 AI 没按你期望的路径走。需要每次重复提醒 AI 的规则,统一写进 agents.md,一次设定长期生效,不用每次再手动说一遍。

如果还是不行,就在对话里明确点名工具:「用 vision MCP 的 analyze_image 工具分析这张图:图片路径」,强制它走对路。


关键收获

TIP

让纯文本模型(如 DeepSeek)能看图,最通用的办法是配置一个 Vision MCP:复制本课第 4 节那段指令粘贴给 AI,它会问你三个问题(用哪个工具、哪家服务商、API Key),然后自动创建识图工具并注册。Claude Code 和 OpenCode 都能用,Windows 和 Mac 都适用。最关键的一点:配完一定要退出 AI 工具重新打开(重启),MCP 才会生效——不重启直接测试会以为没配成功。终端粘贴图片统一用 Ctrl+V(Mac 也是,别按 Cmd+V)。


更多课程:课程大纲

© 2025 逆行的狗