giisp-arxiv-search-mcp
Version:
MCP服务器用于通过标题搜索arXiv论文
163 lines (142 loc) • 4.16 kB
JavaScript
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);
});