当前位置: 首页 > news >正文

解决 cc-connect + Claude Code 图片识别问题

解决 cc-connect + Claude Code 图片识别问题:一次完整的排查与修复之旅

背景

我使用 cc-connect 桥接飞书和本地 AI 编程代理 Claude Code,并配置了 mimo-media-recognition-mcp MCP 服务器用于图片/音频/视频分析。

架构如下:

飞书用户 → cc-connect → Claude Code → MIMO API(文本模型)↓MCP 服务器 → MIMO API(多模态模型,支持图片)
  • Claude Code 主模型mimo-v2.5-pro(仅支持文本)
  • MCP 模型mimo-v2-omni(支持图片、音频、视频)

期望的行为:通过飞书发图片 → Claude Code 调用 MCP 分析图片 → 返回分析结果

实际的行为:通过飞书发图片 → Claude Code 返回"无法看到图片" → MCP 从未被调用


第一步:确认 MCP 本身是正常的

首先验证 MCP 服务器能否独立工作:

MIMO_API_KEY="your-key" MIMO_API_BASE="https://your-api-base" MIMO_MODEL="mimo-v2-omni" \
python -c "
from mimo_media_recognition_mcp.server import understand_image
import asyncio
result = asyncio.run(understand_image(prompt='描述这张图片',image_path='/path/to/test.jpg'
))
print(result)
"

结果:正常返回图片描述。MCP 服务器没有问题。


第二步:分析 cc-connect 日志

启动 cc-connect 并通过飞书发送图片,观察日志:

cc-connect --force 2>&1 | tee cc-connect.log

关键日志:

feishu: downloaded image key=img_xxx size=120814 mime=image/jpeg
claudeSession: image saved path=/home/user/projects/.cc-connect/attachments/img_xxx.jpg size=120814
turn complete tools=0 response_len=173 input_tokens=0 output_tokens=0

注意两个关键信息:

  1. tools=0 — Claude Code 没有调用任何工具(包括 MCP)
  2. input_tokens=0 — API 调用的输入 token 为 0

这说明 Claude Code 根本没有发送 API 请求


第三步:定位根本原因

通过阅读 cc-connect 源码,找到了问题所在。

cc-connect 如何处理图片

cc-connect 有两个 agent 实现:

  • agent/acp/session.go — ACP 协议代理(用于 Cursor、Windsurf 等)
  • agent/claudecode/session.go — Claude Code 专用代理

Claude Code 代理的 Send 函数agent/claudecode/session.go 第 530-598 行):

func (cs *claudeSession) Send(prompt string, images []core.ImageAttachment, files []core.FileAttachment) error {// ...// 保存图片到磁盘for i, img := range images {fpath := filepath.Join(attachDir, fname)os.WriteFile(fpath, img.Data, 0o644)savedPaths = append(savedPaths, fpath)// ⚠️ 问题在这里!把图片编码为 base64 发送给 Claude Codeparts = append(parts, map[string]any{"type": "image","source": map[string]any{"type":       "base64","media_type": mimeType,"data":       base64.StdEncoding.EncodeToString(img.Data),},})}// 发送给 Claude Codereturn cs.writeJSON(map[string]any{"type":    "user","message": map[string]any{"role": "user", "content": parts},})
}

cc-connect 把图片以 Anthropic 格式的 base64 数据内联发送给 Claude Code。

Claude Code 的图片检查机制

Claude Code 在发送 API 请求之前,会检查配置的模型是否支持图片。如果不支持,直接返回固定的"无法看到图片"回复,不会发送任何 API 请求

用户发图片 → cc-connect 编码为 base64 → 发给 Claude Code
→ Claude Code 检查模型(mimo-v2.5-pro)→ 不支持图片
→ 返回"无法看到图片"(不调用 API,不使用 MCP)

这就是为什么 input_tokens=0tools=0

对比:ACP 代理的处理方式

有趣的是,ACP 代理(agent/acp/session.go)的处理方式不同:

func (s *acpSession) appendImageRefs(prompt string, images []core.ImageAttachment) string {// 只保存图片到磁盘for i, img := range images {fpath := filepath.Join(attachDir, fname)os.WriteFile(fpath, img.Data, 0o644)paths = append(paths, fpath)}// 只发送文件路径,不发送 base64 数据return prompt + "\n\n(Image files saved locally: " + strings.Join(paths, ", ") + ")"
}

