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'}`
          }]
        };
      }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide only a title ('Analyze Complexity'), which does not cover behavioral traits like read-only status or side effects. The description adds minimal context by implying analysis (likely read-only) but does not disclose details such as computational cost, rate limits, or output format. With annotations offering little, the description carries more burden but remains insufficient for full transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is poorly structured and repetitive ('complexity|how complex|complexity|how complex|difficulty'), wasting space without adding value. It is not front-loaded with essential information, and the formatting with pipes and dashes reduces readability. While brief, it fails to be concise in a meaningful way due to redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (analyzing code with metrics), lack of output schema, and minimal annotations, the description is incomplete. It does not explain what the analysis returns, how results are interpreted, or any limitations. For a tool with two parameters and no output schema, more context is needed to guide effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage, with clear documentation for 'code' and 'metrics' (including an enum). The description does not add meaning beyond the schema, as it lacks parameter-specific details. According to the rules, with high schema coverage (>80%), the baseline score is 3, reflecting adequate but not enhanced parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose2/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'complexity|how complex|complexity|how complex|difficulty - Analyze code complexity' is tautological, restating the tool name 'analyze_complexity' with redundant phrases. It does not specify what 'analyze' entails or distinguish this tool from sibling tools like 'validate_code_quality' or 'check_coupling_cohesion', which might also assess code aspects. The purpose is vague beyond the basic concept of analyzing complexity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines1/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It does not mention sibling tools like 'validate_code_quality' or 'check_coupling_cohesion', nor does it specify contexts or prerequisites for usage. Without any usage instructions, the agent lacks direction on appropriate application.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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