Skip to main content
Glama
cbunting99

MCP Code Analysis & Quality Server

by cbunting99
index.ts10.8 kB
// Copyright 2025 Chris Bunting // Brief: Main entry point for Static Analysis MCP Server // Scope: Multi-language static code analysis with ESLint, Pylint, SpotBugs, and more 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 { StaticAnalysisService } from './services/StaticAnalysisService.js'; import { LanguageDetector } from './services/LanguageDetector.js'; import { ConfigParser } from './services/ConfigParser.js'; import { Logger } from './utils/Logger.js'; import { AnalysisResult, } from '@mcp-code-analysis/shared-types'; class StaticAnalysisServer { private server: Server; private analysisService: StaticAnalysisService; private languageDetector: LanguageDetector; private configParser: ConfigParser; private logger: Logger; constructor() { this.server = new Server( { name: 'static-analysis-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); this.logger = new Logger(); this.languageDetector = new LanguageDetector(); this.configParser = new ConfigParser(); this.analysisService = new StaticAnalysisService( this.languageDetector, this.configParser, this.logger ); this.setupHandlers(); } private setupHandlers(): void { this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'analyze_file', description: 'Analyze a single file for static analysis issues', inputSchema: { type: 'object', properties: { filePath: { type: 'string', description: 'Path to the file to analyze', }, language: { type: 'string', description: 'Programming language (optional, auto-detected if not provided)', enum: ['javascript', 'typescript', 'python', 'java', 'c', 'cpp', 'go', 'rust'], }, options: { type: 'object', description: 'Analysis options', properties: { rules: { type: 'array', items: { type: 'string' }, description: 'Specific rules to enable', }, exclude: { type: 'array', items: { type: 'string' }, description: 'Rules to exclude', }, fixable: { type: 'boolean', description: 'Only show fixable issues', }, configFile: { type: 'string', description: 'Path to custom configuration file', }, }, }, }, required: ['filePath'], }, }, { name: 'analyze_project', description: 'Analyze an entire project for static analysis issues', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Path to the project root directory', }, filePatterns: { type: 'array', items: { type: 'string' }, description: 'File patterns to include (glob patterns)', }, excludePatterns: { type: 'array', items: { type: 'string' }, description: 'File patterns to exclude', }, options: { type: 'object', description: 'Analysis options', properties: { rules: { type: 'array', items: { type: 'string' }, description: 'Specific rules to enable', }, exclude: { type: 'array', items: { type: 'string' }, description: 'Rules to exclude', }, maxWarnings: { type: 'number', description: 'Maximum number of warnings to report', }, configFile: { type: 'string', description: 'Path to custom configuration file', }, }, }, }, required: ['projectPath'], }, }, { name: 'get_rules', description: 'Get available rules for a specific language', inputSchema: { type: 'object', properties: { language: { type: 'string', description: 'Programming language', enum: ['javascript', 'typescript', 'python', 'java', 'c', 'cpp', 'go', 'rust'], }, configFile: { type: 'string', description: 'Path to configuration file (optional)', }, }, required: ['language'], }, }, { name: 'configure_analyzer', description: 'Configure the analyzer with custom settings', inputSchema: { type: 'object', properties: { language: { type: 'string', description: 'Programming language', enum: ['javascript', 'typescript', 'python', 'java', 'c', 'cpp', 'go', 'rust'], }, config: { type: 'object', description: 'Configuration object', }, }, required: ['language', 'config'], }, }, { name: 'batch_analyze', description: 'Analyze multiple files in batch', inputSchema: { type: 'object', properties: { filePaths: { type: 'array', items: { type: 'string' }, description: 'List of file paths to analyze', }, options: { type: 'object', description: 'Analysis options', properties: { rules: { type: 'array', items: { type: 'string' }, description: 'Specific rules to enable', }, exclude: { type: 'array', items: { type: 'string' }, description: 'Rules to exclude', }, maxWarnings: { type: 'number', description: 'Maximum number of warnings to report', }, }, }, }, required: ['filePaths'], }, }, ], }; }); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { let result: any; switch (name) { case 'analyze_file': result = await this.analyzeFile(args); break; case 'analyze_project': result = await this.analyzeProject(args); break; case 'get_rules': result = await this.getRules(args); break; case 'configure_analyzer': result = await this.configureAnalyzer(args); break; case 'batch_analyze': result = await this.batchAnalyze(args); break; default: throw new Error(`Unknown tool: ${name}`); } return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { this.logger.error(`Error executing tool ${name}:`, error); return { content: [ { type: 'text', text: JSON.stringify({ error: error instanceof Error ? error.message : 'Unknown error', }), }, ], isError: true, }; } }); } private async analyzeFile(args: any): Promise<AnalysisResult> { const { filePath, language, options = {} } = args; this.logger.info(`Analyzing file: ${filePath}`); return await this.analysisService.analyzeFile(filePath, language, options); } private async analyzeProject(args: any): Promise<AnalysisResult[]> { const { projectPath, filePatterns, excludePatterns, options = {} } = args; this.logger.info(`Analyzing project: ${projectPath}`); return await this.analysisService.analyzeProject( projectPath, filePatterns, excludePatterns, options ); } private async getRules(args: any): Promise<any> { const { language, configFile } = args; this.logger.info(`Getting rules for language: ${language}`); return await this.analysisService.getRules(language, configFile); } private async configureAnalyzer(args: any): Promise<any> { const { language, config } = args; this.logger.info(`Configuring analyzer for language: ${language}`); return await this.analysisService.configureAnalyzer(language, config); } private async batchAnalyze(args: any): Promise<AnalysisResult[]> { const { filePaths, options = {} } = args; this.logger.info(`Batch analyzing ${filePaths.length} files`); return await this.analysisService.batchAnalyze(filePaths, options); } async run(): Promise<void> { const transport = new StdioServerTransport(); await this.server.connect(transport); this.logger.info('Static Analysis MCP Server started'); } } async function main(): Promise<void> { const server = new StaticAnalysisServer(); await server.run(); } main().catch((error) => { console.error('Failed to start Static Analysis MCP Server:', error); process.exit(1); });

Latest Blog Posts

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/cbunting99/mcp-code-analysis-server'

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