Skip to main content
Glama
quality.ts6.45 kB
import { z } from "zod"; /** * Quality Tools - specific code quality and security analysis */ // ============================================ // Analyze Complexity // ============================================ export const analyzeComplexitySchema = { name: "analyze_complexity", description: "Analyzes code complexity to identify refactoring candidates", inputSchema: z.object({ code: z.string().describe("Source code to analyze"), language: z.string().describe("Programming language"), }) }; export function analyzeComplexityHandler(args: { code: string; language: string }) { const { code, language } = args; // 1. Cyclomatic Complexity (heuristic: count decision points) const lines = code.split('\n'); let complexity = 1; // Base path let maxNesting = 0; let currentNesting = 0; const branchPatterns = [ /\bif\b/, /\belse\b/, /\bfor\b/, /\bwhile\b/, /\bcase\b/, /\bcatch\b/, /\?.*\:/, /\|\|/, /\&\&/ ]; // 2. Halstead Volume (heuristic: count operands and operators) let operators = 0; let operands = 0; const operatorPattern = /[\+\-\*\/\=\%\&\>\|\<\!\^]/g; const operandPattern = /\b[a-zA-Z_]\w*\b/g; lines.forEach(line => { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith('//') || trimmed.startsWith('*')) return; // Nesting if (trimmed.endsWith('{') || trimmed.endsWith(':')) currentNesting++; if (trimmed.startsWith('}') || trimmed.startsWith('end')) currentNesting--; maxNesting = Math.max(maxNesting, currentNesting); // Branching branchPatterns.forEach(p => { if (p.test(line)) complexity++; }); // Halstead const ops = line.match(operatorPattern); if (ops) operators += ops.length; const oprs = line.match(operandPattern); if (oprs) operands += oprs.length; }); // Score Calculation let rating = "Low"; let status = "✅ Good"; if (complexity > 20 || maxNesting > 4) { rating = "High"; status = "⚠️ Refactor Needed"; } else if (complexity > 10 || maxNesting > 2) { rating = "Medium"; status = "⚠️ Warning"; } const simpleMetrics = ` - **Cyclomatic Complexity**: ~${complexity} (Target: < 10) - **Nesting Depth**: ${maxNesting} (Target: < 3) - **Estimated Operators**: ${operators} - **Estimated Operands**: ${operands} `; const recommendations = []; if (complexity > 10) recommendations.push("- Extract complex logic into helper functions."); if (maxNesting > 3) recommendations.push("- Use guard clauses (early returns) to flatten nesting."); if (lines.length > 200) recommendations.push("- Module is too large; consider splitting."); return { content: [{ type: "text", text: `# Code Quality Report\n\n**Rating**: ${rating} - ${status}\n${simpleMetrics}\n\n## Recommendations\n${recommendations.length > 0 ? recommendations.join('\n') : "- Code structure looks healthy."}` }] }; } // ============================================ // Security Scan // ============================================ export const securityScanSchema = { name: "security_scan", description: "Scans code for common security vulnerabilities (OWASP Top 10)", inputSchema: z.object({ code: z.string().describe("Source code to scan"), language: z.string().describe("Programming language"), focus: z.enum(["injection", "auth", "secrets", "all"]).optional().default("all") }) }; export function securityScanHandler(args: { code: string; language: string; focus?: string }) { const { code, language, focus } = args; const risks: string[] = []; // --- Secrets Detection --- const secretPatterns = [ /(api_?key|secret|password|auth_?token)[\s]*[:=][\s]*['"][a-zA-Z0-9_\-\.]{8,}['"]/i, // Variable assignment /BEGIN RSA PRIVATE KEY/, // Keys /eyJ[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+/ // JWT structure ]; if (focus === "all" || focus === "secrets") { secretPatterns.forEach(p => { if (p.test(code)) { const match = code.match(p)?.[0] || "pattern"; risks.push(`🚨 **Hardcoded Secret**: Detected potential secret at \`${match.substring(0, 15)}...\`. Use environment variables.`); } }); } // --- Injection Risks --- if (focus === "all" || focus === "injection") { if (/execute\s*\(\s*['"]SELECT.*?\+/i.test(code) || /query\s*\(\s*['"].*?\$\{/i.test(code)) { risks.push("🚨 **SQL Injection**: String concatenation detected in SQL query. Use parameterized queries."); } if (/(exec|spawn|eval|system)\s*\(/i.test(code)) { risks.push("⚠️ **RCE Risk**: Dangerous function execution detected (`eval`, `exec`). Ensure strict input validation."); } if (/dangerouslySetInnerHTML/.test(code)) { risks.push("⚠️ **XSS Risk**: `dangerouslySetInnerHTML` used in React. Sanitize content."); } } // --- Auth & Crypto --- if (focus === "all" || focus === "auth") { if (/password\s*==\s*|password\s*===/i.test(code)) { risks.push("⚠️ **Timing Attack**: Insecure password comparison. Use `crypto.timingSafeEqual`."); } if (/md5\(/i.test(code) || /sha1\(/i.test(code)) { risks.push("⚠️ **Weak Crypto**: MD5/SHA1 detected. Use SHA256 or bcrypt/argon2."); } } // --- General Best Practices --- if (code.includes("http://")) { risks.push("⚠️ **Insecure Transport**: `http://` URL found. Use `https://`."); } if (/console\.log/.test(code) && !/debug/i.test(code) && code.length > 500) { risks.push("ℹ️ **Cleanup**: `console.log` statements found in production-like code."); } return { content: [{ type: "text", text: `# Security Scan Report\n\n**Focus**: ${focus}\n\n## Findings\n${risks.length > 0 ? risks.join('\n\n') : "✅ No obvious issues detected via static analysis."}\n\n*Note: This scan checks for common patterns but is not a replacement for dedicated security tools like Snyk or SonarQube.*` }] }; } // Export all export const qualityTools = { analyzeComplexitySchema, analyzeComplexityHandler, securityScanSchema, securityScanHandler };

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/millsydotdev/Code-MCP'

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