luma-mcp 1.2.1 → 1.2.3
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/.github/workflows/release.yml +0 -17
- package/CHANGELOG.md +33 -0
- package/README.md +5 -1
- package/build/image-processor.d.ts +1 -2
- package/build/image-processor.d.ts.map +1 -1
- package/build/image-processor.js +61 -59
- package/build/image-processor.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.js +52 -60
- package/build/index.js.map +1 -1
- package/build/prompts.d.ts +1 -1
- package/build/prompts.d.ts.map +1 -1
- package/build/prompts.js +14 -28
- package/build/prompts.js.map +1 -1
- package/build/vision-client.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -17,18 +17,6 @@ jobs:
|
|
|
17
17
|
with:
|
|
18
18
|
fetch-depth: 0
|
|
19
19
|
|
|
20
|
-
- name: Setup Node.js
|
|
21
|
-
uses: actions/setup-node@v4
|
|
22
|
-
with:
|
|
23
|
-
node-version: '18'
|
|
24
|
-
registry-url: 'https://registry.npmjs.org'
|
|
25
|
-
|
|
26
|
-
- name: Install dependencies
|
|
27
|
-
run: npm ci
|
|
28
|
-
|
|
29
|
-
- name: Build
|
|
30
|
-
run: npm run build
|
|
31
|
-
|
|
32
20
|
- name: Extract version from tag
|
|
33
21
|
id: version
|
|
34
22
|
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
|
@@ -59,8 +47,3 @@ jobs:
|
|
|
59
47
|
prerelease: false
|
|
60
48
|
env:
|
|
61
49
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
62
|
-
|
|
63
|
-
- name: Publish to npm
|
|
64
|
-
run: npm publish --access public
|
|
65
|
-
env:
|
|
66
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.2.3] - 2025-11-21
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- 🧹 **代码清理**: 移除 Claude 特定调试注释和实验性代码
|
|
9
|
+
- 📝 **工具描述优化**: 简化和专业化工具说明,提升 AI 模型调用成功率
|
|
10
|
+
- 🔧 **路径处理通用化**: 重构 @ 前缀路径处理,移除平台特定命名
|
|
11
|
+
|
|
12
|
+
### Technical Details
|
|
13
|
+
- 移除 Claude 资源读取相关的实验性代码
|
|
14
|
+
- 重命名 `stripAtPrefix()` 为 `normalizeImageSourcePath()`
|
|
15
|
+
- 清理所有客户端适配器中的调试日志和注释
|
|
16
|
+
- 统一代码风格和注释规范
|
|
17
|
+
|
|
18
|
+
## [1.2.2] - 2025-11-20
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- ✨ **@ 路径支持**: 自动处理 Claude Code 的 @ 文件引用前缀,修复第一次调用失败的问题
|
|
22
|
+
- 📝 **智能 Prompt**: 通用请求自动添加详细指引,保证全面分析
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
- 🔧 **Prompt 统一**: 简化为单一通用 prompt,智能处理不同场景
|
|
26
|
+
- ✨ **表述优化**: 融合 Minimax 的经典表述,强调“不遗漏细节”和“完整提取”
|
|
27
|
+
- 📚 **文档更新**: 更新项目结构,添加 qwen-client.ts 和测试文件
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
- 🐛 **@ 路径问题**: 修复 Claude Code 中 `@folder/image.png` 导致的路径错误
|
|
31
|
+
- 🐛 **编译错误**: 修复 image-processor.ts 中重复声明的变量
|
|
32
|
+
|
|
33
|
+
### Technical Details
|
|
34
|
+
- 新增 `stripAtPrefix()` 函数处理 Claude Code 的文件引用语法
|
|
35
|
+
- 简化 `buildAnalysisPrompt()` 从两套逻辑到单一逻辑
|
|
36
|
+
- 添加智能请求检测,自动补充详细分析指引
|
|
37
|
+
|
|
5
38
|
## [1.2.1] - 2025-11-18
|
|
6
39
|
|
|
7
40
|
### Changed
|
package/README.md
CHANGED
|
@@ -412,13 +412,17 @@ luma-mcp/
|
|
|
412
412
|
│ ├── vision-client.ts # 视觉模型客户端接口
|
|
413
413
|
│ ├── zhipu-client.ts # GLM-4.5V API 客户端
|
|
414
414
|
│ ├── siliconflow-client.ts # DeepSeek-OCR API 客户端
|
|
415
|
+
│ ├── qwen-client.ts # Qwen3-VL API 客户端
|
|
415
416
|
│ ├── image-processor.ts # 图片处理
|
|
416
417
|
│ ├── prompts.ts # 提示词模板
|
|
417
418
|
│ └── utils/
|
|
418
419
|
│ ├── logger.ts # 日志工具
|
|
419
420
|
│ └── helpers.ts # 工具函数
|
|
420
421
|
├── test/
|
|
421
|
-
│
|
|
422
|
+
│ ├── test-local.ts # 本地测试脚本
|
|
423
|
+
│ ├── test-qwen.ts # Qwen 测试脚本
|
|
424
|
+
│ ├── test-deepseek-raw.ts # DeepSeek 原始测试脚本
|
|
425
|
+
│ └── test-data-uri.ts # Data URI 测试脚本
|
|
422
426
|
├── docs/
|
|
423
427
|
│ ├── design.md # 设计文档
|
|
424
428
|
│ ├── installation.md # 安装指南
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-processor.d.ts","sourceRoot":"","sources":["../src/image-processor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"image-processor.d.ts","sourceRoot":"","sources":["../src/image-processor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiDH;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAAW,GACrB,OAAO,CAAC,IAAI,CAAC,CAsCf;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkCtE"}
|
package/build/image-processor.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 图片处理工具
|
|
3
|
-
*
|
|
4
|
-
* 支持本地文件和远程URL
|
|
3
|
+
* 负责读取、压缩和编码图片(支持本地文件和远程 URL)
|
|
5
4
|
*/
|
|
6
|
-
import { readFile, stat } from
|
|
7
|
-
import sharp from
|
|
8
|
-
import { isUrl } from
|
|
9
|
-
import { logger } from
|
|
5
|
+
import { readFile, stat } from "fs/promises";
|
|
6
|
+
import sharp from "sharp";
|
|
7
|
+
import { isUrl } from "./utils/helpers.js";
|
|
8
|
+
import { logger } from "./utils/logger.js";
|
|
10
9
|
// 判断是否为 Data URI(data:image/png;base64,....)
|
|
11
10
|
function isDataUri(input) {
|
|
12
|
-
return typeof input ===
|
|
11
|
+
return (typeof input === "string" &&
|
|
12
|
+
input.startsWith("data:") &&
|
|
13
|
+
/;base64,/.test(input));
|
|
13
14
|
}
|
|
14
15
|
// 从 Data URI 获取 mimeType
|
|
15
16
|
function getMimeFromDataUri(input) {
|
|
@@ -19,7 +20,7 @@ function getMimeFromDataUri(input) {
|
|
|
19
20
|
// 估算 Data URI 的原始字节大小(不含头部)
|
|
20
21
|
function estimateBytesFromDataUri(input) {
|
|
21
22
|
try {
|
|
22
|
-
const base64 = input.split(
|
|
23
|
+
const base64 = input.split(",")[1] || "";
|
|
23
24
|
// base64 长度 * 3/4,忽略 padding 近似即可
|
|
24
25
|
return Math.floor((base64.length * 3) / 4);
|
|
25
26
|
}
|
|
@@ -27,47 +28,49 @@ function estimateBytesFromDataUri(input) {
|
|
|
27
28
|
return 0;
|
|
28
29
|
}
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* 规范化本地图像路径(例如去掉前缀符号)
|
|
33
|
+
* 某些客户端会使用 "@path/to/file" 作为文件引用,这里统一转换为真实路径
|
|
34
|
+
*/
|
|
35
|
+
function normalizeImageSourcePath(source) {
|
|
36
|
+
if (typeof source === "string" && source.startsWith("@")) {
|
|
37
|
+
const normalized = source.slice(1);
|
|
38
|
+
logger.debug("Normalized @-prefixed image path", {
|
|
39
|
+
original: source,
|
|
40
|
+
normalized,
|
|
41
|
+
});
|
|
42
|
+
return normalized;
|
|
43
|
+
}
|
|
44
|
+
return source;
|
|
45
|
+
}
|
|
30
46
|
/**
|
|
31
47
|
* 验证图片来源(文件或URL)
|
|
32
48
|
*/
|
|
33
49
|
export async function validateImageSource(imageSource, maxSizeMB = 10) {
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
throw new Error(`Unsupported data URI mimeType: ${mime || 'unknown'}. Supported: ${allowed.join(', ')}`);
|
|
40
|
-
}
|
|
41
|
-
const bytes = estimateBytesFromDataUri(imageSource);
|
|
42
|
-
const sizeMB = bytes / (1024 * 1024);
|
|
43
|
-
if (sizeMB > maxSizeMB) {
|
|
44
|
-
throw new Error(`Image data URI too large: ${sizeMB.toFixed(2)}MB (max: ${maxSizeMB}MB)`);
|
|
45
|
-
}
|
|
46
|
-
logger.debug('Image source is data URI, validated', { mime, sizeMB: sizeMB.toFixed(2) });
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
// 如果是URL,直接返回
|
|
50
|
-
if (isUrl(imageSource)) {
|
|
51
|
-
logger.debug('Image source is URL, skipping validation', { imageSource });
|
|
50
|
+
// 先规范化可能带有前缀符号的本地路径(如 "@image.png")
|
|
51
|
+
const normalizedSource = normalizeImageSourcePath(imageSource);
|
|
52
|
+
// 如果是 URL,直接返回
|
|
53
|
+
if (isUrl(normalizedSource)) {
|
|
54
|
+
logger.debug("Image source is URL, skipping validation");
|
|
52
55
|
return;
|
|
53
56
|
}
|
|
54
57
|
// 验证本地文件
|
|
55
58
|
try {
|
|
56
|
-
const stats = await stat(
|
|
59
|
+
const stats = await stat(normalizedSource);
|
|
57
60
|
const fileSizeMB = stats.size / (1024 * 1024);
|
|
58
61
|
if (fileSizeMB > maxSizeMB) {
|
|
59
62
|
throw new Error(`Image file too large: ${fileSizeMB.toFixed(2)}MB (max: ${maxSizeMB}MB)`);
|
|
60
63
|
}
|
|
61
64
|
// 验证文件格式
|
|
62
|
-
const ext =
|
|
63
|
-
const supportedFormats = [
|
|
65
|
+
const ext = normalizedSource.toLowerCase().split(".").pop();
|
|
66
|
+
const supportedFormats = ["jpg", "jpeg", "png", "webp", "gif"];
|
|
64
67
|
if (!ext || !supportedFormats.includes(ext)) {
|
|
65
|
-
throw new Error(`Unsupported image format: ${ext}. Supported: ${supportedFormats.join(
|
|
68
|
+
throw new Error(`Unsupported image format: ${ext}. Supported: ${supportedFormats.join(", ")}`);
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
catch (error) {
|
|
69
|
-
if (error.code ===
|
|
70
|
-
throw new Error(`Image file not found: ${
|
|
72
|
+
if (error.code === "ENOENT") {
|
|
73
|
+
throw new Error(`Image file not found: ${normalizedSource}`);
|
|
71
74
|
}
|
|
72
75
|
throw error;
|
|
73
76
|
}
|
|
@@ -77,30 +80,29 @@ export async function validateImageSource(imageSource, maxSizeMB = 10) {
|
|
|
77
80
|
*/
|
|
78
81
|
export async function imageToBase64(imagePath) {
|
|
79
82
|
try {
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (isUrl(imagePath)) {
|
|
87
|
-
logger.info('Using remote image URL', { url: imagePath });
|
|
88
|
-
return imagePath;
|
|
83
|
+
// 规范化本地路径(处理可能的前缀符号)
|
|
84
|
+
const normalizedPath = normalizeImageSourcePath(imagePath);
|
|
85
|
+
// 如果是 URL,直接返回
|
|
86
|
+
if (isUrl(normalizedPath)) {
|
|
87
|
+
logger.info("Using remote image URL", { url: normalizedPath });
|
|
88
|
+
return normalizedPath;
|
|
89
89
|
}
|
|
90
90
|
// 本地文件:读取并编码
|
|
91
|
-
let imageBuffer = await readFile(
|
|
91
|
+
let imageBuffer = await readFile(normalizedPath);
|
|
92
92
|
// 检查文件大小,如果超过 2MB 则压缩
|
|
93
93
|
if (imageBuffer.length > 2 * 1024 * 1024) {
|
|
94
|
-
logger.info(
|
|
94
|
+
logger.info("Compressing large image", {
|
|
95
|
+
originalSize: `${(imageBuffer.length / (1024 * 1024)).toFixed(2)}MB`,
|
|
96
|
+
});
|
|
95
97
|
imageBuffer = Buffer.from(await compressImage(imageBuffer));
|
|
96
98
|
}
|
|
97
99
|
// 转换为 base64
|
|
98
|
-
const base64 = imageBuffer.toString(
|
|
99
|
-
const mimeType = getMimeType(
|
|
100
|
+
const base64 = imageBuffer.toString("base64");
|
|
101
|
+
const mimeType = getMimeType(normalizedPath);
|
|
100
102
|
return `data:${mimeType};base64,${base64}`;
|
|
101
103
|
}
|
|
102
104
|
catch (error) {
|
|
103
|
-
throw new Error(`Failed to process image: ${error instanceof Error ? error.message :
|
|
105
|
+
throw new Error(`Failed to process image: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
/**
|
|
@@ -109,8 +111,8 @@ export async function imageToBase64(imagePath) {
|
|
|
109
111
|
async function compressImage(imageBuffer) {
|
|
110
112
|
return sharp(imageBuffer)
|
|
111
113
|
.resize(2048, 2048, {
|
|
112
|
-
fit:
|
|
113
|
-
withoutEnlargement: true
|
|
114
|
+
fit: "inside",
|
|
115
|
+
withoutEnlargement: true,
|
|
114
116
|
})
|
|
115
117
|
.jpeg({ quality: 85 })
|
|
116
118
|
.toBuffer();
|
|
@@ -119,19 +121,19 @@ async function compressImage(imageBuffer) {
|
|
|
119
121
|
* 根据文件扩展名获取 MIME 类型
|
|
120
122
|
*/
|
|
121
123
|
function getMimeType(filePath) {
|
|
122
|
-
const ext = filePath.toLowerCase().split(
|
|
124
|
+
const ext = filePath.toLowerCase().split(".").pop();
|
|
123
125
|
switch (ext) {
|
|
124
|
-
case
|
|
125
|
-
case
|
|
126
|
-
return
|
|
127
|
-
case
|
|
128
|
-
return
|
|
129
|
-
case
|
|
130
|
-
return
|
|
131
|
-
case
|
|
132
|
-
return
|
|
126
|
+
case "jpg":
|
|
127
|
+
case "jpeg":
|
|
128
|
+
return "image/jpeg";
|
|
129
|
+
case "png":
|
|
130
|
+
return "image/png";
|
|
131
|
+
case "webp":
|
|
132
|
+
return "image/webp";
|
|
133
|
+
case "gif":
|
|
134
|
+
return "image/gif";
|
|
133
135
|
default:
|
|
134
|
-
return
|
|
136
|
+
return "image/jpeg"; // 默认使用 jpeg
|
|
135
137
|
}
|
|
136
138
|
}
|
|
137
139
|
//# sourceMappingURL=image-processor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-processor.js","sourceRoot":"","sources":["../src/image-processor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"image-processor.js","sourceRoot":"","sources":["../src/image-processor.ts"],"names":[],"mappings":"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"}
|
package/build/index.d.ts
CHANGED
package/build/index.js
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* Luma MCP Server
|
|
4
|
-
*
|
|
4
|
+
* 通用图像理解 MCP 服务器,支持多家视觉模型提供商
|
|
5
5
|
*/
|
|
6
6
|
// 第一件事:重定向console到stderr,避免污染MCP的stdout
|
|
7
|
-
import { setupConsoleRedirection, logger } from
|
|
7
|
+
import { setupConsoleRedirection, logger } from "./utils/logger.js";
|
|
8
8
|
setupConsoleRedirection();
|
|
9
|
-
import { McpServer } from
|
|
10
|
-
import { StdioServerTransport } from
|
|
11
|
-
import { z } from
|
|
12
|
-
import { loadConfig } from
|
|
13
|
-
import { ZhipuClient } from
|
|
14
|
-
import { SiliconFlowClient } from
|
|
15
|
-
import { QwenClient } from
|
|
16
|
-
import { imageToBase64, validateImageSource } from
|
|
17
|
-
import { buildAnalysisPrompt } from
|
|
18
|
-
import { withRetry, createSuccessResponse, createErrorResponse } from
|
|
9
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import { loadConfig } from "./config.js";
|
|
13
|
+
import { ZhipuClient } from "./zhipu-client.js";
|
|
14
|
+
import { SiliconFlowClient } from "./siliconflow-client.js";
|
|
15
|
+
import { QwenClient } from "./qwen-client.js";
|
|
16
|
+
import { imageToBase64, validateImageSource } from "./image-processor.js";
|
|
17
|
+
import { buildAnalysisPrompt } from "./prompts.js";
|
|
18
|
+
import { withRetry, createSuccessResponse, createErrorResponse, } from "./utils/helpers.js";
|
|
19
19
|
/**
|
|
20
20
|
* 创建 MCP 服务器
|
|
21
21
|
*/
|
|
22
22
|
async function createServer() {
|
|
23
|
-
logger.info(
|
|
23
|
+
logger.info("Initializing Luma MCP Server");
|
|
24
24
|
// 加载配置
|
|
25
25
|
const config = loadConfig();
|
|
26
26
|
// 根据配置选择模型客户端
|
|
27
27
|
let visionClient;
|
|
28
|
-
if (config.provider ===
|
|
28
|
+
if (config.provider === "siliconflow") {
|
|
29
29
|
visionClient = new SiliconFlowClient(config.apiKey, config.model, config.maxTokens, config.temperature);
|
|
30
30
|
}
|
|
31
|
-
else if (config.provider ===
|
|
31
|
+
else if (config.provider === "qwen") {
|
|
32
32
|
visionClient = new QwenClient(config.apiKey, config.model, config.maxTokens, config.temperature);
|
|
33
33
|
}
|
|
34
34
|
else {
|
|
35
35
|
visionClient = new ZhipuClient(config.apiKey, config.model, config.maxTokens, config.temperature, config.topP);
|
|
36
36
|
}
|
|
37
|
-
logger.info(
|
|
37
|
+
logger.info("Vision client initialized", {
|
|
38
38
|
provider: config.provider,
|
|
39
|
-
model: visionClient.getModelName()
|
|
39
|
+
model: visionClient.getModelName(),
|
|
40
40
|
});
|
|
41
41
|
// 创建服务器 - 使用 McpServer
|
|
42
42
|
const server = new McpServer({
|
|
43
|
-
name:
|
|
44
|
-
version:
|
|
43
|
+
name: "luma-mcp",
|
|
44
|
+
version: "1.0.0",
|
|
45
45
|
}, {
|
|
46
46
|
capabilities: {
|
|
47
47
|
tools: {},
|
|
@@ -53,53 +53,42 @@ async function createServer() {
|
|
|
53
53
|
await validateImageSource(imageSource);
|
|
54
54
|
// 2. 处理图片(读取或返回URL)
|
|
55
55
|
const imageDataUrl = await imageToBase64(imageSource);
|
|
56
|
-
// 3.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
? prompt // DeepSeek-OCR: 直接使用原始 prompt
|
|
61
|
-
: buildAnalysisPrompt(prompt); // Qwen/GLM: 使用结构化 prompt
|
|
56
|
+
// 3. 构建分析提示词(部分提供商使用原始提示词,部分使用结构化提示词)
|
|
57
|
+
const fullPrompt = config.provider === "siliconflow"
|
|
58
|
+
? prompt
|
|
59
|
+
: buildAnalysisPrompt(prompt);
|
|
62
60
|
// 4. 调用视觉模型分析图片
|
|
63
61
|
return await visionClient.analyzeImage(imageDataUrl, fullPrompt);
|
|
64
62
|
}, 2, // 最多重试2次
|
|
65
63
|
1000 // 初始延补1秒
|
|
66
64
|
);
|
|
67
65
|
// 注册工具 - 使用 McpServer.tool() API
|
|
68
|
-
server.tool(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
3. 用户粘贴了图片到聊天框(会生成临时路径)
|
|
77
|
-
4. 用户要求分析、理解、查看、识别图片内容
|
|
78
|
-
5. 用户询问关于图片中的代码、UI、错误信息等问题
|
|
79
|
-
|
|
80
|
-
**支持场景**:代码截图、UI界面、错误信息、通用图片分析。
|
|
81
|
-
**支持格式**:JPG、PNG、WebP、GIF。
|
|
82
|
-
**支持来源**:本地文件、远程URL、临时文件(包括截图)。
|
|
83
|
-
|
|
84
|
-
如果你是不支持视觉的AI模型,看到图片路径时应主动调用此工具来分析图片内容。`, {
|
|
85
|
-
image_source: z.string().describe('图片来源:支持三种格式:1) 本地文件路径(含临时路径)、2) 远程URL(https://)、3) Data URI(data:image/png;base64,...)。支持 PNG/JPG/WebP/GIF。例如:"./image.png"、"/tmp/screenshot.png"、"C:\\Users\\...\\image.jpg"、"https://example.com/pic.jpg"、"data:image/png;base64,iVBORw0KG..."'),
|
|
86
|
-
prompt: z.string().describe('必须:详细的分析指令。如果用户没有提供具体问题,默认使用:"请详细分析这张图片的内容"。对于具体任务:代码分析、UI设计、错误诊断、文字识别等,应提供明确的指令。例如:"这段代码为什么报错?"、"分析这个UI的布局和风格"、"识别图片中的所有文字"'),
|
|
66
|
+
server.tool("analyze_image", "图像分析工具:对截图、设计稿、照片等图片进行详细理解和中文描述(支持本地文件和 HTTP(S) 图片 URL,最大 10MB)", {
|
|
67
|
+
image_source: z
|
|
68
|
+
.string()
|
|
69
|
+
.describe("要分析的图片来源:本地文件路径或 HTTP(S) 图片 URL(支持 PNG、JPG、JPEG、WebP、GIF,最大 10MB)"),
|
|
70
|
+
prompt: z
|
|
71
|
+
.string()
|
|
72
|
+
.optional()
|
|
73
|
+
.describe("可选的任务说明,例如“帮我详细描述这张 UI 设计图的布局和组件”。如果不填,将自动生成整图的详细中文描述。"),
|
|
87
74
|
}, async (params) => {
|
|
88
75
|
try {
|
|
89
|
-
|
|
76
|
+
// 如果没有提供 prompt,使用默认值
|
|
77
|
+
const prompt = params.prompt || "请详细分析这张图片的内容";
|
|
78
|
+
logger.info("Analyzing image", {
|
|
90
79
|
source: params.image_source,
|
|
91
|
-
prompt
|
|
80
|
+
prompt,
|
|
92
81
|
});
|
|
93
82
|
// 执行分析(带重试)
|
|
94
|
-
const result = await analyzeWithRetry(params.image_source,
|
|
95
|
-
logger.info(
|
|
83
|
+
const result = await analyzeWithRetry(params.image_source, prompt);
|
|
84
|
+
logger.info("Image analysis completed successfully");
|
|
96
85
|
return createSuccessResponse(result);
|
|
97
86
|
}
|
|
98
87
|
catch (error) {
|
|
99
|
-
logger.error(
|
|
88
|
+
logger.error("Image analysis failed", {
|
|
100
89
|
error: error instanceof Error ? error.message : String(error),
|
|
101
90
|
});
|
|
102
|
-
return createErrorResponse(error instanceof Error ? error.message :
|
|
91
|
+
return createErrorResponse(error instanceof Error ? error.message : "Unknown error");
|
|
103
92
|
}
|
|
104
93
|
});
|
|
105
94
|
return server;
|
|
@@ -112,30 +101,33 @@ async function main() {
|
|
|
112
101
|
const server = await createServer();
|
|
113
102
|
const transport = new StdioServerTransport();
|
|
114
103
|
await server.connect(transport);
|
|
115
|
-
logger.info(
|
|
104
|
+
logger.info("Luma MCP server started successfully on stdio");
|
|
116
105
|
}
|
|
117
106
|
catch (error) {
|
|
118
|
-
logger.error(
|
|
107
|
+
logger.error("Failed to start Luma MCP server", {
|
|
119
108
|
error: error instanceof Error ? error.message : String(error),
|
|
120
109
|
});
|
|
121
110
|
process.exit(1);
|
|
122
111
|
}
|
|
123
112
|
}
|
|
124
113
|
// 全局错误处理
|
|
125
|
-
process.on(
|
|
126
|
-
logger.error(
|
|
114
|
+
process.on("uncaughtException", (error) => {
|
|
115
|
+
logger.error("Uncaught exception", {
|
|
116
|
+
error: error.message,
|
|
117
|
+
stack: error.stack,
|
|
118
|
+
});
|
|
127
119
|
process.exit(1);
|
|
128
120
|
});
|
|
129
|
-
process.on(
|
|
130
|
-
logger.error(
|
|
121
|
+
process.on("unhandledRejection", (reason) => {
|
|
122
|
+
logger.error("Unhandled rejection", { reason });
|
|
131
123
|
process.exit(1);
|
|
132
124
|
});
|
|
133
|
-
process.on(
|
|
134
|
-
logger.info(
|
|
125
|
+
process.on("SIGINT", () => {
|
|
126
|
+
logger.info("Received SIGINT, shutting down gracefully");
|
|
135
127
|
process.exit(0);
|
|
136
128
|
});
|
|
137
|
-
process.on(
|
|
138
|
-
logger.info(
|
|
129
|
+
process.on("SIGTERM", () => {
|
|
130
|
+
logger.info("Received SIGTERM, shutting down gracefully");
|
|
139
131
|
process.exit(0);
|
|
140
132
|
});
|
|
141
133
|
main();
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;GAGG;AAEH,wCAAwC;AACxC,OAAO,EAAE,uBAAuB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACpE,uBAAuB,EAAE,CAAC;AAE1B,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/build/prompts.d.ts
CHANGED
package/build/prompts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAuB9D"}
|
package/build/prompts.js
CHANGED
|
@@ -4,40 +4,26 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* 构建图片分析提示词
|
|
6
6
|
*/
|
|
7
|
-
export function buildAnalysisPrompt(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
export function buildAnalysisPrompt(userPrompt) {
|
|
8
|
+
// 判断是否为通用请求(过于简单或模糊)
|
|
9
|
+
const isGenericRequest = /^(分析|查看|识别|描述|理解|看一下|看看|分析一下|请分析|analyze|describe|view|check)/i.test(userPrompt)
|
|
10
|
+
&& userPrompt.length < 30;
|
|
11
|
+
// 如果是通用请求,添加详细指引
|
|
12
|
+
const finalPrompt = isGenericRequest
|
|
13
|
+
? `请详细分析这张图片的内容,包括图片中的主要元素、文字、场景等所有可见信息。`
|
|
14
|
+
: userPrompt;
|
|
15
|
+
return `
|
|
11
16
|
<image_analysis>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
${question}
|
|
17
|
+
${finalPrompt}
|
|
15
18
|
|
|
16
19
|
分析要求:
|
|
17
|
-
1.
|
|
18
|
-
2.
|
|
19
|
-
3.
|
|
20
|
-
4.
|
|
21
|
-
5. 具体可执行:如果涉及代码或问题,提供具体的解决方案
|
|
22
|
-
|
|
23
|
-
请开始分析:
|
|
24
|
-
</image_analysis>
|
|
25
|
-
`.trim();
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
// 没有问题时,通用描述
|
|
29
|
-
return `
|
|
30
|
-
<image_analysis>
|
|
31
|
-
请详细描述这张图片的内容,包括:
|
|
32
|
-
|
|
33
|
-
1. **主要内容**:图片展示了什么
|
|
34
|
-
2. **关键元素**:重要的视觉元素、文字、符号
|
|
35
|
-
3. **布局结构**:元素的组织和排列
|
|
36
|
-
4. **文字内容**:提取所有可见文字
|
|
20
|
+
1. **系统性观察**:从整体到细节,全面观察图片内容(不遗漏任何细节)
|
|
21
|
+
2. **准确识别**:精确识别并完整提取所有文字、符号、代码、数字等
|
|
22
|
+
3. **结构化输出**:使用清晰的标题和列表组织信息
|
|
23
|
+
4. **具体可执行**:如果涉及问题或代码,提供具体的解决方案
|
|
37
24
|
|
|
38
25
|
请用中文清晰描述。
|
|
39
26
|
</image_analysis>
|
|
40
27
|
`.trim();
|
|
41
|
-
}
|
|
42
28
|
}
|
|
43
29
|
//# sourceMappingURL=prompts.js.map
|
package/build/prompts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,qBAAqB;IACrB,MAAM,gBAAgB,GAAG,gEAAgE,CAAC,IAAI,CAAC,UAAU,CAAC;WACrG,UAAU,CAAC,MAAM,GAAG,EAAE,CAAC;IAE5B,iBAAiB;IACjB,MAAM,WAAW,GAAG,gBAAgB;QAClC,CAAC,CAAC,uCAAuC;QACzC,CAAC,CAAC,UAAU,CAAC;IAEf,OAAO;;EAEP,WAAW;;;;;;;;;;CAUZ,CAAC,IAAI,EAAE,CAAC;AACT,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vision-client.d.ts","sourceRoot":"","sources":["../src/vision-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,YAAY,
|
|
1
|
+
{"version":3,"file":"vision-client.d.ts","sourceRoot":"","sources":["../src/vision-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,YAAY,CACV,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB;;OAEG;IACH,YAAY,IAAI,MAAM,CAAC;CACxB"}
|
package/package.json
CHANGED