image-vision-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +252 -0
- package/dist/constants.d.ts +15 -0
- package/dist/constants.js +16 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/proxy/imageProxy.d.ts +1 -0
- package/dist/proxy/imageProxy.js +346 -0
- package/dist/proxy/imageProxy.js.map +1 -0
- package/dist/schemas.d.ts +26 -0
- package/dist/schemas.js +32 -0
- package/dist/schemas.js.map +1 -0
- package/dist/services/clipboard.d.ts +16 -0
- package/dist/services/clipboard.js +196 -0
- package/dist/services/clipboard.js.map +1 -0
- package/dist/services/image.d.ts +19 -0
- package/dist/services/image.js +216 -0
- package/dist/services/image.js.map +1 -0
- package/dist/services/moonshot.d.ts +9 -0
- package/dist/services/moonshot.js +71 -0
- package/dist/services/moonshot.js.map +1 -0
- package/dist/tools/describeClipboard.d.ts +2 -0
- package/dist/tools/describeClipboard.js +106 -0
- package/dist/tools/describeClipboard.js.map +1 -0
- package/dist/tools/describeImage.d.ts +2 -0
- package/dist/tools/describeImage.js +105 -0
- package/dist/tools/describeImage.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 vision-mcp contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# Vision MCP Server
|
|
2
|
+
|
|
3
|
+
为 Claude Code 提供图像识别能力的 MCP server,附带 HTTP 图片拦截代理,让纯文本模型(如 GLM)也能接受图片输入,暂只支持用 kimi 来提供视觉能力。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
本项目包含两部分,可独立或组合使用:
|
|
8
|
+
|
|
9
|
+
### 1. MCP 工具(默认)
|
|
10
|
+
|
|
11
|
+
支持三种图片来源:
|
|
12
|
+
|
|
13
|
+
| 工具 | 输入 | 示例 |
|
|
14
|
+
|------|------|------|
|
|
15
|
+
| `kimi_describe_image` | 本地图片文件 | `C:/Users/me/screenshot.png` |
|
|
16
|
+
| `kimi_describe_image` | 网络图片 URL | `https://example.com/img.png` |
|
|
17
|
+
| `kimi_describe_clipboard` | 系统剪贴板图片(直接 `Ctrl+C` 复制,无需先保存为文件) | - |
|
|
18
|
+
|
|
19
|
+
通过 [Moonshot](https://platform.moonshot.cn) Kimi 视觉模型(如 `kimi-k2.6`)识别,跨平台支持 Windows / macOS / Linux。
|
|
20
|
+
|
|
21
|
+
### 2. HTTP 图片拦截代理(可选)
|
|
22
|
+
- 用户在 Claude Code 中直接 `Ctrl+V` 粘贴图片即可
|
|
23
|
+
- 在 Claude Code 和上游 LLM API 之间做代理
|
|
24
|
+
- 自动拦截请求中的图片,调 Moonshot 识别后替换为文字描述
|
|
25
|
+
- 让纯文本模型(如 GLM)也能正常处理图片输入,不再 400 报错
|
|
26
|
+
|
|
27
|
+
## 工作原理
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
31
|
+
│ Claude Code │
|
|
32
|
+
│ ├─ 调用 MCP 工具 kimi_describe_image/clipboard → Moonshot API │
|
|
33
|
+
│ └─ 发送消息(含图片)→ http://127.0.0.1:8787 (本代理) │
|
|
34
|
+
│ ↓ │
|
|
35
|
+
│ 代理拦截图片 → 调 Moonshot 识别 → 替换为文字 │
|
|
36
|
+
│ ↓ │
|
|
37
|
+
│ 转发纯文本请求 → 上游 LLM API(如 GLM) │
|
|
38
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
MCP 工具和代理共享同一进程、同一份 Moonshot 配置,启动 MCP server 时代理自动起来。
|
|
42
|
+
|
|
43
|
+
## 前置条件
|
|
44
|
+
|
|
45
|
+
- Node.js >= 18
|
|
46
|
+
- Moonshot API Key(在 [platform.moonshot.cn](https://platform.moonshot.cn) 申请)
|
|
47
|
+
|
|
48
|
+
构建产物在 `dist/index.js`。
|
|
49
|
+
|
|
50
|
+
## 配置
|
|
51
|
+
|
|
52
|
+
### 1. 基础配置(启用 MCP 工具)
|
|
53
|
+
|
|
54
|
+
编辑 `~/.claude.json`,加入 MCP server 配置,默认识别剪贴板图片,无需粘贴:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"mcpServers": {
|
|
59
|
+
"vision-mcp": {
|
|
60
|
+
"command": "node",
|
|
61
|
+
"args": ["/absolute/path/to/vision-mcp/dist/index.js"],
|
|
62
|
+
"env": {
|
|
63
|
+
"MOONSHOT_API_KEY": "sk-你的-moonshot-api-key",
|
|
64
|
+
"MOONSHOT_BASE_URL": "https://api.kimi.com/coding/v1"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
重启 Claude Code 后,对 Claude 说"识别剪贴板里的图片"或"识别 C:/xxx.png",Claude 会自动调用识图工具。
|
|
72
|
+
|
|
73
|
+
### 2. 高级配置(启用图片代理,可选)
|
|
74
|
+
|
|
75
|
+
**什么时候需要**:你用 GLM 等纯文本模型,想在 Claude Code 里直接 `Ctrl+V` 粘贴图片(不用先说"识别图片")。代理会自动拦截图片,调 Moonshot 识别后转发给上游模型。
|
|
76
|
+
|
|
77
|
+
| 用法 | 怎么识图 |
|
|
78
|
+
|------|----------|
|
|
79
|
+
| 只用 MCP 工具(默认) | 无需粘贴对 Claude 说"识别图片",自动读取剪贴板图片 |
|
|
80
|
+
| 启用图片代理 | 直接 `Ctrl+V` 粘贴图片到 Claude |
|
|
81
|
+
|
|
82
|
+
#### 配置步骤
|
|
83
|
+
|
|
84
|
+
**第 1 步**:编辑 `~/.claude.json`,配置 MCP server(在基础配置基础上加 `UPSTREAM_BASE_URL`):
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"mcpServers": {
|
|
89
|
+
"vision-mcp": {
|
|
90
|
+
"command": "node",
|
|
91
|
+
"args": ["/absolute/path/to/vision-mcp/dist/index.js"],
|
|
92
|
+
"env": {
|
|
93
|
+
"MOONSHOT_API_KEY": "sk-你的-moonshot-key",
|
|
94
|
+
"MOONSHOT_BASE_URL": "https://api.kimi.com/coding/v1",
|
|
95
|
+
"UPSTREAM_BASE_URL": "https://你的上游-llm-api-地址"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**第 2 步**:编辑 `~/.claude/settings.json`,配置 Claude Code 走代理:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"env": {
|
|
107
|
+
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8787",
|
|
108
|
+
"ANTHROPIC_AUTH_TOKEN": "你的上游-llm-api-token"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
> 两处 `env` 作用不同:
|
|
114
|
+
> - `~/.claude/settings.json` 的 `env`:Claude Code 自身读取(走代理 + 上游认证)
|
|
115
|
+
> - `~/.claude.json` 里 `mcpServers.vision-mcp.env`:MCP server 进程读取(Moonshot key + 上游纯文本模型请求地址)
|
|
116
|
+
|
|
117
|
+
**第 3 步**:重启 Claude Code,直接 `Ctrl+V` 粘贴图片即可。
|
|
118
|
+
|
|
119
|
+
#### 环境变量参考
|
|
120
|
+
|
|
121
|
+
**Claude Code 端**(`~/.claude/settings.json` 的 `env`):
|
|
122
|
+
|
|
123
|
+
| 环境变量 | 必填 | 说明 |
|
|
124
|
+
|---------|------|------|
|
|
125
|
+
| `ANTHROPIC_BASE_URL` | 是 | `http://127.0.0.1:8787`,代理监听端口从该 URL 解析 |
|
|
126
|
+
| `ANTHROPIC_AUTH_TOKEN` | 是 | 上游 LLM API 的认证 token,代理转发时复用 |
|
|
127
|
+
|
|
128
|
+
**MCP server 端**(`~/.claude.json` 的 `mcpServers.vision-mcp.env`):
|
|
129
|
+
|
|
130
|
+
| 环境变量 | 必填 | 默认值 | 说明 |
|
|
131
|
+
|---------|------|--------|------|
|
|
132
|
+
| `UPSTREAM_BASE_URL` | 是 | - | 上游 LLM API 地址,未设则代理不启动(MCP 工具仍可用) |
|
|
133
|
+
| `UPSTREAM_AUTH_TOKEN` | 否 | 取自 `ANTHROPIC_AUTH_TOKEN` | 上游认证 token |
|
|
134
|
+
| `MOONSHOT_API_KEY` | 是 | - | Moonshot API key(MCP 工具与代理共用) |
|
|
135
|
+
| `MOONSHOT_BASE_URL` | 是 | - | Moonshot API 端点(如 `https://api.kimi.com/coding/v1`) |
|
|
136
|
+
| `MOONSHOT_MODEL` | 否 | `kimi-k2.6` | Moonshot 视觉模型名 |
|
|
137
|
+
| `IMAGE_DESC_PROMPT` | 否 | 内置中文提示词 | 代理识别图片时发给 Moonshot 的提示词 |
|
|
138
|
+
| `ALLOW_PRIVATE_NETWORK_IMAGES` | 否 | - | 设为 `1` 或 `true` 允许访问内网图片 URL(默认拒绝,防 SSRF) |
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
## 使用示例
|
|
142
|
+
|
|
143
|
+
### 用 MCP 工具识图
|
|
144
|
+
|
|
145
|
+
默认提示词为 **"请详细描述这张图片的内容。"**。你也可以在对话里指定其他指令,例如"提取图片中的所有文字"、"分析图表数据"、"描述 UI 界面布局"。
|
|
146
|
+
|
|
147
|
+
对 Claude 说:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
识别剪贴板里的图片(先 Ctrl+C 复制一张图)
|
|
151
|
+
```
|
|
152
|
+
```
|
|
153
|
+
识别这张图:C:/Users/me/screenshot.png
|
|
154
|
+
```
|
|
155
|
+
```
|
|
156
|
+
描述一下这张网络图片:https://example.com/chart.png
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Claude 会自动调用 `kimi_describe_clipboard` 或 `kimi_describe_image` 工具。
|
|
160
|
+
|
|
161
|
+
### 用代理粘贴图片(配置代理后)
|
|
162
|
+
|
|
163
|
+
在 Claude Code 输入框里直接 `Ctrl+V` 粘贴图片,再输入问题回车:
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
[粘贴图片] 这张图里有什么?
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
代理自动识别图片,把描述和你的问题一起发给上游模型。
|
|
170
|
+
|
|
171
|
+
## 工具参数
|
|
172
|
+
|
|
173
|
+
### `kimi_describe_image`
|
|
174
|
+
|
|
175
|
+
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
|
176
|
+
|------|------|------|------|------|
|
|
177
|
+
| `image` | string | 是 | - | 本地文件路径或 http(s):// 图片 URL |
|
|
178
|
+
| `prompt` | string | 否 | "请详细描述这张图片的内容。" | 识图指令,最长 4000 字符 |
|
|
179
|
+
| `max_tokens` | number | 否 | 2048 | 返回描述的最大 token 数,1-8192 |
|
|
180
|
+
|
|
181
|
+
### `kimi_describe_clipboard`
|
|
182
|
+
|
|
183
|
+
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
|
184
|
+
|------|------|------|------|------|
|
|
185
|
+
| `prompt` | string | 否 | "请详细描述这张图片的内容。" | 识图指令,最长 4000 字符 |
|
|
186
|
+
| `max_tokens` | number | 否 | 2048 | 返回描述的最大 token 数,1-8192 |
|
|
187
|
+
|
|
188
|
+
## 限制
|
|
189
|
+
|
|
190
|
+
- 图片大小上限 20MB(URL 下载与剪贴板读取均适用)
|
|
191
|
+
- 请求超时 60s(Moonshot API)、30s(图片下载)
|
|
192
|
+
- 输出文本超过 25000 字符会截断
|
|
193
|
+
- 支持格式:JPEG / JPG / PNG / GIF / WebP / BMP
|
|
194
|
+
|
|
195
|
+
## 故障排查
|
|
196
|
+
|
|
197
|
+
| 错误 | 解决方案 |
|
|
198
|
+
|------|----------|
|
|
199
|
+
| `MOONSHOT_API_KEY 环境变量未设置` | 检查 MCP 配置的 `env.MOONSHOT_API_KEY` |
|
|
200
|
+
| `Moonshot API 鉴权失败 (401)` | API key 错误或失效 |
|
|
201
|
+
| `Moonshot API 模型不存在 (404)` | 模型名错误(当前用 `kimi-k2.6`) |
|
|
202
|
+
| `Moonshot API 限流 (429)` | 请求过于频繁,稍后重试 |
|
|
203
|
+
| `无法访问本地文件` | 路径错误或无权限 |
|
|
204
|
+
| `下载图片失败` | URL 无法访问或超时 |
|
|
205
|
+
| `剪贴板中没有图片` | 先复制一张图片到剪贴板 |
|
|
206
|
+
| `listen EADDRINUSE 127.0.0.1:8787` | 端口被占用,改 `ANTHROPIC_BASE_URL` 里的端口或关掉占用进程 |
|
|
207
|
+
| 代理启动失败但 MCP 工具可用 | 不影响 MCP 工具功能,仅代理不可用 |
|
|
208
|
+
|
|
209
|
+
## 开发
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
npm run dev # 开发模式(tsx watch,热重载)
|
|
213
|
+
npm run build # 编译 TypeScript → dist/
|
|
214
|
+
npm run clean # 清理构建产物
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## 跨平台剪贴板支持
|
|
218
|
+
|
|
219
|
+
`kimi_describe_clipboard` 工具的剪贴板读取策略:
|
|
220
|
+
|
|
221
|
+
| 平台 | 优先方案 | 回退方案 |
|
|
222
|
+
|------|----------|----------|
|
|
223
|
+
| Windows | PowerShell + System.Windows.Forms | - |
|
|
224
|
+
| macOS | `pngpaste`(`brew install pngpaste`) | `osascript` |
|
|
225
|
+
| Linux | `xclip` | `xsel`(`sudo apt install xclip`) |
|
|
226
|
+
|
|
227
|
+
## 安装
|
|
228
|
+
|
|
229
|
+
发布到 npm 后,直接在 MCP 配置里用 `npx` 启动。`-y` 表示自动下载并运行 `image-vision-mcp` 包:
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
{
|
|
233
|
+
"mcpServers": {
|
|
234
|
+
"vision-mcp": {
|
|
235
|
+
"command": "npx",
|
|
236
|
+
"args": ["-y", "image-vision-mcp"],
|
|
237
|
+
"env": {
|
|
238
|
+
"MOONSHOT_API_KEY": "sk-你的-moonshot-api-key",
|
|
239
|
+
"MOONSHOT_BASE_URL": "https://api.moonshot.cn/v1"
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## 贡献
|
|
247
|
+
|
|
248
|
+
欢迎提 issue 和 PR。当前只支持 Moonshot Kimi,后续计划扩展其他视觉模型(OpenAI、Gemini、通义千问等),架构上已预留扩展点。
|
|
249
|
+
|
|
250
|
+
## License
|
|
251
|
+
|
|
252
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const API_BASE_URL: string;
|
|
2
|
+
export declare const DEFAULT_MODEL: string;
|
|
3
|
+
export declare const CHARACTER_LIMIT = 25000;
|
|
4
|
+
export declare const REQUEST_TIMEOUT_MS = 60000;
|
|
5
|
+
export declare const IMAGE_DOWNLOAD_TIMEOUT_MS = 30000;
|
|
6
|
+
export declare const IMAGE_MAX_SIZE_BYTES: number;
|
|
7
|
+
export declare const SUPPORTED_MIME_TYPES: {
|
|
8
|
+
readonly ".jpg": "image/jpeg";
|
|
9
|
+
readonly ".jpeg": "image/jpeg";
|
|
10
|
+
readonly ".png": "image/png";
|
|
11
|
+
readonly ".gif": "image/gif";
|
|
12
|
+
readonly ".webp": "image/webp";
|
|
13
|
+
readonly ".bmp": "image/bmp";
|
|
14
|
+
};
|
|
15
|
+
export declare const DEFAULT_PROMPT = "\u8BF7\u8BE6\u7EC6\u63CF\u8FF0\u8FD9\u5F20\u56FE\u7247\u7684\u5185\u5BB9\u3002";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const API_BASE_URL = process.env.MOONSHOT_BASE_URL?.replace(/\/+$/, "") || "";
|
|
2
|
+
export const DEFAULT_MODEL = process.env.MOONSHOT_MODEL || "kimi-k2.6";
|
|
3
|
+
export const CHARACTER_LIMIT = 25000;
|
|
4
|
+
export const REQUEST_TIMEOUT_MS = 60000;
|
|
5
|
+
export const IMAGE_DOWNLOAD_TIMEOUT_MS = 30000;
|
|
6
|
+
export const IMAGE_MAX_SIZE_BYTES = 20 * 1024 * 1024; // 20MB
|
|
7
|
+
export const SUPPORTED_MIME_TYPES = {
|
|
8
|
+
".jpg": "image/jpeg",
|
|
9
|
+
".jpeg": "image/jpeg",
|
|
10
|
+
".png": "image/png",
|
|
11
|
+
".gif": "image/gif",
|
|
12
|
+
".webp": "image/webp",
|
|
13
|
+
".bmp": "image/bmp",
|
|
14
|
+
};
|
|
15
|
+
export const DEFAULT_PROMPT = "请详细描述这张图片的内容。";
|
|
16
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;AACrF,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,WAAW,CAAC;AACvE,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AACrC,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC;AACxC,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAC/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;AAE7D,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,WAAW;CACX,CAAC;AAEX,MAAM,CAAC,MAAM,cAAc,GAAG,eAAe,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Vision MCP Server
|
|
4
|
+
*
|
|
5
|
+
* 通过视觉模型提供识图能力的 MCP server。
|
|
6
|
+
* 使用 stdio 传输,供 Claude Code 本地调用。
|
|
7
|
+
*
|
|
8
|
+
* 同时启动 HTTP 图片拦截代理:拦截 Claude Code 发往上游 API 的图片请求,
|
|
9
|
+
* 调用 Moonshot 识别后替换为文字描述,避免 GLM 等纯文本模型 400 报错。
|
|
10
|
+
* 配置 ANTHROPIC_BASE_URL=http://127.0.0.1:8787 即可启用。
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Vision MCP Server
|
|
4
|
+
*
|
|
5
|
+
* 通过视觉模型提供识图能力的 MCP server。
|
|
6
|
+
* 使用 stdio 传输,供 Claude Code 本地调用。
|
|
7
|
+
*
|
|
8
|
+
* 同时启动 HTTP 图片拦截代理:拦截 Claude Code 发往上游 API 的图片请求,
|
|
9
|
+
* 调用 Moonshot 识别后替换为文字描述,避免 GLM 等纯文本模型 400 报错。
|
|
10
|
+
* 配置 ANTHROPIC_BASE_URL=http://127.0.0.1:8787 即可启用。
|
|
11
|
+
*/
|
|
12
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
13
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
14
|
+
import { registerDescribeImageTool } from "./tools/describeImage.js";
|
|
15
|
+
import { registerDescribeClipboardTool } from "./tools/describeClipboard.js";
|
|
16
|
+
import { startImageProxy } from "./proxy/imageProxy.js";
|
|
17
|
+
import { cleanupOldTempImages } from "./services/clipboard.js";
|
|
18
|
+
function getRequiredEnv(name, hint) {
|
|
19
|
+
const value = process.env[name]?.trim();
|
|
20
|
+
if (!value) {
|
|
21
|
+
console.error(`[vision-mcp] 错误: ${name} 环境变量未设置`);
|
|
22
|
+
console.error(`[vision-mcp] ${hint}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
async function main() {
|
|
28
|
+
// 0. fail-fast 校验必需的环境变量
|
|
29
|
+
const apiKey = getRequiredEnv("MOONSHOT_API_KEY", "请在 MCP 配置的 env 里设置 MOONSHOT_API_KEY");
|
|
30
|
+
getRequiredEnv("MOONSHOT_BASE_URL", "请在 MCP 配置的 env 里设置 MOONSHOT_BASE_URL(如 https://api.moonshot.cn/v1)");
|
|
31
|
+
// 1. 清理上次进程异常退出残留的临时图片
|
|
32
|
+
await cleanupOldTempImages();
|
|
33
|
+
// 2. 启动 HTTP 图片拦截代理(与 MCP 共存于同一进程)
|
|
34
|
+
try {
|
|
35
|
+
await startImageProxy();
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
console.error("[vision-mcp] 代理启动失败(不影响 MCP 功能):", err);
|
|
39
|
+
}
|
|
40
|
+
// 3. 启动 MCP 服务器
|
|
41
|
+
const server = new McpServer({
|
|
42
|
+
name: "vision-mcp-server",
|
|
43
|
+
version: "1.0.0",
|
|
44
|
+
});
|
|
45
|
+
registerDescribeImageTool(server, () => apiKey);
|
|
46
|
+
registerDescribeClipboardTool(server, () => apiKey);
|
|
47
|
+
const transport = new StdioServerTransport();
|
|
48
|
+
await server.connect(transport);
|
|
49
|
+
console.error("[vision-mcp] server running via stdio");
|
|
50
|
+
}
|
|
51
|
+
main().catch((err) => {
|
|
52
|
+
console.error("[vision-mcp] fatal:", err);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,SAAS,cAAc,CAAC,IAAY,EAAE,IAAY;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,oBAAoB,IAAI,UAAU,CAAC,CAAC;QAClD,OAAO,CAAC,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,yBAAyB;IACzB,MAAM,MAAM,GAAG,cAAc,CAC3B,kBAAkB,EAClB,qCAAqC,CACtC,CAAC;IACF,cAAc,CACZ,mBAAmB,EACnB,oEAAoE,CACrE,CAAC;IAEF,uBAAuB;IACvB,MAAM,oBAAoB,EAAE,CAAC;IAE7B,mCAAmC;IACnC,IAAI,CAAC;QACH,MAAM,eAAe,EAAE,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAC;IACzD,CAAC;IAED,gBAAgB;IAChB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,yBAAyB,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;IAChD,6BAA6B,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;IAEpD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;AACzD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function startImageProxy(): Promise<void>;
|