Skip to main content
Glama

suggest_improvements

Read-onlyIdempotent

Analyze code to suggest targeted improvements for performance, readability, maintainability, accessibility, or type-safety based on specified priority levels.

Instructions

개선|더 좋게|리팩토링|improve|make better|refactor|optimize|enhance code - Suggest improvements

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
codeYesCode to analyze
focusNoFocus area
priorityNoPriority level

Implementation Reference

  • The primary handler function implementing the tool logic: analyzes input code based on focus (performance, readability, etc.) and priority, generates suggestions with categories, issues, fixes, and returns a structured result with summary and top suggestions.
    export async function suggestImprovements(args: { code: string; focus?: string; priority?: string }): Promise<ToolResult> {
      const { code, focus = 'maintainability', priority = 'medium' } = args;
      
      const suggestions = [];
      const codeLines = code.split('\n');
      const codeLength = codeLines.length;
      
      // Performance improvements
      if (focus === 'performance' || focus === 'all') {
        // Check for inefficient loops
        if (code.includes('for') && code.includes('length')) {
          suggestions.push({
            category: 'performance',
            priority: 'high',
            issue: 'Potential inefficient loop accessing .length property',
            suggestion: 'Cache array length in a variable before the loop',
            example: 'const len = array.length; for (let i = 0; i < len; i++)'
          });
        }
        
        // Check for React performance issues
        if (code.includes('React') || code.includes('jsx') || code.includes('tsx')) {
          if (!code.includes('memo') && !code.includes('useMemo') && !code.includes('useCallback')) {
            suggestions.push({
              category: 'performance',
              priority: 'medium',
              issue: 'Missing React performance optimizations',
              suggestion: 'Consider using React.memo, useMemo, or useCallback',
              example: 'const Component = React.memo(() => { ... })'
            });
          }
          
          if (code.includes('map') && code.includes('return')) {
            suggestions.push({
              category: 'performance',
              priority: 'medium',
              issue: 'Ensure unique keys in map functions',
              suggestion: 'Use unique and stable keys for list items',
              example: 'items.map(item => <div key={item.id}>{item.name}</div>)'
            });
          }
        }
        
        // Check for expensive operations
        if (code.includes('JSON.parse') || code.includes('JSON.stringify')) {
          suggestions.push({
            category: 'performance',
            priority: 'medium',
            issue: 'JSON operations can be expensive',
            suggestion: 'Consider memoizing JSON operations or using alternatives',
            example: 'const memoizedParse = useMemo(() => JSON.parse(data), [data])'
          });
        }
      }
      
      // Readability improvements
      if (focus === 'readability' || focus === 'all') {
        // Check for long functions
        if (codeLength > 20) {
          suggestions.push({
            category: 'readability',
            priority: 'high',
            issue: `Function is too long (${codeLength} lines)`,
            suggestion: 'Break down into smaller, focused functions',
            example: 'Extract logical groups into separate functions'
          });
        }
        
        // Check for deep nesting
        let maxNesting = 0;
        let currentNesting = 0;
        for (const line of codeLines) {
          const braceCount = (line.match(/\{/g) || []).length - (line.match(/\}/g) || []).length;
          currentNesting += braceCount;
          maxNesting = Math.max(maxNesting, currentNesting);
        }
        
        if (maxNesting > 3) {
          suggestions.push({
            category: 'readability',
            priority: 'high',
            issue: `Deep nesting detected (${maxNesting} levels)`,
            suggestion: 'Use early returns or guard clauses to reduce nesting',
            example: 'if (!condition) return; // instead of wrapping in else'
          });
        }
        
        // Check for magic numbers
        const magicNumbers = code.match(/\b\d{2,}\b/g) || [];
        if (magicNumbers.length > 0) {
          suggestions.push({
            category: 'readability',
            priority: 'medium',
            issue: 'Magic numbers found in code',
            suggestion: 'Extract numbers into named constants',
            example: 'const MAX_RETRY_COUNT = 3; // instead of using 3 directly'
          });
        }
        
        // Check for unclear variable names
        const shortVars = code.match(/\b[a-z]\b/g) || [];
        if (shortVars.length > 2) {
          suggestions.push({
            category: 'readability',
            priority: 'medium',
            issue: 'Single letter variable names detected',
            suggestion: 'Use descriptive variable names',
            example: 'const userIndex = 0; // instead of i = 0'
          });
        }
      }
      
      // Maintainability improvements
      if (focus === 'maintainability' || focus === 'all') {
        // Check for error handling
        const hasAsyncCode = code.includes('async') || code.includes('await') || code.includes('Promise');
        const hasErrorHandling = code.includes('try') || code.includes('catch') || code.includes('throw');
        
        if (hasAsyncCode && !hasErrorHandling) {
          suggestions.push({
            category: 'maintainability',
            priority: 'high',
            issue: 'Async code without error handling',
            suggestion: 'Add try-catch blocks for async operations',
            example: 'try { await asyncOperation(); } catch (error) { handleError(error); }'
          });
        }
        
        // Check for code duplication
        const lines = codeLines.map(line => line.trim()).filter(line => line.length > 5);
        const duplicateLines = lines.filter((line, index) => lines.indexOf(line) !== index);
        if (duplicateLines.length > 0) {
          suggestions.push({
            category: 'maintainability',
            priority: 'medium',
            issue: 'Potential code duplication detected',
            suggestion: 'Extract common code into reusable functions',
            example: 'Create utility functions for repeated logic'
          });
        }
        
        // Check for comments
        const commentLines = code.match(/\/\*[\s\S]*?\*\/|\/\/.*$/gm) || [];
        const commentRatio = commentLines.length / codeLines.length;
        if (commentRatio < 0.1 && codeLength > 10) {
          suggestions.push({
            category: 'maintainability',
            priority: 'low',
            issue: 'Low comment-to-code ratio',
            suggestion: 'Add comments explaining complex logic',
            example: '// Validate user input before processing'
          });
        }
      }
      
      // Type safety improvements
      if (focus === 'type-safety' || focus === 'all') {
        // Check for any types
        if (code.includes('any')) {
          suggestions.push({
            category: 'type-safety',
            priority: 'high',
            issue: 'Using "any" type reduces type safety',
            suggestion: 'Use specific types or interfaces',
            example: 'interface User { id: string; name: string; }'
          });
        }
        
        // Check for loose equality
        if (code.includes('== ') || code.includes('!= ')) {
          suggestions.push({
            category: 'type-safety',
            priority: 'medium',
            issue: 'Loose equality operators found',
            suggestion: 'Use strict equality operators',
            example: 'Use === and !== instead of == and !='
          });
        }
        
        // Check for missing return types
        const functions = code.match(/function\s+\w+\([^)]*\)/g) || [];
        const functionsWithReturnType = code.match(/function\s+\w+\([^)]*\):\s*\w+/g) || [];
        if (functions.length > functionsWithReturnType.length) {
          suggestions.push({
            category: 'type-safety',
            priority: 'medium',
            issue: 'Functions missing explicit return types',
            suggestion: 'Add return type annotations',
            example: 'function getName(): string { return "name"; }'
          });
        }
      }
      
      // Accessibility improvements
      if (focus === 'accessibility' || focus === 'all') {
        // Check for missing alt text
        if (code.includes('<img') && !code.includes('alt=')) {
          suggestions.push({
            category: 'accessibility',
            priority: 'high',
            issue: 'Images without alt text',
            suggestion: 'Add descriptive alt text to images',
            example: '<img src="..." alt="Description of image" />'
          });
        }
        
        // Check for missing ARIA labels
        if (code.includes('button') && !code.includes('aria-label') && !code.includes('aria-describedby')) {
          suggestions.push({
            category: 'accessibility',
            priority: 'medium',
            issue: 'Interactive elements may need ARIA labels',
            suggestion: 'Add ARIA labels for screen readers',
            example: '<button aria-label="Close dialog">×</button>'
          });
        }
        
        // Check for form labels
        if (code.includes('<input') && !code.includes('label')) {
          suggestions.push({
            category: 'accessibility',
            priority: 'high',
            issue: 'Form inputs without labels',
            suggestion: 'Associate labels with form controls',
            example: '<label htmlFor="name">Name:</label><input id="name" />'
          });
        }
      }
      
      // Filter suggestions by priority if specified
      const filteredSuggestions = priority === 'all' ? suggestions : 
        suggestions.filter(s => s.priority === priority || s.priority === 'critical');
      
      // Sort by priority
      const priorityOrder = { 'critical': 4, 'high': 3, 'medium': 2, 'low': 1 };
      filteredSuggestions.sort((a, b) => (priorityOrder[b.priority as keyof typeof priorityOrder] || 0) - (priorityOrder[a.priority as keyof typeof priorityOrder] || 0));
      
      const improvementResult = {
        action: 'suggest_improvements',
        focus,
        priority,
        codeStats: {
          lines: codeLength,
          functions: (code.match(/function\s+\w+|\w+\s*=\s*\(/g) || []).length,
          comments: (code.match(/\/\*[\s\S]*?\*\/|\/\/.*$/gm) || []).length
        },
        suggestions: filteredSuggestions,
        summary: {
          total: filteredSuggestions.length,
          critical: filteredSuggestions.filter(s => s.priority === 'critical').length,
          high: filteredSuggestions.filter(s => s.priority === 'high').length,
          medium: filteredSuggestions.filter(s => s.priority === 'medium').length,
          low: filteredSuggestions.filter(s => s.priority === 'low').length
        },
        overallScore: Math.max(0, 100 - (filteredSuggestions.length * 10)),
        status: 'success'
      };
      
      const topSuggestions = filteredSuggestions.slice(0, 8);
      return {
        content: [{ type: 'text', text: `Focus: ${focus}\nScore: ${improvementResult.overallScore}/100\nSuggestions: ${improvementResult.summary.total} (${improvementResult.summary.critical}C ${improvementResult.summary.high}H ${improvementResult.summary.medium}M ${improvementResult.summary.low}L)\n\n${topSuggestions.map(s => `[${s.priority.toUpperCase()}] ${s.category}\n  Issue: ${s.issue}\n  Fix: ${s.suggestion}`).join('\n\n')}${filteredSuggestions.length > 8 ? `\n\n... ${filteredSuggestions.length - 8} more suggestions` : ''}` }]
      };
    }
  • The ToolDefinition providing name, description, input schema (code required, optional focus and priority), and annotations for the MCP tool protocol.
    export const suggestImprovementsDefinition: ToolDefinition = {
      name: 'suggest_improvements',
      description: '개선|더 좋게|리팩토링|improve|make better|refactor|optimize|enhance code - Suggest improvements',
      inputSchema: {
        type: 'object',
        properties: {
          code: { type: 'string', description: 'Code to analyze' },
          focus: { type: 'string', description: 'Focus area', enum: ['performance', 'readability', 'maintainability', 'accessibility', 'type-safety'] },
          priority: { type: 'string', description: 'Priority level', enum: ['critical', 'high', 'medium', 'low'] }
        },
        required: ['code']
      },
      annotations: {
        title: 'Suggest Improvements',
        audience: ['user', 'assistant'],
        readOnlyHint: true,
        destructiveHint: false,
        idempotentHint: true,
        openWorldHint: false
      }
    };
  • src/index.ts:123-123 (registration)
    Addition of the tool definition to the central tools array, enabling discovery via MCP 'tools/list' request.
    suggestImprovementsDefinition,
  • src/index.ts:188-188 (registration)
    Mapping of tool name to handler function in the toolHandlers registry object, used for dynamic execution dispatch in MCP 'tools/call'.
    'suggest_improvements': suggestImprovements,
  • src/index.ts:64-64 (registration)
    Import statement bringing in the tool definition and handler implementation for registration.
    import { suggestImprovementsDefinition, suggestImprovements } from './tools/convention/suggestImprovements.js';
