Skip to main content
Glama

analyze_complexity

Analyze code complexity by calculating cyclomatic, cognitive, or Halstead metrics to identify difficult sections and improve maintainability.

Instructions

complexity|how complex|complexity|how complex|difficulty - Analyze code complexity

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
codeYesCode to analyze
metricsNoMetrics to calculate

Implementation Reference

  • Main handler function that analyzes code complexity for JS/TS/Python, computes cyclomatic, cognitive, Halstead metrics, and provides overall score.
    export async function analyzeComplexity(args: { code: string; metrics?: string }): Promise<ToolResult> {
      const { code: complexityCode, metrics: complexityMetrics = 'all' } = args;
    
      // Check if this is Python code
      if (PythonParser.isPythonCode(complexityCode)) {
        return analyzePythonComplexity(complexityCode);
      }
    
      const complexityAnalysis = {
        action: 'analyze_complexity',
        metrics: complexityMetrics,
        results: {} as any,
        overallScore: 0,
        issues: [] as string[],
        recommendations: [] as string[],
        status: 'pending' as string
      };
    
      // AST 기반 cyclomatic complexity 분석
      complexityAnalysis.results.astCyclomaticComplexity = calculateAstComplexity(complexityCode);
      
      if (complexityMetrics === 'cyclomatic' || complexityMetrics === 'all') {
        const cyclomaticComplexityScore = (complexityCode.match(/\bif\b|\bfor\b|\bwhile\b|\bcase\b|\b&&\b|\b\|\|\b/g) || []).length + 1;
        complexityAnalysis.results.cyclomaticComplexity = {
          value: cyclomaticComplexityScore,
          threshold: CODE_QUALITY_METRICS.COMPLEXITY.maxCyclomaticComplexity,
          status: cyclomaticComplexityScore <= CODE_QUALITY_METRICS.COMPLEXITY.maxCyclomaticComplexity ? 'pass' : 'fail',
          description: 'Number of linearly independent paths through the code'
        };
      }
      
      if (complexityMetrics === 'cognitive' || complexityMetrics === 'all') {
        complexityAnalysis.results.cognitiveComplexity = calculateCognitiveComplexity(complexityCode);
      }
      
      if (complexityMetrics === 'halstead' || complexityMetrics === 'all') {
        // Halstead metrics calculation (simplified version)
        const operators = (complexityCode.match(/[+\-*/=<>!&|%^~?:]/g) || []).length;
        const operands = (complexityCode.match(/\b[a-zA-Z_]\w*\b/g) || []).length;
        const uniqueOperators = new Set(complexityCode.match(/[+\-*/=<>!&|%^~?:]/g) || []).size;
        const uniqueOperands = new Set(complexityCode.match(/\b[a-zA-Z_]\w*\b/g) || []).size;
        
        const vocabulary = uniqueOperators + uniqueOperands;
        const length = operators + operands;
        const calculatedLength = vocabulary > 0 ? uniqueOperators * Math.log2(uniqueOperators) + uniqueOperands * Math.log2(uniqueOperands) : 0;
        const volume = length * Math.log2(vocabulary);
        const difficulty = vocabulary > 0 ? (uniqueOperators / 2) * (operands / uniqueOperands) : 0;
        const effort = difficulty * volume;
        
        complexityAnalysis.results.halsteadMetrics = {
          vocabulary: vocabulary,
          length: length,
          calculatedLength: Math.round(calculatedLength),
          volume: Math.round(volume),
          difficulty: Math.round(difficulty * 100) / 100,
          effort: Math.round(effort),
          timeToProgram: Math.round(effort / 18), // Halstead's formula: effort / 18 seconds
          bugsDelivered: Math.round(volume / 3000 * 100) / 100, // Halstead's formula: volume / 3000
          description: 'Software science metrics measuring program complexity'
        };
      }
      
      // Additional complexity metrics
      if (complexityMetrics === 'all') {
        const lines = complexityCode.split('\n');
        const nonEmptyLines = lines.filter(line => line.trim().length > 0).length;
        const comments = (complexityCode.match(/\/\*[\s\S]*?\*\/|\/\/.*$/gm) || []).length;
        const functions = (complexityCode.match(/function\s+\w+|\w+\s*=\s*\(/g) || []).length;
        const classes = (complexityCode.match(/class\s+\w+/g) || []).length;
        
        complexityAnalysis.results.additionalMetrics = {
          linesOfCode: nonEmptyLines,
          comments: comments,
          commentRatio: nonEmptyLines > 0 ? Math.round((comments / nonEmptyLines) * 100) / 100 : 0,
          functions: functions,
          classes: classes,
          averageFunctionLength: functions > 0 ? Math.round(nonEmptyLines / functions) : 0
        };
      }
      
      // Overall assessment
      const issues = [];
      let overallScore = 100;
      
      if (complexityAnalysis.results.cyclomaticComplexity && complexityAnalysis.results.cyclomaticComplexity.status === 'fail') {
        issues.push('High cyclomatic complexity detected');
        overallScore -= 20;
      }
      
      if (complexityAnalysis.results.cognitiveComplexity && complexityAnalysis.results.cognitiveComplexity.status === 'fail') {
        issues.push('High cognitive complexity detected');
        overallScore -= 25;
      }
      
      if (complexityAnalysis.results.halsteadMetrics && complexityAnalysis.results.halsteadMetrics.difficulty > 10) {
        issues.push('High Halstead difficulty detected');
        overallScore -= 15;
      }
      
      complexityAnalysis.overallScore = Math.max(0, overallScore);
      complexityAnalysis.issues = issues;
    
      return {
        content: [{
          type: 'text',
          text: `Complexity: ${complexityAnalysis.results.astCyclomaticComplexity?.value ?? 'N/A'}\nScore: ${complexityAnalysis.overallScore}${issues.length ? '\nIssues: ' + issues.join(', ') : ''}`
        }]
      };
    }
  • Tool schema definition including input schema for code and optional metrics.
    export const analyzeComplexityDefinition: ToolDefinition = {
      name: 'analyze_complexity',
      description: 'complexity|how complex|complexity|how complex|difficulty - Analyze code complexity',
      inputSchema: {
        type: 'object',
        properties: {
          code: { type: 'string', description: 'Code to analyze' },
          metrics: { type: 'string', description: 'Metrics to calculate', enum: ['cyclomatic', 'cognitive', 'halstead', 'all'] }
        },
        required: ['code']
      },
      annotations: {
        title: 'Analyze Complexity',
        audience: ['user', 'assistant']
      }
    };
  • src/index.ts:664-665 (registration)
    Tool registration in the main switch dispatcher that calls the analyzeComplexity handler.
    case 'analyze_complexity':
      return await analyzeComplexity(args as any) as CallToolResult;
  • src/index.ts:140-140 (registration)
    Inclusion of tool definition in the tools array for listTools.
    analyzeComplexityDefinition,
  • Helper function for Python-specific complexity analysis using PythonParser.
    async function analyzePythonComplexity(code: string): Promise<ToolResult> {
      try {
        const pythonComplexity = await PythonParser.analyzeComplexity(code);
        const totalComplexity = pythonComplexity.cyclomaticComplexity;
        const issues: string[] = [];
    
        const MAX_COMPLEXITY = 10;
        if (totalComplexity > MAX_COMPLEXITY) {
          issues.push('High complexity');
        }
    
        pythonComplexity.functions.forEach(f => {
          if (f.complexity > MAX_COMPLEXITY) {
            issues.push(`Function ${f.name}: complexity ${f.complexity}`);
          }
        });
    
        const issuesText = issues.length ? `\nIssues: ${issues.join(', ')}` : '';
        return {
          content: [{
            type: 'text',
            text: `Python Complexity: ${totalComplexity}\nFunctions: ${pythonComplexity.functions.length}\nClasses: ${pythonComplexity.classes.length}${issuesText}`
          }]
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Python analysis error: ${error instanceof Error ? error.message : 'Unknown error'}`
          }]
        };
      }

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/ssdeanx/ssd-ai'

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