Skip to main content
Glama

analyze_complexity

Analyze code complexity by calculating cyclomatic, cognitive, and Halstead metrics to identify maintainability issues and optimization opportunities.

Instructions

복잡도|복잡한지|complexity|how complex|난이도 - Analyze code complexity

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
codeYesCode to analyze
metricsNoMetrics to calculate

Implementation Reference

  • Main handler function implementing the analyze_complexity tool. Handles JS/TS complexity analysis (cyclomatic, cognitive, Halstead) and delegates Python to PythonParser.
    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(', ') : ''}`
        }]
      };
    }
  • Input schema and ToolDefinition for the analyze_complexity tool.
    export const analyzeComplexityDefinition: ToolDefinition = {
      name: 'analyze_complexity',
      description: '복잡도|복잡한지|complexity|how complex|난이도 - 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'],
        readOnlyHint: true,
        destructiveHint: false,
        idempotentHint: true,
        openWorldHint: false
      }
    };
  • src/index.ts:183-188 (registration)
    Registration of the analyze_complexity handler in the toolHandlers dispatch map.
    'get_coding_guide': getCodingGuide,
    'apply_quality_rules': applyQualityRules,
    'validate_code_quality': validateCodeQuality,
    'analyze_complexity': analyzeComplexity,
    'check_coupling_cohesion': checkCouplingCohesion,
    'suggest_improvements': suggestImprovements,
  • src/index.ts:119-124 (registration)
    Registration of the analyzeComplexityDefinition in the tools list for MCP listTools endpoint.
    applyQualityRulesDefinition,
    validateCodeQualityDefinition,
    analyzeComplexityDefinition,
    checkCouplingCohesionDefinition,
    suggestImprovementsDefinition,
  • Helper method in PythonParser used for Python code complexity analysis, called from the main handler.
    public static async analyzeComplexity(code: string): Promise<PythonComplexity> {
      const result = await this.executePython(code, 'complexity');
      return {
        cyclomaticComplexity: result.cyclomaticComplexity || 1,
        functions: result.functions || [],
        classes: result.classes || []
      };
    }

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/su-record/hi-ai'

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