Skip to main content
Glama

Java Class Analyzer MCP Server

index.ts12 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 { JavaClassAnalyzer } from './analyzer/JavaClassAnalyzer.js'; import { DependencyScanner } from './scanner/DependencyScanner.js'; import { DecompilerService } from './decompiler/DecompilerService.js'; export class JavaClassAnalyzerMCPServer { private server: Server; private analyzer: JavaClassAnalyzer; private scanner: DependencyScanner; private decompiler: DecompilerService; constructor() { this.server = new Server( { name: 'java-class-analyzer', version: '1.0.0', capabilities: { tools: { scan_dependencies: { description: '扫描Maven项目的所有依赖,建立类名到JAR包的映射索引', }, decompile_class: { description: '反编译指定的Java类文件,返回Java源码', }, analyze_class: { description: '分析Java类的结构、方法、字段等信息', }, }, }, } ); this.analyzer = new JavaClassAnalyzer(); this.scanner = new DependencyScanner(); this.decompiler = new DecompilerService(); this.setupHandlers(); } private setupHandlers() { this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'scan_dependencies', description: '扫描Maven项目的所有依赖,建立类名到JAR包的映射索引', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Maven项目根目录路径', }, forceRefresh: { type: 'boolean', description: '是否强制刷新索引', default: false, }, }, required: ['projectPath'], }, }, { name: 'decompile_class', description: '反编译指定的Java类文件,返回Java源码', inputSchema: { type: 'object', properties: { className: { type: 'string', description: '要反编译的Java类全名,如:com.example.QueryBizOrderDO', }, projectPath: { type: 'string', description: 'Maven项目根目录路径', }, useCache: { type: 'boolean', description: '是否使用缓存,默认true', default: true, }, cfrPath: { type: 'string', description: 'CFR反编译工具的jar包路径,可选', }, }, required: ['className', 'projectPath'], }, }, { name: 'analyze_class', description: '分析Java类的结构、方法、字段等信息', inputSchema: { type: 'object', properties: { className: { type: 'string', description: '要分析的Java类全名', }, projectPath: { type: 'string', description: 'Maven项目根目录路径', }, }, required: ['className', 'projectPath'], }, }, ], }; }); this.server.setRequestHandler(CallToolRequestSchema, async (request: any) => { const { name, arguments: args } = request.params; try { switch (name) { case 'scan_dependencies': return await this.handleScanDependencies(args); case 'decompile_class': return await this.handleDecompileClass(args); case 'analyze_class': return await this.handleAnalyzeClass(args); default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { console.error(`工具调用异常 [${name}]:`, error); return { content: [ { type: 'text', text: `工具调用失败: ${error instanceof Error ? error.message : String(error)}\n\n建议:\n1. 检查输入参数是否正确\n2. 确保已运行必要的准备工作\n3. 查看服务器日志获取详细信息`, }, ], }; } }); } private async handleScanDependencies(args: any) { const { projectPath, forceRefresh = false } = args; const result = await this.scanner.scanProject(projectPath, forceRefresh); return { content: [ { type: 'text', text: `依赖扫描完成!\n\n` + `扫描的JAR包数量: ${result.jarCount}\n` + `索引的类数量: ${result.classCount}\n` + `索引文件路径: ${result.indexPath}\n\n` + `示例索引条目:\n${result.sampleEntries.slice(0, 5).join('\n')}`, }, ], }; } private async handleDecompileClass(args: any) { const { className, projectPath, useCache = true, cfrPath } = args; try { console.error(`开始反编译类: ${className}, 项目路径: ${projectPath}, 使用缓存: ${useCache}, CFR路径: ${cfrPath || '自动查找'}`); // 检查索引是否存在,如果不存在则先创建 await this.ensureIndexExists(projectPath); const sourceCode = await this.decompiler.decompileClass(className, projectPath, useCache, cfrPath); if (!sourceCode || sourceCode.trim() === '') { return { content: [ { type: 'text', text: `警告: 类 ${className} 的反编译结果为空,可能是CFR工具问题或类文件损坏`, }, ], }; } return { content: [ { type: 'text', text: `类 ${className} 的反编译源码:\n\n\`\`\`java\n${sourceCode}\n\`\`\``, }, ], }; } catch (error) { console.error(`反编译类 ${className} 失败:`, error); return { content: [ { type: 'text', text: `反编译失败: ${error instanceof Error ? error.message : String(error)}\n\n建议:\n1. 确保已运行 scan_dependencies 建立类索引\n2. 检查CFR工具是否正确安装\n3. 验证类名是否正确`, }, ], }; } } private async handleAnalyzeClass(args: any) { const { className, projectPath } = args; // 检查索引是否存在,如果不存在则先创建 await this.ensureIndexExists(projectPath); const analysis = await this.analyzer.analyzeClass(className, projectPath); let result = `类 ${className} 的分析结果:\n\n`; result += `包名: ${analysis.packageName}\n`; result += `类名: ${analysis.className}\n`; result += `修饰符: ${analysis.modifiers.join(' ')}\n`; result += `父类: ${analysis.superClass || '无'}\n`; result += `实现的接口: ${analysis.interfaces.join(', ') || '无'}\n\n`; if (analysis.fields.length > 0) { result += `字段 (${analysis.fields.length}个):\n`; analysis.fields.forEach(field => { result += ` - ${field.modifiers.join(' ')} ${field.type} ${field.name}\n`; }); result += '\n'; } if (analysis.methods.length > 0) { result += `方法 (${analysis.methods.length}个):\n`; analysis.methods.forEach(method => { result += ` - ${method.modifiers.join(' ')} ${method.returnType} ${method.name}(${method.parameters.join(', ')})\n`; }); result += '\n'; } return { content: [ { type: 'text', text: result, }, ], }; } /** * 确保索引文件存在,如果不存在则自动创建 */ private async ensureIndexExists(projectPath: string): Promise<void> { const fs = await import('fs-extra'); const path = await import('path'); const indexPath = path.join(projectPath, '.mcp-class-index.json'); if (!(await fs.pathExists(indexPath))) { console.error('索引文件不存在,正在自动创建...'); try { await this.scanner.scanProject(projectPath, false); console.error('索引文件创建完成'); } catch (error) { console.error('自动创建索引失败:', error); throw new Error(`无法创建类索引文件: ${error instanceof Error ? error.message : String(error)}`); } } } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); const env = process.env.NODE_ENV || 'development'; if (env === 'development') { console.error('Java Class Analyzer MCP Server running on stdio (DEBUG MODE)'); } else { console.error('Java Class Analyzer MCP Server running on stdio'); } } } const mcpServer = new JavaClassAnalyzerMCPServer(); // 添加全局异常处理,防止服务器崩溃 process.on('uncaughtException', (error) => { console.error('未捕获的异常:', error); // 不退出进程,继续运行 }); process.on('unhandledRejection', (reason, promise) => { console.error('未处理的Promise拒绝:', reason); // 不退出进程,继续运行 }); mcpServer.run().catch((error) => { console.error('服务器启动失败:', error); process.exit(1); });

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/handsomestWei/java-class-analyzer-mcp-server'

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