Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/allen781105_mcp-test.json
T

1 line
8.3 KiB
JSON

{"repo": "allen781105/mcp-test", "files": {"app/api/chat/route.js": {"d0e7b18d14743a0f42ea29c83fe042e474df6213": {"t": 1785746669.9306607, "n": 6730, "h": "70eef58612c22c45", "c": "import { NextResponse } from 'next/server';\nimport { ChildProcess } from 'child_process';\nimport { spawn } from 'child_process';\nimport axios from 'axios';\nimport path from 'path';\n\n// MCP服务器进程\nlet mcpProcess = null;\nlet mcpClient = null;\n\n// 启动MCP服务器\nasync function startMCPServer() {\n // 如果已经有进程运行,直接返回\n if (mcpProcess && mcpClient) return mcpClient;\n \n console.log('启动MCP服务器...');\n const serverPath = path.join(process.cwd(), 'mcp-server.js');\n mcpProcess = spawn('node', [serverPath], {\n stdio: ['pipe', 'pipe', process.stderr],\n detached: false\n });\n \n // 等待服务器启动\n return new Promise((resolve, reject) => {\n // 设置超时\n const timeout = setTimeout(() => {\n reject(new Error('启动MCP服务器超时'));\n }, 10000);\n \n // 监听输出\n let buffer = '';\n mcpProcess.stdout.on('data', (data) => {\n buffer += data.toString();\n // 检查是否有服务就绪的消息\n if (buffer.includes('MCP服务器已启动,等待连接')) {\n clearTimeout(timeout);\n console.log('MCP服务器已就绪');\n resolve(true);\n }\n });\n \n // 处理错误\n mcpProcess.on('error', (err) => {\n clearTimeout(timeout);\n console.error('启动MCP服务器失败:', err);\n reject(err);\n });\n \n // 处理退出\n mcpProcess.on('exit', (code) => {\n console.log(`MCP服务器已退出,退出码: ${code}`);\n mcpProcess = null;\n mcpClient = null;\n if (code !== 0) {\n clearTimeout(timeout);\n reject(new Error(`MCP服务器异常退出,退出码: ${code}`));\n }\n });\n });\n}\n\n// 获取MCP工具描述(无需启动服务器)\nfunction getMCPToolsDescription() {\n return [\n {\n type: \"function\",\n function: {\n name: \"query_database\",\n description: \"执行MySQL数据库查询,返回查询结果\",\n parameters: {\n type: \"object\",\n properties: {\n sql: {\n type: \"string\",\n description: \"要执行的SQL查询语句\"\n }\n },\n required: [\"sql\"]\n }\n }\n },\n {\n type: \"function\",\n function: {\n name: \"get_tables\",\n description: \"获取数据库中所有表的列表\",\n parameters: {\n type: \"object\",\n properties: {}\n }\n }\n },\n {\n type: \"function\",\n function: {\n name: \"describe_table\",\n description: \"获取指定表的结构信息\",\n parameters: {\n type: \"object\",\n properties: {\n table_name: {\n type: \"string\",\n description: \"要描述的表名\"\n }\n },\n required: [\"table_name\"]\n }\n }\n }\n ];\n}\n\n// 模拟Deepseek响应\nfunction simulateDeepseekResponse(messages) {\n const lastMessage = messages[messages.length - 1];\n let responseText = \"\";\n \n // 简单的响应逻辑\n if (lastMessage.content.toLowerCase().includes(\"你好\") || lastMessage.content.toLowerCase().includes(\"hello\")) {\n responseText = \"你好!我是Deepseek助手。我可以帮你进行MySQL数据库查询。请问有什么可以帮助你的?\";\n } else if (lastMessage.content.toLowerCase().includes(\"查询\") && lastMessage.content.toLowerCase().includes(\"表\")) {\n responseText = \"我可以帮你查询数据库表。你可以使用以下命令:\\n1. 获取所有表:get_tables\\n2. 查看表结构:describe_table\\n3. 执行SQL查询:query_database\";\n } else if (lastMessage.content.toLowerCase().includes(\"mysql\") || lastMessage.content.toLowerCase().includes(\"数据库\")) {\n responseText = \"我已连接到MySQL数据库。你可以请我执行SQL查询,比如'查询用户表中的所有记录'。\";\n } else {\n responseText = \"我理解了您的问题。是否需要我帮您查询数据库相关信息?您可以具体告诉我您需要查询的内容。\";\n }\n \n return {\n role: \"assistant\",\n content: responseText\n };\n}\n\n// 处理deepseek请求\nasync function handleDeepseekRequest(messages) {\n // 检查API密钥是否存在\n const apiKey = process.env.DEEPSEEK_API_KEY;\n \n try {\n // 获取工具描述\n const tools = getMCPToolsDescription();\n \n // 尝试调用Deepseek API\n const apiBaseUrl = process.env.DEEPSEEK_API_BASE_URL || 'https://api.deepseek.com';\n console.log(`尝试调用Deepseek API: ${apiBaseUrl}`);\n \n // 发送请求到deepseek模型,包含工具信息\n const modelResponse = await axios.post(`${apiBaseUrl}/v1/chat/completions`, {\n model: \"deepseek-chat\",\n messages,\n tools,\n tool_choice: \"auto\"\n }, {\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`\n }\n });\n \n // 获取初始响应\n let assistantResponse = modelResponse.data.choices[0].message;\n console.log(\"初始响应:\", assistantResponse);\n \n // 如果模型想要调用工具\n if (assistantResponse.tool_calls && assistantResponse.tool_calls.length > 0) {\n console.log('检测到工具调用,准备处理');\n \n // 启动MCP服务器(如果未启动)\n await startMCPServer();\n const toolResults = [];\n \n // 处理每个工具调用\n for (const toolCall of assistantResponse.tool_calls) {\n const { function: func } = toolCall;\n console.log(`调用工具: ${func.name},参数:`, func.arguments);\n \n try {\n // 直接通过HTTP请求调用MCP服务器\n const mcpResponse = await axios.post('http://localhost:3001/tools/' + func.name, \n JSON.parse(func.arguments)\n );\n const result = mcpResponse.data;\n console.log(`工具调用结果:`, result);\n \n // 添加工具调用结果\n toolResults.push({\n tool_call_id: toolCall.id,\n role: \"tool\",\n name: func.name,\n content: JSON.stringify(result)\n });\n } catch (error) {\n console.error(`工具调用失败:`, error);\n toolResults.push({\n tool_call_id: toolCall.id,\n role: \"tool\",\n name: func.name,\n content: JSON.stringify({ error: error.message || \"工具调用失败\" })\n });\n }\n }\n \n // 添加工具响应到消息历史\n const finalMessages = [\n ...messages,\n assistantResponse,\n ...toolResults\n ];\n \n // 发送最终请求以获取助手响应\n console.log('发送最终请求到Deepseek...');\n const finalResponse = await axios.post(`${apiBaseUrl}/v1/chat/completions`, {\n model: \"deepseek-chat\",\n messages: finalMessages\n }, {\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`\n }\n });\n \n return finalResponse.data.choices[0].message;\n }\n \n // 如果没有工具调用,直接返回模型回复\n return assistantResponse;\n } catch (error) {\n console.error('调用Deepseek API失败,使用模拟响应:', error);\n \n // 如果API调用失败,返回模拟响应\n return simulateDeepseekResponse(messages);\n }\n}\n\nexport async function POST(request) {\n try {\n const { messages } = await request.json();\n \n // 处理deepseek请求\n const response = await handleDeepseekRequest(messages);\n \n return NextResponse.json({ message: response });\n } catch (error) {\n console.error('处理聊天请求时出错:', error);\n return NextResponse.json(\n { message: { \n role: \"assistant\", \n content: `很抱歉,处理请求时发生错误: ${error.message || '未知错误'}` \n } },\n { status: 200 } // 即使出错也返回200状态码,确保前端能正常显示\n );\n }\n} "}}}}