qwen-vision-mcp
Enables text-only LLMs to see images on demand by integrating Qwen vision models via MCP, supporting stateful multi-turn conversations with automatic history trimming.
README
qwen-vision-mcp
让任何文本模型(Claude、GLM、GPT、Gemini...)通过 MCP 按需"看图"。后端走阿里云 DashScope 的 qwen 视觉模型,通过 Anthropic 兼容接口调用。
为什么需要这个
文本模型(GLM-4、Claude Haiku、GPT-4o-mini 等便宜/快的模型)不会直接看图。但很多任务(截图报错、UI 调试、图表分析、文档 OCR)需要视觉理解。
qwen-vision-mcp 把 qwen 视觉模型包装成一个 MCP 工具 look(image, question),让任何 MCP 兼容的 Agent 按需调用——只在需要时才"看一眼",主对话仍由你便宜的文本模型驱动。
特色
- 🧠 有状态多轮持久:同一会话内 qwen 会记得之前所有图片和问答,支持"再看一眼刚才那张图"。
- 🚆 自动 trim 防超限:单次请求体超过 DashScope 6MB 上限时,自动把较早的 image block 替换成文字指针(保留文字 question + assistant 回复),长程多图对话不崩。
- 🔌 按进程隔离:每个客户端会话独立一个 MCP server 进程,messages 不串台。
- 📦 极简依赖:只依赖
@modelcontextprotocol/sdk,Bun 直接跑 .ts,无编译步骤。 - 🔁 失败干净回滚:网络异常 / HTTP 错误时自动 pop 掉刚 push 的 user message,历史不污染。
工作原理
文本模型 (GLM/Claude/GPT) ──MCP stdio──▶ qwen-vision-mcp server
│
▼
DashScope qwen 视觉模型
(Anthropic 兼容接口)
主模型决定"什么时候需要看图、问什么",qwen 只负责"看一眼并回答具体问题"。模型行为由工具 description 引导(要拆解、要聚焦、要多轮追问)。
安装
需要 Bun 运行时 + DashScope API Key(阿里云百炼控制台 获取)。
git clone <your-fork-url> qwen-vision-mcp
cd qwen-vision-mcp
bun install # 装 @modelcontextprotocol/sdk
cp .env.example .env # 填入 QWEN_API_KEY
.env 内容:
QWEN_BASE_URL=https://dashscope.aliyuncs.com/apps/anthropic/v1
QWEN_API_KEY=sk-你的-key
QWEN_MODEL=qwen3.7-plus
QWEN_MAX_TOKENS=1024
QWEN_MAX_REQUEST_BYTES=5000000
接入 MCP 客户端
Claude Code
在 ~/.claude.json(或项目级 .mcp.json)的 mcpServers 里加:
{
"mcpServers": {
"qwen-vision": {
"command": "bun",
"args": ["run", "/absolute/path/to/qwen-vision-mcp/index.ts"],
"env": { "QWEN_API_KEY": "sk-..." }
}
}
}
Cursor / Continue / 其它 MCP 客户端
任何支持 stdio MCP server 的客户端都能接入,配置格式大同小异——指定 bun 为 command,run /path/to/index.ts 为 args,把 QWEN_API_KEY 放到 env 里。
Proma
在 Proma 工作区的 mcp.json 里加:
"qwen-vision": {
"type": "stdio",
"command": "bun",
"args": ["run", "/absolute/path/to/qwen-vision-mcp/index.ts"],
"env": { "QWEN_API_KEY": "sk-...", "QWEN_MODEL": "qwen3.7-plus" },
"enabled": true
}
暴露的工具
look(image, question) — 有状态
让 qwen 看一张图片回答你提出的具体问题。
- image: 本地绝对路径 / http(s) URL /
data:image;base64,... - question: 针对该图片的具体、聚焦的问题
重要:这个工具是有状态的。同一会话内 qwen 会记得前面所有图片和问答。
- 同一张图追问细节 → 直接连续调用,qwen 自带上下文
- 切换到完全无关的新图 → 先调
reset_vision_session清空历史,避免旧图污染
reset_vision_session() — 清空历史
何时调:当前图片讨论完、要切到无关新图时,或想从干净状态重启时。 何时不调:同一张图的多轮追问、相关图片延续讨论时。
配置项
| 环境变量 | 默认 | 说明 |
|---|---|---|
QWEN_BASE_URL |
https://dashscope.aliyuncs.com/apps/anthropic/v1 |
DashScope Anthropic 兼容入口 |
QWEN_API_KEY |
必填 | DashScope API Key |
QWEN_MODEL |
qwen3.7-plus |
视觉模型 id(可改 qwen-vl-max-latest 等) |
QWEN_MAX_TOKENS |
1024 |
单次回复 token 上限 |
QWEN_MAX_REQUEST_BYTES |
5000000 |
单次请求体字节上限(DashScope 硬上限 6MB) |
QWEN_ENABLE_THINKING |
false |
推理模型 thinking 开关。默认关(视觉问答 7-10x 提速);复杂图表分析/推理题场景设 true |
已知限制
- 进程隔离 ≠ 跨重启持久化:进程被杀(客户端退出、crash)→ 内存里的 messages 丢失 = 自动 reset。同一会话活跃期间的持久化没问题,跨重启做不到。
- URL 图片需 DashScope 服务端能访问:内网图床 / 被墙的 URL 会报
Failed to download multimodal content,用本地路径最稳。 - 历史图片 trim 策略:超过
QWEN_MAX_REQUEST_BYTES时从最早的 image 开始替换成文字指针,保留最后 1 张图和所有文字。这意味着 qwen 对"很久之前的图"会失去视觉记忆(但仍能从对话历史里"读"自己之前的描述)。
故障排查
| 错误 | 原因 | 解决 |
|---|---|---|
404 |
BASE_URL 错了 | 确认用 /apps/anthropic/v1 而不是 /compatible-mode/v1 |
model not found |
QWEN_MODEL id 错了 | 查 DashScope 文档 确认 id |
Failed to download multimodal content |
URL 图片 DashScope 服务端访问不到 | 改用本地路径 |
Exceeded limit on max bytes to request body : 6291456 |
请求体超 6MB | 已自动 trim;若仍报错,调小 QWEN_MAX_REQUEST_BYTES 或主动调 reset_vision_session |
| 响应慢(每次 10s+) | qwen3.7-plus 是推理模型,默认每轮生成几百 token thinking |
已默认关 thinking;确认 QWEN_ENABLE_THINKING=false(或换非推理模型如 qwen-vl-max-latest) |
开发与测试
# 启动 server(stdio 模式,等待客户端连接)
bun run index.ts
# 协议层冒烟测试(发 initialize + tools/list)
( \
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' ; \
sleep 2 \
) | bun run index.ts
# 端到端测试(看一张本地图)
( \
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"look","arguments":{"image":"/tmp/test.png","question":"一句话描述这张图"}}}' ; \
sleep 15 \
) | bun run index.ts
License
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.