UNPKG

aliyun-bailian-mcp-server

Version:
237 lines (213 loc) 7.46 kB
/** * MCP服务器实现 * 遵循Model Context Protocol规范 */ const { v4: uuidv4 } = require('uuid'); const BailianClient = require('./bailian-client'); class MCPServer { constructor(apiKey, appId, baseUrl) { this.bailianClient = new BailianClient(apiKey, appId, baseUrl); this.sessions = new Map(); // 定义MCP工具 this.tools = [ { name: "chat_with_qwen", description: "与通义千问大模型对话,可解答各种问题,执行创作、分析等任务", input_schema: { type: "object", properties: { message: { type: "string", description: "发送给模型的消息内容" }, model: { type: "string", enum: ["qwen-plus", "qwen-max", "qwen-max-1201", "qwen-turbo"], description: "要使用的通义千问模型类型", default: "qwen-plus" }, temperature: { type: "number", description: "温度参数,控制输出的随机性,值越大回复越随机", default: 0.7 }, enable_search: { type: "boolean", description: "是否启用搜索增强", default: false } }, required: ["message"] } }, { name: "image_understanding", description: "解析图像内容,对图片进行分析、识别或描述", input_schema: { type: "object", properties: { image_url: { type: "string", description: "需要分析的图片URL地址" }, prompt: { type: "string", description: "引导模型对图片进行特定分析的提示词", default: "请描述这张图片" }, model: { type: "string", enum: ["qwen-vl-plus", "qwen-vl-max"], description: "要使用的多模态模型类型", default: "qwen-vl-plus" } }, required: ["image_url"] } } ]; } /** * 获取工具列表 * @returns {Object} 工具列表对象 */ listTools() { return { tools: this.tools }; } /** * 调用指定工具 * @param {string} toolName 工具名称 * @param {Object} parameters 参数对象 * @returns {Promise<Object>} 工具调用结果 */ async callTool(toolName, parameters = {}) { // 兼容处理:如果第一个参数是sessionId,则使用旧版API格式 let sessionId = null; if (arguments.length >= 2 && typeof arguments[0] === 'string' && typeof arguments[1] === 'string') { // 旧格式: callTool(sessionId, toolName, parameters) sessionId = arguments[0]; toolName = arguments[1]; parameters = arguments[2] || {}; console.log(`使用旧格式API调用: sessionId=${sessionId}, toolName=${toolName}`); } // 如果没有sessionId,生成一个新的 if (!sessionId) { sessionId = uuidv4(); console.log(`为工具调用生成新的会话ID: ${sessionId}`); } // 获取或创建会话 if (!this.sessions.has(sessionId)) { this.sessions.set(sessionId, { id: sessionId, createdAt: new Date(), lastUsedAt: new Date(), messages: [] }); console.log(`创建新会话: ${sessionId}`); } else { const session = this.sessions.get(sessionId); session.lastUsedAt = new Date(); console.log(`更新现有会话: ${sessionId}, 消息数: ${session.messages.length}`); } // 查找对应工具 const tool = this.tools.find(t => t.name === toolName); if (!tool) { console.error(`未找到工具: ${toolName}`); throw new Error(`未找到名为 ${toolName} 的工具`); } try { console.log(`开始调用工具: ${toolName}, 参数:`, JSON.stringify(parameters)); let result; // 根据工具类型调用不同API switch (toolName) { case 'chat_with_qwen': { const { message, model = 'qwen-plus', temperature = 0.7, enable_search = false } = parameters; // 获取当前会话 const session = this.sessions.get(sessionId); // 添加用户消息到历史 session.messages.push({ role: 'user', content: message }); // 调用API console.log(`调用百炼API, 模型: ${model}, 温度: ${temperature}, 联网搜索: ${enable_search}`); const response = await this.bailianClient.chatCompletion( session.messages, { modelName: model, temperature, enableSearch: enable_search } ); // 保存回复到会话历史 if (response.choices && response.choices.length > 0) { const assistantMessage = response.choices[0].message; session.messages.push(assistantMessage); console.log(`收到模型回复,消息长度: ${assistantMessage.content.length}`); } else { console.warn('API响应中没有找到choices或message'); } result = { result: { response: response.choices[0].message.content, model: model, session_id: sessionId } }; break; } case 'image_understanding': { const { image_url, prompt = '请描述这张图片', model = 'qwen-vl-plus' } = parameters; // 构建多模态消息 const multimodalMessage = [ { role: 'user', content: [ { type: 'text', text: prompt }, { type: 'image_url', image_url: { url: image_url } } ] } ]; // 调用API console.log(`调用多模态API, 模型: ${model}, 图片URL: ${image_url.substring(0, 50)}...`); const response = await this.bailianClient.chatCompletion( multimodalMessage, { modelName: model } ); result = { result: { response: response.choices[0].message.content, model: model } }; break; } default: console.error(`工具 ${toolName} 未实现`); throw new Error(`工具 ${toolName} 未实现`); } console.log(`工具调用成功: ${toolName}`); return result; } catch (error) { console.error(`调用工具 ${toolName} 失败:`, error); throw new Error(`工具调用失败: ${error.message}`); } } /** * 清理过期会话 * 默认清理2小时未使用的会话 */ cleanSessions(maxAge = 7200000) { const now = new Date(); let cleanCount = 0; for (const [sessionId, session] of this.sessions.entries()) { const lastUsedTime = session.lastUsedAt.getTime(); if (now.getTime() - lastUsedTime > maxAge) { this.sessions.delete(sessionId); cleanCount++; } } if (cleanCount > 0) { console.log(`已清理 ${cleanCount} 个过期会话,当前会话数: ${this.sessions.size}`); } } } module.exports = MCPServer;