UNPKG

giisp-arxiv-search-mcp

Version:

MCP服务器用于通过标题搜索arXiv论文

163 lines (142 loc) 4.16 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-ArxivSearch/1.0.0' } }); // 创建MCP服务器实例 const server = new Server( { name: "giispArxivSearch-mcp-server", version: "1.0.0", }, { capabilities: { tools: {}, }, } ); // 定义工具列表 const tools = [ { name: "searchArxivByTitle", description: "通过标题搜索arXiv论文", inputSchema: { type: "object", properties: { key: { type: "string", description: "搜索关键词(论文标题)", }, pageSize: { type: "number", description: "返回数据数量,默认为10", default: 10 } }, required: ["key"], }, } ]; // 处理工具列表请求 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 "searchArxivByTitle": const key = args.key; const pageSize = args.pageSize || 10; if (!key || typeof key !== "string") { throw new Error("key参数是必需的且必须是字符串"); } if (typeof pageSize !== "number" || pageSize <= 0) { throw new Error("pageSize参数必须是大于0的数字"); } process.stderr.write(`开始搜索arXiv论文: ${key}, 返回数量: ${pageSize}\n`); // 构建请求参数 const requestParams = { key: key, pageSize: pageSize }; const response = await apiClient.post( "https://giiisp.com/first/paper/searchArxivByTitle", 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: "arXiv论文搜索完成" }, 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("arXiv搜索MCP服务器已启动\n"); } main().catch((error) => { process.stderr.write(`服务器启动失败: ${error.message}\n`); process.exit(1); });