@mcpcn/image-understanding-mcp
Version:
智谱GLM-4V-Plus-0111 图片内容理解MCP工具
178 lines • 6.83 kB
JavaScript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
import { ImageUnderstandingTool } from './tools/image-recognition.js';
import { DEFAULT_VISION_MODEL, SUPPORTED_VISION_MODELS } from './config.js';
// 从环境变量获取API密钥
const API_KEY = process.env.ZHIPU_API_KEY;
if (!API_KEY) {
console.error('错误:未找到API密钥。请设置环境变量 GLM_API_KEY 或 ZHIPU_API_KEY');
process.exit(1);
}
// 创建图片理解工具实例
const imageUnderstanding = new ImageUnderstandingTool(API_KEY);
// 创建MCP服务器
const server = new Server({
name: 'image-understanding-mcp',
version: '1.0.0',
}, {
capabilities: {
tools: {},
},
});
// 注册工具列表处理器
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'analyze_image',
description: `使用智谱视觉模型(默认:${DEFAULT_VISION_MODEL})分析图片内容,支持通过URL上传图片`,
inputSchema: {
type: 'object',
properties: {
imageUrl: {
type: 'string',
description: '图片的URL地址(支持HTTP/HTTPS链接和base64编码)',
},
prompt: {
type: 'string',
description: '对图片分析的具体要求或问题(可选,默认为通用描述)',
default: '请详细描述这张图片的内容',
},
model: {
type: 'string',
enum: SUPPORTED_VISION_MODELS,
description: `使用的模型版本(默认:${DEFAULT_VISION_MODEL},可通过环境变量GLM_VISION_MODEL覆盖)`,
default: DEFAULT_VISION_MODEL,
},
temperature: {
type: 'number',
minimum: 0,
maximum: 1,
description: '生成文本的随机性控制(0-1,可选,默认0.7)',
default: 0.7,
},
maxTokens: {
type: 'number',
minimum: 1,
maximum: 4096,
description: '最大输出token数量(可选,默认1024)',
default: 1024,
},
},
required: ['imageUrl'],
},
},
],
};
});
// 注册工具调用处理器
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case 'analyze_image': {
// 校验并收窄参数类型
const params = (args ?? {});
if (!('imageUrl' in (args ?? {}))) {
throw new Error('imageUrl参数是必需的');
}
if (!params.imageUrl) {
throw new Error('imageUrl参数是必需的');
}
const result = await imageUnderstanding.analyzeImage(params);
if (result.success) {
return {
content: [
{
type: 'text',
text: JSON.stringify({
success: true,
analysis: result.analysis,
model: result.model,
tokenUsage: result.tokenUsage,
}, null, 2),
},
],
};
}
else {
return {
content: [
{
type: 'text',
text: JSON.stringify({
success: false,
error: result.error,
model: result.model,
}, null, 2),
},
],
isError: true,
};
}
}
default:
throw new Error(`未知的工具: ${name}`);
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : '未知错误';
return {
content: [
{
type: 'text',
text: JSON.stringify({
success: false,
error: errorMessage,
}, null, 2),
},
],
isError: true,
};
}
});
// 启动服务器
async function main() {
console.error(`智谱图片内容理解MCP服务器启动中(默认模型:${DEFAULT_VISION_MODEL})...`);
// 验证API密钥
try {
const isValid = await imageUnderstanding.validateApiKey();
if (!isValid) {
console.error('警告:API密钥验证失败,请检查您的GLM_API_KEY或ZHIPU_API_KEY环境变量');
}
else {
console.error('API密钥验证成功');
}
}
catch (error) {
console.error('API密钥验证时出现错误,但服务器将继续启动');
}
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('服务器已启动,等待连接...');
}
// 处理未捕获的异常
process.on('uncaughtException', (error) => {
console.error('未捕获的异常:', error);
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的Promise拒绝:', reason);
process.exit(1);
});
// 优雅关闭
process.on('SIGINT', () => {
console.error('接收到SIGINT信号,正在关闭服务器...');
process.exit(0);
});
process.on('SIGTERM', () => {
console.error('接收到SIGTERM信号,正在关闭服务器...');
process.exit(0);
});
main().catch((error) => {
console.error('服务器启动失败:', error);
process.exit(1);
});
//# sourceMappingURL=index.js.map