Skip to main content
Glama
cbunting99

MCP Code Analysis & Quality Server

by cbunting99
index.ts11.8 kB
// Copyright 2025 Chris Bunting // Brief: Main entry point for Code Complexity Analyzer MCP Server // Scope: Advanced code complexity analysis with cyclomatic, cognitive, and Halstead metrics 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 { ComplexityAnalysisService } from './services/ComplexityAnalysisService.js'; import { ASTProcessor } from './services/ASTProcessor.js'; import { MetricCalculator } from './services/MetricCalculator.js'; import { StructureAnalyzer } from './services/StructureAnalyzer.js'; import { MaintainabilityAssessor } from './services/MaintainabilityAssessor.js'; import { Logger } from './utils/Logger.js'; import { AnalysisResult, } from '@mcp-code-analysis/shared-types'; class ComplexityAnalyzerServer { private server: Server; private analysisService: ComplexityAnalysisService; private astProcessor: ASTProcessor; private metricCalculator: MetricCalculator; private structureAnalyzer: StructureAnalyzer; private maintainabilityAssessor: MaintainabilityAssessor; private logger: Logger; constructor() { this.server = new Server( { name: 'complexity-analyzer-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); this.logger = new Logger(); this.astProcessor = new ASTProcessor(); this.metricCalculator = new MetricCalculator(); this.structureAnalyzer = new StructureAnalyzer(); this.maintainabilityAssessor = new MaintainabilityAssessor(); this.analysisService = new ComplexityAnalysisService( this.astProcessor, this.metricCalculator, this.structureAnalyzer, this.maintainabilityAssessor, this.logger ); this.setupHandlers(); } private setupHandlers(): void { this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'analyze_complexity', description: 'Analyze code complexity with comprehensive metrics including cyclomatic, cognitive, and Halstead metrics', 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: 'Complexity analysis options', properties: { thresholds: { type: 'object', description: 'Custom thresholds for complexity metrics', properties: { cyclomatic: { type: 'number', description: 'Cyclomatic complexity threshold', }, cognitive: { type: 'number', description: 'Cognitive complexity threshold', }, maintainability: { type: 'number', description: 'Maintainability index threshold', }, }, }, includeMetrics: { type: 'array', items: { type: 'string' }, description: 'Specific metrics to include', }, excludeFiles: { type: 'array', items: { type: 'string' }, description: 'Files to exclude from analysis', }, }, }, }, required: ['filePath'], }, }, { name: 'suggest_refactorings', description: 'Suggest refactoring opportunities based on complexity analysis', inputSchema: { type: 'object', properties: { filePath: { type: 'string', description: 'Path to the file to analyze for refactoring opportunities', }, complexityThreshold: { type: 'number', description: 'Complexity threshold to trigger refactoring suggestions', default: 10, }, focusArea: { type: 'string', description: 'Area to focus refactoring suggestions on', enum: ['cyclomatic', 'cognitive', 'maintainability', 'all'], default: 'all', }, }, required: ['filePath'], }, }, { name: 'calculate_metrics', description: 'Calculate custom complexity metrics for specific code elements', inputSchema: { type: 'object', properties: { filePath: { type: 'string', description: 'Path to the file to analyze', }, targetElements: { type: 'array', items: { type: 'string' }, description: 'Specific code elements to analyze (function names, class names, etc.)', }, customMetrics: { type: 'array', items: { type: 'string' }, description: 'Custom metrics to calculate', }, }, required: ['filePath'], }, }, { name: 'identify_hotspots', description: 'Identify complexity hotspots in codebase that need immediate attention', 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)', }, hotspotThreshold: { type: 'number', description: 'Threshold for identifying hotspots', default: 15, }, maxResults: { type: 'number', description: 'Maximum number of hotspots to return', default: 20, }, }, required: ['projectPath'], }, }, { name: 'track_trends', description: 'Track complexity trends over time for historical analysis', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Path to the project root directory', }, timeRange: { type: 'string', description: 'Time range for trend analysis', enum: ['week', 'month', 'quarter', 'year'], default: 'month', }, metrics: { type: 'array', items: { type: 'string' }, description: 'Metrics to track trends for', default: ['cyclomaticComplexity', 'cognitiveComplexity', 'maintainabilityIndex'], }, includeFiles: { type: 'array', items: { type: 'string' }, description: 'Specific files to include in trend analysis', }, }, required: ['projectPath'], }, }, ], }; }); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { let result: any; switch (name) { case 'analyze_complexity': result = await this.analyzeComplexity(args); break; case 'suggest_refactorings': result = await this.suggestRefactorings(args); break; case 'calculate_metrics': result = await this.calculateMetrics(args); break; case 'identify_hotspots': result = await this.identifyHotspots(args); break; case 'track_trends': result = await this.trackTrends(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 analyzeComplexity(args: any): Promise<AnalysisResult> { const { filePath, language, options = {} } = args; this.logger.info(`Analyzing complexity for file: ${filePath}`); return await this.analysisService.analyzeComplexity(filePath, language, options); } private async suggestRefactorings(args: any): Promise<any> { const { filePath, complexityThreshold = 10, focusArea = 'all' } = args; this.logger.info(`Suggesting refactorings for file: ${filePath}`); return await this.analysisService.suggestRefactorings(filePath, complexityThreshold, focusArea); } private async calculateMetrics(args: any): Promise<any> { const { filePath, targetElements, customMetrics } = args; this.logger.info(`Calculating custom metrics for file: ${filePath}`); return await this.analysisService.calculateMetrics(filePath, targetElements, customMetrics); } private async identifyHotspots(args: any): Promise<any> { const { projectPath, filePatterns, hotspotThreshold = 15, maxResults = 20 } = args; this.logger.info(`Identifying hotspots in project: ${projectPath}`); return await this.analysisService.identifyHotspots(projectPath, filePatterns, hotspotThreshold, maxResults); } private async trackTrends(args: any): Promise<any> { const { projectPath, timeRange = 'month', metrics, includeFiles } = args; this.logger.info(`Tracking trends for project: ${projectPath}`); return await this.analysisService.trackTrends(projectPath, timeRange, metrics, includeFiles); } async run(): Promise<void> { const transport = new StdioServerTransport(); await this.server.connect(transport); this.logger.info('Code Complexity Analyzer MCP Server started'); } } async function main(): Promise<void> { const server = new ComplexityAnalyzerServer(); await server.run(); } main().catch((error) => { console.error('Failed to start Code Complexity Analyzer 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