agent-vision
# agent-vision
一个小而直接的视觉 MCP Server + Agent Skill:让纯文本 Agent 通过一个
OpenAI-compatible 视觉模型理解图片和视频,也能通过生图模型从文字生成图片。
- 纯 Node.js / TypeScript,`npx` 自动下载运行
- MCP 工具:`analyze_image`、`analyze_video`、`generate_image`
- Agent Skills 标准目录:`skills/agent-vision/`,能力自适应:能看图的 Agent 直接看,纯文本 Agent 直接跑 CLI
- 图片:本地路径、HTTP(S) URL、Data URI
- 视频:本地路径或 URL,自动下载 npm 内的 ffmpeg 并均匀抽帧
- 识图多 provider 多模型并发竞速:所有 target 同时请求,谁先成功用谁,其余请求 abort
- 生图:支持 OpenAI-compatible 和火山方舟 Seedream,独立配置 provider / model,按顺序失败回退
## 为什么做这个项目
参考项目各有优点,但组合起来偏重:
- [luma-mcp](https://github.com/JochenYang/luma-mcp):Node.js、npx 和图片预处理体验好,但主要面向单图。
- [deepseek-vision-mcp](https://github.com/JunHua-ECJTU/deepseek-vision-mcp):MCP 执行层与 Skill 决策层分离得很清楚,但依赖 Python,且本地视频受 provider 限制。
- [vision-tool](https://github.com/farhanic017/vision-tool):支持视频抽帧,但包含大量 provider 探测、并行 fallback 和安装逻辑,并采用 GPL-3.0。
- [agent-vision-toolkit](https://github.com/Anionex/agent-vision-toolkit):Skill 和任务工作流很强,但核心是多组 Python/Shell CLI,不是 MCP 视频服务。
`agent-vision` 保持两条简单链路:
- 理解:**MCP/CLI → 图片或视频帧 → 你配置的视觉 API → 文本**
- 生成:**MCP/CLI → 文字描述 → 你配置的生图 API → 图片**
本仓库是独立实现,没有复制 `vision-tool` 的 GPL 源码。
## 要求
- Node.js 20+
- 图片/视频理解:支持 `/chat/completions` 和 `image_url` 的 OpenAI-compatible 视觉模型
- 生图:OpenAI-compatible 生图模型,或火山方舟 Seedream(API Key 鉴权);理解和生图可以单独配置
ffmpeg 由 `@ffmpeg-installer/ffmpeg` 按平台自动安装,无需另行安装。
## 配置
推荐用配置文件(一次配置,所有宿主共用):
```bash
mkdir -p ~/.config/agent-vision
cat > ~/.config/agent-vision/settings.json <<'EOF'
{
"providers": [
{
"name": "dashscope",
"baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"apiKey": "sk-...",
"models": ["qwen-vl-max", "qwen-vl-plus"]
},
{
"name": "openai",
"baseUrl": "https://api.openai.com/v1",
"apiKey": "sk-...",
"models": ["gpt-4o"]
}
]
}
EOF
chmod 600 ~/.config/agent-vision/settings.json
```
- 位置:`$AGENT_VISION_CONFIG` 显式路径,或 `$XDG_CONFIG_HOME/agent-vision/settings.json`(默认 `~/.config/agent-vision/settings.json`)
- `providers` 用于图片/视频理解,每个 provider × model 是一个 target;多个 target 时**并发请求,第一个成功者胜出**,其余请求 abort。注意成本:N 个 target 意味着每次分析最多 N 份上传与推理费用
- provider 字段:`baseUrl`(必填)、`models`(必填非空)、`name`/`apiKey`/`headers`(可选;`apiKey` 缺省回退环境变量)
- 顶层可选:`maxTokens`、`timeoutMs`、`headers`、`maxImageMb`、`maxVideoMb`、`allowPrivateUrls`、`ffmpegPath`
- 文件定义的字段优先于环境变量;含 key 的文件建议 `chmod 600`
环境变量作为回退仍然完整支持(无配置文件时):
| 设置 | 兼容回退 |
|---|---|
| `AGENT_VISION_API_KEY` | `VISION_API_KEY` → `OPENAI_API_KEY` |
| `AGENT_VISION_BASE_URL` | `VISION_BASE_URL` → `OPENAI_BASE_URL` |
| `AGENT_VISION_MODEL` | `VISION_MODEL` → `OPENAI_MODEL` |
### 生图配置
在同一个 `settings.json` 中添加 `generationProviders`,字段与识图的 `providers`
类似,额外通过 `type` 选择生图协议;也可以只配置生图,不配置识图:
```json
{
"generationProviders": [
{
"name": "image-api",
"type": "openai-images",
"baseUrl": "https://your-image-api.example/v1",
"apiKey": "sk-...",
"models": ["your-image-generation-model"]
}
]
}
```
- 识图与生图模型完全分开,不会把视觉聊天模型自动当作生图模型。
- `type` 支持 `openai-images`(默认,兼容旧配置)和 `volcengine-ark`。按显式协议适配请求,不根据域名或模型名称猜测;未知类型会报配置错误。
- `generationProviders` 内按 provider、model 的配置顺序依次尝试,拿到第一张有效图片就停止,**不并发竞速**。失败回退仍可能产生多次费用(例如上游超时但实际已完成生成);只想调用一个模型时配置一个 target。
- 每次只生成一张图片;目前支持文生图,不包含参考图编辑或异步任务轮询。
- 两种协议均支持 `data[0].b64_json` 或 `data[0].url` 返回。`openai-images` 省略 `response_format`,避免不支持该参数的模型报错;`volcengine-ark` 请求 base64 返回。参考 [OpenAI 官方 Images API 文档](https://developers.openai.com/api/reference/resources/images/methods/generate)。
- 与识图共用顶层 `timeoutMs`、`maxImageMb`、`headers`、`allowPrivateUrls`,生图较慢时可调高 `timeoutMs`。
- `doctor` 会分别列出识图和生图 targets,并显示生图协议,只配置生图时不要求 ffmpeg。
#### 火山引擎方舟(Seedream)
在已有配置中加入下面的生图部分即可,保留原来的 `providers`:
```json
{
"generationProviders": [
{
"name": "volcengine",
"type": "volcengine-ark",
"baseUrl": "https://ark.cn-beijing.volces.com/api/v3",
"apiKey": "你的方舟 API Key",
"models": ["doubao-seedream-5-0-lite-260128"]
}
]
}
```
`models` 填写你已开通的 Seedream Model ID,也支持配置了生图模型的 `ep-...` 接入点 ID。
`apiKey` 可省略并从 `ARK_API_KEY` 读取;若设置了 `AGENT_VISION_GENERATION_API_KEY`,则后者优先。
方舟不会自动继承识图的 `AGENT_VISION_API_KEY` / `OPENAI_API_KEY`,避免把其他服务的 key 发给火山。
```bash
npx -y @yanickxia/agent-vision generate \
--prompt "一只坐在窗边的橘猫,水彩风格" --output ./cat.jpg --size 2K
```
- 使用方舟原生 `/api/v3/images/generations` 参数,不发送 OpenAI 的 `n` 或 `quality`;传 `--quality` 会在调用前报错,不静默忽略。
- `--size` 可用模型支持的分辨率档位(例如 `2K`)或 `宽x高`,省略时采用模型默认值。
- 保持服务端的单图、非流式默认行为,不发送部分 Seedream 模型不支持的组图/流式开关。
- 保留模型默认水印和输出格式;Seedream 通常返回 JPEG,文件扩展名不会触发转码。
- 能解析火山的 HTTP 错误及成功 HTTP 响应中的顶层/单图错误,保留错误码与消息。
协议依据:[方舟官方图片生成 API](https://ark.volcengine.com/region:cn-beijing/docs/image-generation-api.md)。
本适配针对**方舟 Seedream 文生图**,不是“视觉智能/即梦”的 AK/SK 签名接口,不包含图生图、组图或图层拆分。
#### 生图环境变量
也可以用环境变量配置生图:
| 变量 | 回退 / 说明 |
|---|---|
| `AGENT_VISION_GENERATION_TYPE` | 默认 `openai-images`;火山方舟设为 `volcengine-ark` |
| `AGENT_VISION_GENERATION_MODEL` | 生图模型名称,必须显式设置;不回退到识图模型 |
| `AGENT_VISION_GENERATION_BASE_URL` | OpenAI 协议回退到识图 URL 及其别名;方舟协议默认 `https://ark.cn-beijing.volces.com/api/v3`,不继承识图 URL |
| `AGENT_VISION_GENERATION_API_KEY` | OpenAI 协议回退到识图 key 及其别名;方舟协议回退到 `ARK_API_KEY` |
| `ARK_API_KEY` | 仅用于 `volcengine-ark` 的 key 回退 |
| `AGENT_VISION_GENERATION_HEADERS` | 生图专用额外请求头 JSON,覆盖通用环境变量请求头 |
文件中 `generationProviders` 优先于环境变量生图 target;provider 的 `apiKey`
省略时使用上述生图 key 回退,显式 `"apiKey": ""` 可关闭 key 回退。
文件内未指定 `type` 的 provider 始终是 `openai-images`,不受环境变量的 `TYPE` 影响。
请求头优先级:通用环境变量 → 生图环境变量 → 文件顶层 → provider。
### 通用选项
以下可选变量与对应的配置文件字段等价:
| 变量 | 默认值 | 说明 |
|---|---:|---|
| `AGENT_VISION_MAX_TOKENS` | `4096` | 最大输出 tokens |
| `AGENT_VISION_TIMEOUT_MS` | `120000` | 下载和 API 超时 |
| `AGENT_VISION_MAX_IMAGE_MB` | `20` | 输入和生成图片的大小上限 |
| `AGENT_VISION_MAX_VIDEO_MB` | `200` | 视频大小上限 |
| `AGENT_VISION_HEADERS` | `{}` | 额外请求头 JSON |
| `AGENT_VISION_ALLOW_PRIVATE_URLS` | `false` | 允许私网图片/视频来源及生图结果 URL |
| `AGENT_VISION_FFMPEG_PATH` | 自动发现 | 指定 ffmpeg 可执行文件;默认先用 PATH,再用 npm 内置版本 |
## MCP 安装
### npm(推荐)
```json
{
"mcpServers": {
"agent-vision": {
"command": "npx",
"args": ["-y", "@yanickxia/agent-vision"]
}
}
}
```
### 直接从 GitHub 运行
```json
{
"mcpServers": {
"agent-vision": {
"command": "npx",
"args": ["-y", "github:yanickxia/agent-vision"]
}
}
}
```
无需 env 块:配置从 `~/.config/agent-vision/settings.json` 读取(见上文「配置」)。
也可以继续用环境变量,在 `env` / `environment` 块里传入。
Claude Desktop、Claude Code、Cursor、Cline 等使用上面的标准
`mcpServers` 格式。
### OpenCode
```jsonc
{
"mcp": {
"agent-vision": {
"type": "local",
"command": ["npx", "-y", "@yanickxia/agent-vision"],
"enabled": true
}
}
}
```
## Agent Skill
```bash
npx skills add yanickxia/agent-vision --skill agent-vision -g -y
```
也可以复制 `skills/agent-vision/` 到 Agent 的 skills 目录。Skill 是能力自适应
的:Agent 自己能看图就直接看;看不了(或输入是视频)就由 Skill 指导 Agent
直接跑 CLI 完成分析。生图不受「能否看图」限制,任何 Agent 都可以使用。
**MCP 和 Skill/CLI 都支持火山方舟生图**,共用同一份 `settings.json` 中的
`generationProviders` 配置。Skill 直接执行 CLI,不依赖启动或安装 MCP Server。
| 入口 | 调用 | 输出 |
|---|---|---|
| MCP | `generate_image`,传 `prompt`、可选 `size` / `output_path` | 图片内容和元数据,可选保存文件 |
| Skill / CLI | `agent-vision generate --prompt ... --output ...` | 保存文件,stdout 返回绝对路径 |
从源码使用尚未发布的功能时,先在仓库中运行 `npm run build`,然后用
`node /绝对路径/agent-vision/dist/cli.js generate ...` 运行 CLI。
本地 MCP 配置也可使用 `command: "node"`、`args: ["/绝对路径/agent-vision/dist/cli.js"]`,
不要加 `generate` 参数,无子命令时即启动 MCP stdio 服务。
## CLI
```bash
npx -y @yanickxia/agent-vision image ./screenshot.png \
--prompt "读取报错并给出可能原因"
npx -y @yanickxia/agent-vision video ./demo.mp4 \
--prompt "按时间顺序总结 UI 操作" --frames 8
npx -y @yanickxia/agent-vision generate \
--prompt "一只坐在窗边的橘猫,水彩风格" --output ./cat.png --size 1024x1024
npx -y @yanickxia/agent-vision doctor
```
`generate` 必须提供 `--prompt`(或一个带引号的位置参数)和 `--output`。
可选 `--size` 原样传给生图 API;`--quality` 仅用于 OpenAI-compatible 协议。
省略时采用 provider 默认值,支持值取决于模型。
输出文件的父目录必须存在,已有文件不会被覆盖;成功时 stdout 输出保存的绝对路径。
图片保留 API 返回的实际格式,不会因输出文件的扩展名而转码。
## MCP 工具
### `analyze_image`
```json
{
"source": "/absolute/path/to/image.png",
"prompt": "这个页面有哪些可用性问题?"
}
```
支持 JPEG、PNG、WebP、GIF、BMP。GIF 是否能体现动画取决于视觉模型;需要稳定的
时间线分析时请转为视频并使用 `analyze_video`。
### `analyze_video`
```json
{
"source": "/absolute/path/to/video.mp4",
"prompt": "概括操作流程和关键变化",
"max_frames": 8
}
```
`max_frames` 范围 1–16,默认 8。实现会均匀抽取 JPEG 帧,并带时间点一起发给
模型。它不是逐帧转写,快速变化可能被漏掉。
### `generate_image`
```json
{
"prompt": "一只坐在窗边的橘猫,水彩风格",
"output_path": "/absolute/path/to/cat.png",
"size": "1024x1024"
}
```
只有 `prompt` 必填。`output_path` 可选,不传时仅返回 MCP 图片内容,不写本地文件。
`size`、`quality` 可选。返回一个 text 内容块(JSON 元数据:模型、MIME 类型、字节数、
可选输出路径和上游改写的 prompt)以及一个 image 内容块。路径是 MCP Server 所在机器上的路径。
## 隐私与安全
- 图片会发送到你配置的视觉 API。
- 生图 prompt 会发送到你配置的生图 API;如果上游返回图片 URL,会下载该图片,但不会向图片下载地址转发生图 API key 或自定义请求头。
- 视频不会整体发给模型;远程视频先下载到本地临时目录,然后只发送抽出的 JPEG 帧。
- 临时目录在成功或失败后都会删除。
- 用户提供的远程图片/视频 URL 和上游返回的生图 URL 默认拒绝 localhost、私网、链路本地和云元数据地址。
- 生图失败会删除本次预留的输出文件;成功的生图文件会保留,不会作为临时文件清理。
- stdio 模式不向 stdout 写日志,避免破坏 MCP 协议。
## 开发
```bash
npm install
npm run typecheck
npm test
npm pack --dry-run
```
## License
MIT。第三方依赖保留各自许可证,见 `NOTICE`。
TDQS
Scored across 3 tools
The three tools target clearly distinct actions and modalities: image generation, image analysis, and video analysis. The analyze_image description also explicitly clarifies when not to use it, reducing misselection risk.
All tools follow a consistent verb_noun pattern: generate_image, analyze_image, analyze_video. The convention is predictable and directly reflects each tool's purpose.
Three tools are well-scoped for a focused vision server: generation, image understanding, and video understanding. Each tool has a clear reason to exist, with no redundant surface area.
The core lifecycle for vision tasks is covered: create images, inspect images, and inspect videos. Minor gaps exist, such as image editing/transformation or batch analysis, but agents can work around them for most stated use cases.