ACP 代理只发送文件路径,不发送 base64 数据。但 Claude Code 代理没有这样做。


第四步:修复方案

修改 agent/claudecode/session.goSend 函数,移除 base64 编码部分,只保留文件保存和路径引用。

修改前(原始代码):

// Save and encode images
for i, img := range images {ext := extFromMime(img.MimeType)fname := fmt.Sprintf("img_%d_%d%s", time.Now().UnixMilli(), i, ext)fpath := filepath.Join(attachDir, fname)if err := os.WriteFile(fpath, img.Data, 0o644); err != nil {slog.Error("claudeSession: save image failed", "error", err)continue}savedPaths = append(savedPaths, fpath)slog.Debug("claudeSession: image saved", "path", fpath, "size", len(img.Data))mimeType := img.MimeTypeif mimeType == "" {mimeType = "image/png"}// ❌ 这行发送 base64 数据给 Claude Codeparts = append(parts, map[string]any{"type": "image","source": map[string]any{"type":       "base64","media_type": mimeType,"data":       base64.StdEncoding.EncodeToString(img.Data),},})
}

修改后:

// Save images to disk (do NOT send base64 inline)
for i, img := range images {ext := extFromMime(img.MimeType)fname := fmt.Sprintf("img_%d_%d%s", time.Now().UnixMilli(), i, ext)fpath := filepath.Join(attachDir, fname)if err := os.WriteFile(fpath, img.Data, 0o644); err != nil {slog.Error("claudeSession: save image failed", "error", err)continue}savedPaths = append(savedPaths, fpath)slog.Debug("claudeSession: image saved", "path", fpath, "size", len(img.Data))// ✅ 不再发送 base64 数据,只保存到磁盘
}

同时移除未使用的 encoding/base64 导入。


第五步:编译和部署

1. 克隆源码

git clone https://github.com/chenhg5/cc-connect.git
cd cc-connect

2. 修改代码

编辑 agent/claudecode/session.go,按上述方式修改 Send 函数。

3. 安装 Go 编译器

cc-connect 需要 Go 1.25.0:

# 从镜像下载
curl -L https://mirrors.aliyun.com/golang/go1.25.0.linux-amd64.tar.gz -o /tmp/go.tar.gz
mkdir -p ~/go-install
tar -C ~/go-install -xzf /tmp/go.tar.gz
export PATH=$HOME/go-install/go/bin:$PATH

4. 编译

cd ~/cc-connect
export GOPROXY=https://mirrors.aliyun.com/goproxy/
go build -tags no_web -o cc-connect-modified ./cmd/cc-connect

使用 -tags no_web 跳过 Web UI 构建(需要 Node.js 构建前端资源)。

5. 替换原版

# 停止原版 cc-connect
pkill -f cc-connect# 启动修改版
~/cc-connect/cc-connect-modified --force

修复后的流程

飞书发图片→ cc-connect 下载图片,保存到 .cc-connect/attachments/→ cc-connect 发送文本消息给 Claude Code:"User sent image(s).(Images also saved locally: /path/to/img.jpg)"→ Claude Code 收到文本消息→ Claude Code 读取 CLAUDE.md 中的图片分析指令→ Claude Code 调用 MCP 工具分析图片→ MCP 使用 mimo-v2-omni 模型分析图片→ 返回分析结果给用户

CLAUDE.md 配置

确保项目目录下有 CLAUDE.md,告诉 Claude Code 如何处理图片:

