Model Control Plane (MCP) Server

import os import requests import json from typing import Dict, Any, Optional, List, Union import sys import tempfile import subprocess from datetime import datetime def analyze_repo(repo_url: str, base_url: str = "http://localhost:8000", capture_output: bool = False) -> Dict[str, Any]: """ Analyze a Git repository and return useful information about it. Args: repo_url: URL of the Git repository to analyze base_url: URL of the MCP server capture_output: If True, capture and return the output instead of printing Returns: Dict containing repository analysis information """ results = {} # Helper function to log or print results def log_result(key: str, value: Any): if capture_output: results[key] = value else: print(f"\n=== {key} ===") if isinstance(value, (dict, list)): print(json.dumps(value, indent=2)) else: print(value) # Clone repo to temporary directory try: temp_dir = tempfile.mkdtemp(prefix="mcp_git_analysis_") log_result("temporary_directory", temp_dir) # Clone the repository clone_start = datetime.now() log_result("cloning_repo", f"Cloning {repo_url} into {temp_dir}") subprocess.run(["git", "clone", "--depth", "1", repo_url, temp_dir], check=True, capture_output=True) clone_duration = (datetime.now() - clone_start).total_seconds() log_result("clone_duration_seconds", clone_duration) # Get basic repository info repo_info = {} # Get commit count (approximate with depth=1) try: commit_count_cmd = subprocess.run( ["git", "rev-list", "--count", "HEAD"], cwd=temp_dir, check=True, capture_output=True, text=True ) repo_info["commit_count"] = int(commit_count_cmd.stdout.strip()) except (subprocess.SubprocessError, ValueError): repo_info["commit_count"] = "unknown" # Get last commit info try: last_commit_cmd = subprocess.run( ["git", "log", "-1", "--pretty=format:%h|%an|%ad|%s"], cwd=temp_dir, check=True, capture_output=True, text=True ) commit_parts = last_commit_cmd.stdout.split("|") repo_info["last_commit"] = { "hash": commit_parts[0], "author": commit_parts[1], "date": commit_parts[2], "message": commit_parts[3] if len(commit_parts) > 3 else "" } except subprocess.SubprocessError: repo_info["last_commit"] = "unknown" # Get file types and count file_types = {} try: for root, _, files in os.walk(temp_dir): if ".git" in root: continue for file in files: ext = os.path.splitext(file)[1].lower() if ext: file_types[ext] = file_types.get(ext, 0) + 1 else: file_types["no_extension"] = file_types.get("no_extension", 0) + 1 # Sort by count file_types = {k: v for k, v in sorted(file_types.items(), key=lambda item: item[1], reverse=True)} repo_info["file_types"] = file_types repo_info["file_count"] = sum(file_types.values()) # Determine primary language lang_map = { ".py": "Python", ".js": "JavaScript", ".ts": "TypeScript", ".java": "Java", ".c": "C", ".cpp": "C++", ".cs": "C#", ".go": "Go", ".rs": "Rust", ".rb": "Ruby", ".php": "PHP", ".html": "HTML", ".css": "CSS", ".sh": "Shell", ".md": "Markdown" } # Find the most common extension that maps to a language primary_lang = "Unknown" for ext, count in file_types.items(): if ext in lang_map: primary_lang = lang_map[ext] break repo_info["primary_language"] = primary_lang except Exception as e: repo_info["file_count"] = "error" repo_info["error"] = str(e) log_result("repository_info", repo_info) # Add repository URL to results results["repository"] = repo_url results["timestamp"] = datetime.now().isoformat() # Enhance with commit history try: # Get recent commits (limited to avoid excessive data) commit_history_cmd = subprocess.run( ["git", "log", "--pretty=format:%h|%an|%ad|%s", "-n", "5"], cwd=temp_dir, check=True, capture_output=True, text=True ) commit_history = [] for line in commit_history_cmd.stdout.strip().split('\n'): if line: parts = line.split('|') commit_history.append({ "hash": parts[0], "author": parts[1], "date": parts[2], "message": parts[3] if len(parts) > 3 else "" }) if commit_history: results["commit_history"] = commit_history except Exception as e: log_result("commit_history_error", str(e)) # Also try server-side analysis if the MCP server is available try: # First check if the server is responding at all try: models_response = requests.get(f"{base_url}/v1/models", timeout=5) if models_response.status_code != 200: log_result("server_connection_error", f"MCP server returned status {models_response.status_code}") raise Exception(f"MCP server returned status {models_response.status_code}") except requests.RequestException as e: log_result("server_connection_error", f"Failed to connect to MCP server: {str(e)}") raise e # Test repository analysis through MCP API analyze_payload = {"repo_url": repo_url} try: response = requests.post(f"{base_url}/v1/git/analyze", json=analyze_payload, timeout=10) if response.status_code == 200: server_analysis = response.json() log_result("server_analysis", server_analysis) elif response.status_code == 404: # Endpoint doesn't exist - handle gracefully log_result("server_analysis_status", "Git analysis endpoint not available (404)") log_result("server_analysis_error", "The /v1/git/analyze endpoint is not implemented in this MCP server version") else: log_result("server_analysis_error", f"Error: {response.status_code} - {response.text}") except requests.RequestException as e: log_result("server_analysis_error", f"Request failed: {str(e)}") except Exception as e: log_result("server_connection_error", str(e)) # Clean up try: import shutil shutil.rmtree(temp_dir) log_result("cleanup", "Removed temporary directory") except Exception as e: log_result("cleanup_error", str(e)) except Exception as e: log_result("error", str(e)) # Return the collected results if in capture mode if capture_output: return results else: return {"status": "completed", "output": "printed to console"} def test_git_integration(base_url: str = "http://localhost:8000", repo_url: str = None): """Test the Git integration in the MCP server""" if not repo_url: # If no repo_url is provided as an argument, check if it was passed from CLI if len(sys.argv) > 1: repo_url = sys.argv[1] else: print("Error: Please provide a Git repository URL") print("Usage: python test_git_integration.py <git-repo-url>") sys.exit(1) print(f"Testing Git integration with repository: {repo_url}") print(f"MCP server: {base_url}") # Run the repository analysis analyze_repo(repo_url, base_url, capture_output=False) print("\nGit integration test completed.") if __name__ == "__main__": test_git_integration()