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
JavaScript
/**
* 简化的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);
});