# MCP 工具调用完整示例 ## 概述 本文档展示 Cherry Studio 架构风格的 MCP 工具调用流程,通过"发布小红书文章"的实际例子,详细说明 AI 如何理解用户意图、生成内容、并自动调用 MCP 工具。 ## 实现架构 ### 核心流程 ``` 用户输入 ↓ 获取 MCP 工具 (带服务器名称前缀) ↓ 添加 System Prompt (指导 AI 使用工具) ↓ AI 理解意图 + 生成内容 ↓ AI 调用工具 (OpenAI Function Calling) ↓ 解析工具名称 (serverName__toolName) ↓ 执行 MCP 工具 ↓ 工具结果返回 ↓ AI 生成友好回复 ``` ### 关键创新点 1. **工具名称前缀**: `serverName__toolName` 格式避免多服务器工具名冲突 2. **System Prompt**: 详细的工具使用指南,让 AI 理解如何创作和调用 3. **参数自动注入**: AI 根据用户意图自动生成完整参数 4. **多轮对话**: 支持工具结果继续对话 ## 完整示例:发布小红书文章 ### 用户输入 ``` 用户: 帮我发布小红书文章,内容是:如何制作一道酸菜鱼 ``` ### 步骤 1: 获取 MCP 工具 假设连接了名为 `xiaohongshu` 的 MCP 服务器,提供以下工具: ```json { "name": "public_content", "description": "发布内容到小红书平台", "inputSchema": { "type": "object", "properties": { "title": { "type": "string", "description": "文章标题,吸引眼球且相关" }, "content": { "type": "string", "description": "文章正文,Markdown 格式" }, "tags": { "type": "array", "description": "标签列表,3-5个", "items": { "type": "string" } }, "category": { "type": "string", "description": "分类,如美食、生活、旅游等" } }, "required": ["title", "content", "tags", "category"] } } ``` ### 步骤 2: 转换为 OpenAI 格式(带前缀) ```typescript // chatService.ts - convertToolsToOpenAIFormat() { type: 'function', function: { name: 'xiaohongshu__public_content', // 添加服务器前缀 description: '发布内容到小红书平台', parameters: { ...inputSchema } } } ``` ### 步骤 3: 生成 System Prompt ```typescript // chatService.ts - createSystemPromptWithTools() 你是一个智能助手,可以使用以下工具完成任务: • xiaohongshu__public_content 描述: 发布内容到小红书平台 参数: - title [必填]: 文章标题,吸引眼球且相关 - content [必填]: 文章正文,Markdown 格式 - tags [必填]: 标签列表,3-5个 - category [必填]: 分类,如美食、生活、旅游等 使用指南: 1. 当用户需要完成某个任务时,请分析哪个工具最合适 2. 如果需要发布内容(如文章、笔记等),请根据用户意图创作完整的内容 3. 为内容生成合适的标题、正文、标签等所有必需参数 4. 自动调用相应工具,将生成的内容作为参数传递 5. 根据工具执行结果,给用户友好的反馈 注意事项: - 保持内容质量和平台特色 - 标签要相关且有吸引力 - 分类要准确 - 如果工具执行失败,给出明确的错误说明和建议 当前连接的 MCP 服务器: xiaohongshu ``` ### 步骤 4: 发送请求到 LLM ```typescript // modelServiceManager.ts - sendChatRequestStream() const request = { model: 'gpt-4', messages: [ { role: 'system', content: '你是一个智能助手,可以使用以下工具...' // System Prompt }, { role: 'user', content: '帮我发布小红书文章,内容是:如何制作一道酸菜鱼' } ], tools: [ { type: 'function', function: { name: 'xiaohongshu__public_content', description: '发布内容到小红书平台', parameters: { ... } } } ], tool_choice: 'auto', stream: true } ``` ### 步骤 5: AI 理解 + 生成内容 + 调用工具 AI 响应(SSE 流式返回): ```json // 第一部分:AI 思考过程(可选) { "choices": [{ "delta": { "content": "好的,我来帮你创作一篇关于酸菜鱼制作的小红书文章并发布。" } }] } // 第二部分:工具调用 { "choices": [{ "delta": { "tool_calls": [ { "id": "call_abc123", "type": "function", "function": { "name": "xiaohongshu__public_content", "arguments": { "title": "🐟 超详细!家常酸菜鱼做法,10分钟学会!", "content": "# 酸菜鱼制作教程\n\n## 所需食材\n- 草鱼1条(约1.5kg)\n- 酸菜200g\n- 姜片、蒜瓣适量...\n\n## 制作步骤\n\n### 1. 处理鱼肉\n...", "tags": ["美食教程", "酸菜鱼", "家常菜", "川菜", "烹饪技巧"], "category": "美食" } } } ] }, "finish_reason": "tool_calls" }] } ``` ### 步骤 6: 解析工具名称 ```typescript // chatService.ts - executeToolCalls() const fullFunctionName = 'xiaohongshu__public_content' const parts = fullFunctionName.split('__') if (parts.length !== 2) { console.error('工具名称格式错误') return } const [serverName, toolName] = parts // serverName = 'xiaohongshu' // toolName = 'public_content' ``` ### 步骤 7: 执行 MCP 工具 ```typescript // MCPClientService.ts - callTool() const result = await mcpClient.callTool( 'xiaohongshu', // serverId 'public_content', // toolName (不带前缀) { title: '🐟 超详细!家常酸菜鱼做法,10分钟学会!', content: '# 酸菜鱼制作教程\n\n## 所需食材...', tags: ['美食教程', '酸菜鱼', '家常菜', '川菜', '烹饪技巧'], category: '美食' } ) // MCP Server 响应: { "success": true, "article_id": "xhs_2024_001", "url": "https://www.xiaohongshu.com/discovery/item/xhs_2024_001", "views": 0, "likes": 0 } ``` ### 步骤 8: 工具结果返回 AI ```typescript // chatService.ts - 继续对话 const messages = [ { role: 'system', content: '...' // System Prompt }, { role: 'user', content: '帮我发布小红书文章,内容是:如何制作一道酸菜鱼' }, { role: 'assistant', tool_calls: [{ id: 'call_abc123', type: 'function', function: { name: 'xiaohongshu__public_content', arguments: '{"title":"🐟 超详细!家常酸菜鱼做法,10分钟学会!",...}' } }] }, { role: 'tool', tool_call_id: 'call_abc123', name: 'xiaohongshu__public_content', // 保持原名称(带前缀) content: JSON.stringify({ success: true, article_id: 'xhs_2024_001', url: 'https://www.xiaohongshu.com/discovery/item/xhs_2024_001' }) } ] // 再次调用 LLM ``` ### 步骤 9: AI 生成友好回复 ```json { "choices": [{ "delta": { "content": "✅ 文章已成功发布到小红书!\n\n📝 标题:🐟 超详细!家常酸菜鱼做法,10分钟学会!\n🔗 链接:https://www.xiaohongshu.com/discovery/item/xhs_2024_001\n\n你的酸菜鱼教程已经上线啦!记得定期查看浏览和点赞数据哦~ 🎉" }, "finish_reason": "stop" }] } ``` ## 关键代码实现 ### 1. System Prompt 生成 (chatService.ts) ```typescript private createSystemPromptWithTools(tools: any[], serverName: string): string { const toolDescriptions = tools.map(tool => { const func = tool.function const params = func.parameters?.properties || {} const required = func.parameters?.required || [] const paramDesc = Object.entries(params).map(([name, schema]: [string, any]) => { const isRequired = required.includes(name) const requiredMark = isRequired ? '[必填]' : '[可选]' return ` - ${name} ${requiredMark}: ${schema.description || schema.type}` }).join('\n') return `• ${func.name}\n 描述: ${func.description}\n 参数:\n${paramDesc || ' 无参数'}` }).join('\n\n') return `你是一个智能助手,可以使用以下工具完成任务: ${toolDescriptions} 使用指南: 1. 当用户需要完成某个任务时,请分析哪个工具最合适 2. 如果需要发布内容(如文章、笔记等),请根据用户意图创作完整的内容 3. 为内容生成合适的标题、正文、标签等所有必需参数 4. 自动调用相应工具,将生成的内容作为参数传递 5. 根据工具执行结果,给用户友好的反馈 注意事项: - 保持内容质量和平台特色 - 标签要相关且有吸引力 - 分类要准确 - 如果工具执行失败,给出明确的错误说明和建议 当前连接的 MCP 服务器: ${serverName}` } ``` ### 2. 工具名称转换 (chatService.ts) ```typescript private convertToolsToOpenAIFormat(mcpTools: any[], serverName: string): any[] { return mcpTools.map(tool => ({ type: 'function', function: { name: `${serverName}__${tool.name}`, // 添加服务器前缀 description: tool.description || '', parameters: tool.inputSchema || { type: 'object', properties: {}, required: [] } } })) } ``` ### 3. 工具名称解析 (chatService.ts) ```typescript private async executeToolCalls( conversation: Conversation, toolCalls: any[], model: string | undefined, onChunk: (chunk: string) => void, mcpServerId: string ): Promise { for (const toolCall of toolCalls) { const fullFunctionName = toolCall.function.name const args = JSON.parse(toolCall.function.arguments) console.log('🔧 执行工具调用:', { fullName: fullFunctionName, id: toolCall.id, arguments: args }) // 解析 serverName__toolName 格式 const parts = fullFunctionName.split('__') if (parts.length !== 2) { console.error('❌ 工具名称格式错误,应为 serverName__toolName:', fullFunctionName) continue } const toolName = parts[1] console.log('🎯 提取工具名称:', toolName) try { // 调用 MCP 工具(使用不带前缀的工具名) const result = await this.mcpClient.callTool( mcpServerId, toolName, // 使用原始工具名 args ) // 添加工具结果到消息历史(使用完整名称) const toolResultMessage: Message = { id: Date.now().toString(), role: 'tool', content: JSON.stringify(result), timestamp: new Date(), status: 'success', toolCallId: toolCall.id, toolName: fullFunctionName // 保持完整名称 } conversation.messages.push(toolResultMessage) this.saveConversations() // 继续对话 await this.callModelStream(conversation, model, onChunk, mcpServerId) } catch (error) { console.error('❌ 工具执行失败:', error) // 错误处理... } } } ``` ## 测试场景 ### 场景 1: 发布文章 ``` 用户: 帮我发布一篇关于"春季穿搭指南"的小红书笔记 AI 处理: 1. 识别需要使用 xiaohongshu__public_content 工具 2. 创作完整文章(标题、正文、标签、分类) 3. 调用工具发布 4. 返回发布结果和链接 ``` ### 场景 2: 多工具选择 假设有多个 MCP 服务器: ``` - xiaohongshu__public_content (发布小红书) - weibo__post_status (发布微博) - notion__create_page (创建 Notion 页面) ``` ``` 用户: 帮我把这篇文章同时发到小红书和微博 AI 处理: 1. 理解需要两个工具 2. 为小红书创作合适格式的内容 3. 为微博创作合适格式的内容(字数限制) 4. 依次调用两个工具 5. 返回两个平台的发布结果 ``` ### 场景 3: 错误处理 ``` 用户: 发布文章到小红书,标题是"测试" AI 处理: 1. 识别内容不完整 2. 提示用户补充正文内容 3. 等待用户补充后再调用工具 ``` ## 优势总结 ### 1. **智能参数生成** - AI 自动创作内容,无需用户逐一填写参数 - 符合平台特色(小红书风格 vs 微博风格) ### 2. **工具名称隔离** - `serverName__toolName` 避免多服务器冲突 - 清晰的工具来源 ### 3. **友好的用户体验** - 自然语言输入:"帮我发布..." - 自动处理所有技术细节 - 结果友好呈现 ### 4. **可扩展性** - 轻松添加新 MCP 服务器 - 支持任意数量和类型的工具 - System Prompt 自动生成 ### 5. **多轮对话支持** - 工具结果自动传回 AI - 可以追问、修改、重试 ## 对比 Cherry Studio | 特性 | mcp-client-vue | Cherry Studio | |------|---------------|---------------| | 工具名称格式 | ✅ `serverName__toolName` | ✅ `serverName__toolName` | | System Prompt | ✅ 自动生成 | ✅ 自动生成 | | 参数自动注入 | ✅ AI 生成 | ✅ AI 生成 | | 多轮对话 | ✅ 完整支持 | ✅ 完整支持 | | 流式响应 | ✅ SSE 真流式 | ✅ 真流式 | | 错误处理 | ✅ 完善 | ✅ 完善 | | UI 界面 | Vue 3 + Naive UI | Electron + React | ## 下一步优化 1. **批量工具调用**: 同时调用多个工具 2. **工具调用历史**: 记录和展示工具调用日志 3. **工具执行超时**: 防止长时间阻塞 4. **工具权限控制**: 敏感操作需要用户确认 5. **工具调用缓存**: 避免重复调用 ## 相关文件 - `/web/src/services/chatService.ts` - 核心服务 - `/web/src/services/modelServiceManager.ts` - 模型管理 - `/web/src/services/MCPClientService.ts` - MCP 客户端 - `/web/src/components/Chat/ChatLayout.vue` - UI 组件 --- **版本**: v1.0.2+ **更新时间**: 2024-01 **作者**: MCP Client Vue Team