Skip to main content
Glama

CodeAnalysis MCP Server

by 0xjcf
maturity_analyzer.py8.87 kB
#!/usr/bin/env python3 """Maturity Model Analyzer This script analyzes the codebase to identify, track, and report on the maturity levels of components based on their documentation. Maturity: beta Why: - Tracking component maturity helps set proper expectations for usage - Provides visibility into the stability of different parts of the codebase - Helps plan development efforts to mature experimental components - Identifies deprecated components that should be migrated away from """ import argparse import json import os import re from pathlib import Path from datetime import datetime import matplotlib.pyplot as plt import pandas as pd # Define maturity levels and their order MATURITY_LEVELS = ["experimental", "beta", "stable", "deprecated"] MATURITY_LEVEL_MAP = {level: idx for idx, level in enumerate(MATURITY_LEVELS)} class MaturityAnalyzer: """Analyzes component maturity throughout the codebase.""" def __init__(self, output_dir=None): """Initialize the maturity analyzer.""" if output_dir is None: # Default to a maturity directory at the script location self.output_dir = Path(__file__).parent / "output" else: self.output_dir = Path(output_dir) # Ensure output directory exists self.output_dir.mkdir(parents=True, exist_ok=True) # Initialize data structures self.components = {} self.maturity_stats = {level: 0 for level in MATURITY_LEVELS} # Define regex patterns for extracting maturity info self.patterns = { # JavaScript/TypeScript JSDoc pattern "js_ts": re.compile(r'@maturity\s+(experimental|beta|stable|deprecated)'), # Python docstring pattern "py": re.compile(r'Maturity:\s+(experimental|beta|stable|deprecated)', re.IGNORECASE), # Pine Script comment pattern "pine": re.compile(r'@maturity=(experimental|beta|stable|deprecated)'), # Solidity NatSpec pattern "sol": re.compile(r'@maturity\s+(experimental|beta|stable|deprecated)') } def analyze_file(self, file_path): """Analyze a single file for component maturity information.""" try: with open(file_path, 'r', encoding='utf-8') as f: content = f.read() file_ext = file_path.suffix.lower() component_name = file_path.stem # Determine which pattern to use based on file extension if file_ext in ['.js', '.jsx', '.ts', '.tsx']: pattern = self.patterns["js_ts"] elif file_ext == '.py': pattern = self.patterns["py"] elif file_ext in ['.pine', '.pinescript']: pattern = self.patterns["pine"] elif file_ext == '.sol': pattern = self.patterns["sol"] else: # Unsupported file type return None # Extract maturity level match = pattern.search(content) if match: maturity = match.group(1).lower() # Extract component name from file content if available name_match = re.search(r'(?:class|function|component|contract)\s+(\w+)', content) if name_match: component_name = name_match.group(1) # Extract since version if available since_match = re.search(r'@since\s+([\d\.]+)', content) since_version = since_match.group(1) if since_match else "unknown" # Extract expected next level if available (mainly for experimental/beta) next_level = None next_level_match = re.search(r'@next\s+(beta|stable)', content) if next_level_match: next_level = next_level_match.group(1) # Create component entry self.components[str(file_path)] = { "name": component_name, "path": str(file_path), "maturity": maturity, "since_version": since_version, "next_level": next_level, "last_modified": datetime.fromtimestamp(file_path.stat().st_mtime).isoformat() } # Update statistics self.maturity_stats[maturity] += 1 return maturity return None except Exception as e: print(f"Error analyzing {file_path}: {e}") return None def analyze_directory(self, directory_path, exclude_patterns=None): """Analyze all relevant files in a directory for maturity information.""" if exclude_patterns is None: exclude_patterns = ['node_modules', 'dist', 'build', '.git'] directory_path = Path(directory_path) if not directory_path.is_dir(): print(f"Error: {directory_path} is not a directory") return # Walk through the directory for root, dirs, files in os.walk(directory_path): # Skip excluded directories dirs[:] = [d for d in dirs if not any(pattern in str(Path(root) / d) for pattern in exclude_patterns)] for file in files: file_path = Path(root) / file if file_path.suffix.lower() in ['.js', '.jsx', '.ts', '.tsx', '.py', '.pine', '.pinescript', '.sol']: self.analyze_file(file_path) def generate_report(self): """Generate a JSON report of component maturity.""" report = { "metadata": { "timestamp": datetime.now().isoformat(), "total_components": len(self.components), "maturity_stats": self.maturity_stats }, "components": self.components } # Save to file report_path = self.output_dir / "maturity_report.json" with open(report_path, 'w', encoding='utf-8') as f: json.dump(report, f, indent=2) print(f"Maturity report generated at {report_path}") return report def generate_visualizations(self): """Generate visualizations of component maturity.""" if not self.components: print("No components found. Run analyze_directory() first.") return # Create a DataFrame for easier visualization df = pd.DataFrame.from_dict(self.components, orient='index') # Maturity distribution pie chart plt.figure(figsize=(10, 6)) maturity_counts = df['maturity'].value_counts() plt.pie(maturity_counts, labels=maturity_counts.index, autopct='%1.1f%%', colors=['#FF9999', '#66B2FF', '#99FF99', '#FFCC99']) plt.title('Component Maturity Distribution') plt.savefig(self.output_dir / "maturity_distribution.png") plt.close() # Maturity by file type bar chart plt.figure(figsize=(12, 6)) file_types = df['path'].apply(lambda x: os.path.splitext(x)[1][1:]) maturity_by_filetype = pd.crosstab(file_types, df['maturity']) maturity_by_filetype.plot(kind='bar', stacked=True, color=['#FF9999', '#66B2FF', '#99FF99', '#FFCC99']) plt.title('Component Maturity by File Type') plt.xlabel('File Type') plt.ylabel('Number of Components') plt.legend(title='Maturity Level') plt.tight_layout() plt.savefig(self.output_dir / "maturity_by_filetype.png") plt.close() print(f"Visualizations saved to {self.output_dir}") def main(): parser = argparse.ArgumentParser(description="Analyze component maturity") parser.add_argument("--directory", help="Directory to analyze", default=".") parser.add_argument("--output", help="Output directory for reports and visualizations") parser.add_argument("--exclude", help="Comma-separated list of directories to exclude") args = parser.parse_args() # Initialize analyzer analyzer = MaturityAnalyzer(output_dir=args.output) # Set up exclude patterns exclude_patterns = ['node_modules', 'dist', 'build', '.git'] if args.exclude: exclude_patterns.extend(args.exclude.split(',')) # Analyze directory analyzer.analyze_directory(args.directory, exclude_patterns=exclude_patterns) # Generate report and visualizations analyzer.generate_report() analyzer.generate_visualizations() if __name__ == "__main__": main()

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/0xjcf/MCP_CodeAnalysis'

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