Behavior4/5

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

Annotations already provide readOnlyHint=true, destructiveHint=false, idempotentHint=true, and openWorldHint=false, covering safety and idempotency. The description adds no behavioral context beyond what annotations declare, but doesn't contradict them. It mentions 'suggest improvements' which aligns with read-only analysis, so no contradiction exists.

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 a single run-on phrase listing synonyms without proper structure or front-loading of key information. It wastes space on redundant terms ('improve|make better|refactor|optimize|enhance code') rather than providing a clear, concise purpose statement. Every word doesn't earn its place.

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

Completeness3/5

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

Given annotations cover safety and idempotency, and schema fully describes parameters, the description is minimally adequate. However, it lacks output information (no output schema provided) and doesn't explain what the improvements entail or how results are presented. For a code analysis tool with siblings, more context on differentiation would be beneficial.

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?

Schema description coverage is 100%, with clear descriptions for all parameters and enums. The description adds no parameter-specific information beyond what the schema provides, such as examples or usage tips. With high schema coverage, the baseline score of 3 is appropriate as the schema carries the semantic burden.

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

Purpose3/5

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

The description lists synonyms for 'improve' but lacks a specific verb-resource combination. It states 'Suggest improvements' which is tautological with the tool name, and doesn't clearly differentiate what type of improvements (code improvements) or how it differs from siblings like 'validate_code_quality' or 'apply_quality_rules'.

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

Usage Guidelines2/5

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

No explicit guidance on when to use this tool versus alternatives. The description provides no context about appropriate scenarios, prerequisites, or comparisons to sibling tools like 'analyze_complexity' or 'apply_quality_rules'. Usage is implied through parameter enums but not explained.

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

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