# Image Analysis ProtocolWhen you receive a message that mentions an image, picture, photo, or screenshot,
the image file has already been saved to disk by cc-connect.## Steps to analyze an image:1. Find the latest image file:
```bash
ls -t /home/user/projects/.cc-connect/attachments/ | head -1
  1. Analyze it using MCP:
MIMO_API_KEY="your-key" MIMO_API_BASE="your-api-base" MIMO_MODEL="mimo-v2-omni" \
python -c "
from mimo_media_recognition_mcp.server import understand_image
import asyncio
result = asyncio.run(understand_image(prompt='详细描述这张图片的内容',image_path='/home/user/projects/.cc-connect/attachments/IMAGE_FILENAME'
))
print(result)
"
  1. Reply with the analysis result in the user's language.

IMPORTANT: You MUST use the Bash tool to run the analysis command.
NEVER say you cannot see images.

总结

项目 说明
问题 cc-connect 把图片以 Anthropic base64 格式发给 Claude Code,但 MIMO 模型不支持图片格式,Claude Code 直接返回"无法看到图片"
根因 agent/claudecode/session.goSend 函数把图片编码为 base64 内联发送
修复 移除 base64 编码,只保存图片到磁盘,通过文件路径引用
效果 Claude Code 收到文本消息,读取 CLAUDE.md,调用 MCP 分析图片

核心思路:不让 Claude Code 看到图片数据(它处理不了),而是让它知道图片在哪里(文件路径),然后通过 MCP 工具去分析。


附录:一键启动脚本

#!/bin/bash
# start-cc-connect.shpkill -f cc-connect 2>/dev/null
sleep 1# 使用修改版 cc-connect
~/cc-connect/cc-connect-modified --force
chmod +x start-cc-connect.sh
./start-cc-connect.sh
http://www.gsyq.cn/news/1394902.html

相关文章:

  • 精准窗口尺寸控制:3步掌握WindowResizer的高级应用技巧
  • 无人船的基本结构(TODO)
  • Excel两列数据比对:从找不同到数据一致性校验
  • Unity启动页帧动画实现原理与工程实践
  • 从零到一:30分钟掌握nomic-embed-text-v1文本嵌入模型部署全攻略 [特殊字符]
  • 从PLC对接到数字孪生闭环,AI Agent在离散制造中的全栈集成路径,深度拆解3类产线适配方案
  • 2026 百色房屋漏水不用愁!雨中匠人免费上门检测,本地专业防水公司常年TOP1!卫生间免砸砖防水,快速解决您的烦恼。权威!靠谱!稳定!售后无忧!!! - 防水百科
  • OpenCV鱼眼矫正踩坑实录:手把手教你读懂fisheye::initUndistortRectifyMap源码里的数学
  • 浏览器视频资源嗅探神器:猫抓插件让你轻松保存网页视频资源
  • Burp Suite弱口令检测实战:从响应特征到多维认证逆向
  • 内容创作团队借助Taotoken多模型能力提升文案生成效率与多样性
  • 从POV原理到静音时钟:非接触供电与动平衡实践
  • 从LSB隐写到Nihilist密码:一次完整的Misc实战解密之旅
  • 深度实践ShiroAttack2:揭秘开源安全工具的架构创新与实战应用
  • 3分钟掌握iOS应用签名:终极图形化工具完整指南
  • 如何通过 Python 调用 Taotoken 的多模型 API 快速构建应用
  • 关联规则挖掘实战:从超市货架到电商推荐的商业逻辑
  • 部署/推理大模型的程序架构(推理引擎/框架)及其开源协议
  • 从攻击到防御:手把手教你用Hydra破解自家Win10后,如何设置强密码策略和账户锁定
  • EtherCAT PDO映射实战:从XML文件到STM32代码,搞定一个自定义模拟量变量
  • Blender导出OBJ到Unity模型发白的三大断点与解决方案
  • CTGAN完全教程:如何用条件GAN生成高质量的合成表格数据
  • AI工具协同失效诊断手册:用3个指标(响应熵值、上下文衰减率、意图偏移度)秒判工作流亚健康
  • 终于搞懂 XSS 为什么能盗号了:Cookie、Session、HttpOnly 一次讲明白
  • 基于4G GSM的嵌入式安防系统软件架构设计与实现
  • 留学生论文救星!okbiye Turnitin 降 AIGC 功能,轻松规避学术不端检测
  • 融合超图与强化学习的会话推荐系统:HG-SRL模型详解与实践
  • ESP8266 WiFi中继器深度解析:高性能物联网网关与网络扩展技术实现
  • Unlock-Music:打破音乐平台限制,让加密音乐重获自由的终极解决方案
  • 从Haar特征到SURF:深入拆解积分图如何成为计算机视觉经典算法的‘加速引擎’