UNPKG

giisp-deepresearch-mcp

Version:

MCP server for searching 160 million academic papers from Giiisp database

167 lines (149 loc) 4.9 kB
#!/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 axios from "axios"; // 配置axios默认设置 const apiClient = axios.create({ timeout: 30000, // 30秒超时 headers: { 'Content-Type': 'application/json', 'User-Agent': 'MCP-DeepResearch/1.0.0' } }); // 创建MCP服务器实例 const server = new Server( { name: "giispDeepResearch-mcp-server", version: "1.0.0", }, { capabilities: { tools: {}, }, } ); // 定义工具列表 const tools = [ { name: "DeepResearch", description: "搜索集思谱1.6亿数据库内的论文数据", inputSchema: { type: "object", properties: { titleAndAbs: { type: "string", description: "标题或摘要用英文搜返回的就是英文的结果", }, startDate: { type: "string", description: "开始时间(格式:yyyy-MM-dd)", }, endDate: { type: "string", description: "结束时间(格式:yyyy-MM-dd)", } }, required: ["titleAndAbs"], }, } ]; // 处理工具列表请求 server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools, }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; // 注意:MCP服务器不能使用console.log或console.error,会干扰stdio通信 // 所有日志都应该写入到stderr或文件中 process.stderr.write(`[MCP] 收到工具调用请求: ${name}\n`); try { switch (name) { case "DeepResearch": const titleAndAbs = args.titleAndAbs; const startDate = args.startDate; const endDate = args.endDate; if (!titleAndAbs || typeof titleAndAbs !== "string") { throw new Error("titleAndAbs参数是必需的且必须是字符串"); } // 验证可选参数 if (startDate && typeof startDate !== "string") { throw new Error("startDate参数必须是字符串"); } if (endDate && typeof endDate !== "string") { throw new Error("endDate参数必须是字符串"); } const timeRange = startDate && endDate ? `, 时间范围: ${startDate} - ${endDate}` : ""; process.stderr.write(`开始搜索论文: ${titleAndAbs}${timeRange}\n`); // 构建请求参数 const requestParams = { titleAndAbs: titleAndAbs }; if (startDate) requestParams.startDate = startDate; if (endDate) requestParams.endDate = endDate; const response = await apiClient.post( "https://giiisp.com/first/oaPaper/searchArticlesByQuery1", requestParams ); process.stderr.write(`API响应状态: ${response.status}\n`); // 返回正确的MCP响应格式 return { content: [ { type: "text", text: JSON.stringify({ success: true, status: response.status, data: response.data, message: "论文搜索完成" }, null, 2) } ] }; default: throw new Error(`未知的工具: ${name}`); } } catch (error) { process.stderr.write(`[MCP] 工具调用错误: ${error.message}\n`); let errorMessage = "未知错误"; if (error.code === "ECONNABORTED") { errorMessage = "请求超时,请稍后重试"; } else if (error.response) { errorMessage = `API错误: ${error.response.status} - ${error.response.statusText}`; } else if (error.request) { errorMessage = "网络错误: 无法连接到服务器"; } else { errorMessage = error.message || "未知错误"; } return { content: [ { type: "text", text: JSON.stringify( { success: false, error: errorMessage, details: error.message }, null, 2 ) } ], isError: true }; } }); // 启动服务器 async function main() { const transport = new StdioServerTransport(); await server.connect(transport); process.stderr.write("已启动\n"); } main().catch((error) => { process.stderr.write(`失败: ${error.message}\n`); process.exit(1); });