UNPKG

skilled-feishu-mcp

Version:

A Model Context Protocol (MCP) server that integrates with Feishu's Open Platform APIs

179 lines (149 loc) 4.73 kB
#!/usr/bin/env node /** * 简化的MCP客户端测试 * 专注于验证连接和基本通信 */ import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; import fs from 'fs'; // 配置 const IS_DEV_MODE = process.env.NODE_ENV === 'development'; const TIMEOUT_MS = 10000; const SERVER_PATH = '/opt/homebrew/bin/skilled-feishu-mcp'; const APP_ID = process.env.FEISHU_APP_ID || 'cli_test_9e11c52b0e1c500e'; const APP_SECRET = process.env.FEISHU_APP_SECRET || 'test_app_secret_for_development'; // 日志文件 const logFile = fs.createWriteStream('mcp_simple_test.log'); /** * 记录日志 */ function log(message, isError = false) { const timestamp = new Date().toISOString(); const logMessage = `[${timestamp}] ${message}`; // 控制台输出 console[isError ? 'error' : 'log'](message); // 写入日志文件 logFile.write(logMessage + '\n'); } /** * 主函数 */ async function main() { log('======================================'); log('简化版MCP客户端连接测试'); log('======================================'); log(`时间: ${new Date().toLocaleString()}`); log(`开发模式: ${IS_DEV_MODE ? '是' : '否'}`); log(`服务器路径: ${SERVER_PATH}`); log(`应用ID: ${APP_ID.substring(0, 4)}****${APP_ID.substring(APP_ID.length - 4)}`); log('\n1. 创建MCP客户端...'); const client = new Client({ name: "MCP Simple Test", version: "1.0.0" }, { capabilities: { tools: true } }); log(' 客户端创建完成'); log('\n2. 准备服务器参数...'); const serverArgs = [ '--stdio', `--feishu-app-id=${APP_ID}`, `--feishu-app-secret=${APP_SECRET}`, '--verbose' ]; if (IS_DEV_MODE) { serverArgs.push('--development'); log(' 添加开发模式参数'); } const fullCommand = `${SERVER_PATH} ${serverArgs.join(' ')}`; log(` 完整命令: ${fullCommand}`); log('\n3. 创建传输层并连接...'); const transport = new StdioClientTransport({ command: SERVER_PATH, args: serverArgs, env: process.env, stdin: 'pipe', stdout: 'pipe', stderr: 'pipe' }); // 记录stderr输出 if (transport.stderr) { transport.stderr.on('data', (data) => { const text = data.toString().trim(); log(` [stderr] ${text}`); }); } // 记录stdout输出(用于调试) if (transport.stdout) { transport.stdout.on('data', (data) => { const text = data.toString().trim(); log(` [stdout raw] ${text}`); }); } // 处理进程退出 if (transport.process) { transport.process.on('exit', (code, signal) => { log(` 进程退出 - 代码: ${code}, 信号: ${signal}`); }); transport.process.on('error', (err) => { log(` 进程错误: ${err.message}`, true); }); } // 设置超时 const timeout = setTimeout(() => { log(' 连接超时', true); process.exit(1); }, TIMEOUT_MS); try { log(' 开始连接...'); await client.connect(transport); clearTimeout(timeout); log(' 连接成功!'); // 获取服务器信息 const version = client.getServerVersion(); log(` 服务器信息: ${version?.name || 'unknown'} v${version?.version || 'unknown'}`); const capabilities = client.getServerCapabilities(); log(` 服务器功能: ${JSON.stringify(capabilities)}`); log('\n4. 获取工具列表...'); const response = await client.listTools({}); log(` 获取了 ${response.tools.length} 个工具`); if (response.tools.length > 0) { log(' 工具列表:'); response.tools.slice(0, 5).forEach(tool => { log(` - ${tool.name}: ${tool.description?.substring(0, 50)}...`); }); if (response.tools.length > 5) { log(` - ... 另外 ${response.tools.length - 5} 个工具`); } } log('\n5. 关闭连接...'); await client.close(); await transport.close(); log(' 连接已关闭'); log('\n✅ 测试成功完成'); } catch (error) { clearTimeout(timeout); log(`\n❌ 测试失败: ${error.message}`, true); if (error.stack) { log(` 堆栈跟踪: ${error.stack}`, true); } try { log(' 正在清理连接...'); await client.close(); await transport.close(); } catch (cleanupError) { log(` 清理时出错: ${cleanupError.message}`, true); } process.exit(1); } } // 执行主函数 main().catch(err => { log(`未捕获错误: ${err.message}`, true); if (err.stack) { log(err.stack, true); } process.exit(1); });