Skip to main content
Glama

McpDocServer

by ruan11223344
mcp.test.js8.84 kB
// mcp-test.js - MCP测试脚本 import { spawn } from 'child_process'; import path from 'path'; import { fileURLToPath } from 'url'; import fs from 'fs'; // 获取当前文件的目录路径 const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // 检查服务器文件是否存在 const SERVER_PATH = path.join(__dirname, '../server.js'); if (!fs.existsSync(SERVER_PATH)) { throw new Error(`找不到服务器文件: ${SERVER_PATH}`); } // 生成请求ID function generateId() { return Math.random().toString(36).substring(2, 10); } // 发送请求并返回响应的Promise function sendRequest(server, request) { return new Promise((resolve, reject) => { let responseData = ''; const onData = (data) => { responseData += data; try { // 尝试解析JSON响应 const response = JSON.parse(responseData); removeListeners(); resolve(response); } catch (e) { // 不是完整的JSON,继续等待更多数据 } }; const onError = (err) => { // 这里不需要处理,因为服务器错误日志不影响测试 // 但为了调试可以开启 // console.log('服务器日志:', err.toString().slice(0, 50) + '...'); }; const removeListeners = () => { server.stdout.removeListener('data', onData); server.stderr.removeListener('data', onError); }; server.stdout.on('data', onData); server.stderr.on('data', onError); // 发送请求 server.stdin.write(JSON.stringify(request) + '\n'); // 设置超时,避免永久等待 setTimeout(() => { removeListeners(); reject(new Error('请求超时')); }, 5000); }); } // Jest测试用例 describe('MCP服务器测试', () => { let server; let docSource = 'taro'; // 根据docs目录内容设置默认源 let docId; // 存储搜索结果中的文档ID // 在所有测试前启动服务器 beforeAll(() => { console.log(`启动服务器: ${SERVER_PATH}`); server = spawn('node', [SERVER_PATH]); server.stdout.setEncoding('utf8'); server.stderr.setEncoding('utf8'); // 忽略服务器stdout和stderr输出 server.stderr.on('data', () => {}); server.stdout.on('data', () => {}); // 等待服务器启动 return new Promise(resolve => setTimeout(resolve, 3000)); }, 15000); // 测试初始化 test('初始化MCP服务器', async () => { // 创建初始化请求 const request = { jsonrpc: "2.0", id: generateId(), method: "initialize", params: { protocolVersion: "2024-11-05", capabilities: {}, clientInfo: { name: "doc-test-client", version: "1.0.0" } } }; const response = await sendRequest(server, request); expect(response).toBeDefined(); expect(response.jsonrpc).toBe('2.0'); expect(response.id).toBe(request.id); expect(response.error).toBeUndefined(); expect(response.result).toBeDefined(); expect(response.result.serverInfo.name).toBe("文档 MCP 服务器"); }, 10000); // 测试搜索功能 test('调用搜索工具', async () => { try { // 根据server.js创建正确的搜索请求,使用taro文档源 const request = { jsonrpc: "2.0", id: generateId(), method: "tools/call", params: { name: "search_docs", arguments: { query: "组件", source: docSource, limit: 5 } } }; const response = await sendRequest(server, request); expect(response).toBeDefined(); expect(response.jsonrpc).toBe('2.0'); expect(response.id).toBe(request.id); // 处理可能的错误 if (response.error) { console.log(`搜索功能返回错误: ${response.error.message}`); // 设置一个默认的文档ID,用于继续测试 docId = `https://taro-docs.jd.com/taro/docs/components/viewContainer/view`; return; } expect(response.result).toBeDefined(); // 解析结果中的文档ID const content = response.result?.content; expect(content).toBeDefined(); expect(Array.isArray(content)).toBe(true); // 从结果中提取第一个文档ID let searchResults; for (const item of content) { if (item.type === 'text' && item.text) { try { searchResults = JSON.parse(item.text); break; } catch (e) { // 不是JSON格式,继续下一项 } } } expect(searchResults).toBeDefined(); if (searchResults.error) { console.log(`搜索结果包含错误: ${searchResults.error}`); // 设置一个默认的文档ID,用于继续测试 docId = `https://taro-docs.jd.com/taro/docs/components/viewContainer/view`; return; } expect(searchResults.results).toBeDefined(); expect(Array.isArray(searchResults.results)).toBe(true); if (searchResults.results.length === 0) { console.log(`搜索结果为空`); // 设置一个默认的文档ID,用于继续测试 docId = `https://taro-docs.jd.com/taro/docs/components/viewContainer/view`; return; } // 保存第一个结果的ID,用于后续详情测试 docId = searchResults.results[0].id; console.log(`获取到文档ID: ${docId}`); } catch (error) { console.error(`搜索功能测试出错: ${error ? error.message : '未知错误'}`); // 设置一个默认的文档ID,用于继续测试 docId = `https://taro-docs.jd.com/taro/docs/components/viewContainer/view`; } }, 10000); // 测试详情功能 test('调用文档详情工具', async () => { // 确保docId有值 if (!docId) { docId = `https://taro-docs.jd.com/taro/docs/components/viewContainer/view`; console.log(`使用默认文档ID: ${docId}`); } expect(docId).toBeDefined(); try { // 根据server.js创建正确的文档详情请求 const request = { jsonrpc: "2.0", id: generateId(), method: "tools/call", params: { name: "get_doc_detail", arguments: { id: docId, source: docSource } } }; const response = await sendRequest(server, request); expect(response).toBeDefined(); expect(response.jsonrpc).toBe('2.0'); expect(response.id).toBe(request.id); // 处理可能的错误 if (response.error) { console.log(`详情功能返回错误: ${response.error.message}`); return; } expect(response.result).toBeDefined(); // 解析结果,确认成功获取文档详情 const content = response.result?.content; expect(content).toBeDefined(); expect(Array.isArray(content)).toBe(true); let docDetail; for (const item of content) { if (item.type === 'text' && item.text) { try { docDetail = JSON.parse(item.text); break; } catch (e) { // 不是JSON格式,继续下一项 } } } expect(docDetail).toBeDefined(); if (docDetail.error) { console.log(`文档详情包含错误: ${docDetail.error}`); return; } expect(docDetail.success).toBe(true); expect(docDetail.document).toBeDefined(); expect(docDetail.document.id).toBe(docId); console.log(`成功获取文档详情: ${docDetail.document.title}`); } catch (error) { console.error(`详情功能测试出错: ${error ? error.message : '未知错误'}`); } }, 10000); // 在所有测试后关闭服务器 afterAll(() => { if (server) { console.log('关闭服务器进程...'); // 直接发送SIGTERM信号强制终止进程 server.kill('SIGTERM'); // 添加确认关闭的日志 server.on('close', (code) => { console.log(`服务器进程退出,退出码 ${code}`); }); // 设置超时检查 return new Promise((resolve) => { // 如果5秒后进程仍未退出,强制退出 const timeout = setTimeout(() => { console.log('服务器进程超时未退出,强制终止'); server.kill('SIGKILL'); resolve(); }, 1000); // 进程退出后,清除超时并resolve server.on('close', () => { clearTimeout(timeout); resolve(); }); }); } }, 5000); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ruan11223344/McpDocServer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server