Skip to main content
Glama

MCP Azure DevOps Server

validate_setup.py13.8 kB
#!/usr/bin/env python3 """ MCP Azure DevOps Server Setup Validation Script This script validates the setup and configuration of the MCP Azure DevOps server to help diagnose common issues before they cause problems. """ import os import sys import subprocess import json from pathlib import Path from typing import Dict, List, Tuple, Any class SetupValidator: """Validates MCP Azure DevOps server setup and configuration.""" def __init__(self): self.issues = [] self.warnings = [] self.info = [] def log_issue(self, message: str): """Log a critical issue.""" self.issues.append(f"❌ ISSUE: {message}") def log_warning(self, message: str): """Log a warning.""" self.warnings.append(f"⚠️ WARNING: {message}") def log_info(self, message: str): """Log informational message.""" self.info.append(f"ℹ️ INFO: {message}") def validate_python_version(self) -> bool: """Validate Python version is 3.10 or higher.""" version = sys.version_info if version.major < 3 or (version.major == 3 and version.minor < 10): self.log_issue(f"Python version {version.major}.{version.minor} is not supported. Requires Python 3.10+") return False else: self.log_info(f"Python version {version.major}.{version.minor}.{version.micro} is supported") return True def validate_virtual_environment(self) -> bool: """Check if running in a virtual environment.""" if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix): self.log_info("Running in virtual environment") return True else: self.log_warning("Not running in a virtual environment. Consider using 'python -m venv .venv'") return False def validate_dependencies(self) -> bool: """Validate required dependencies are installed.""" required_packages = ['mcp', 'azure-devops'] missing_packages = [] for package in required_packages: try: __import__(package.replace('-', '_')) self.log_info(f"Package '{package}' is installed") except ImportError: missing_packages.append(package) self.log_issue(f"Required package '{package}' is not installed") if missing_packages: self.log_issue(f"Install missing packages with: pip install {' '.join(missing_packages)}") return False return True def validate_environment_variables(self) -> bool: """Validate required environment variables.""" required_vars = { 'AZURE_DEVOPS_ORG_URL': 'Azure DevOps organization URL (e.g., https://dev.azure.com/your-org)', 'AZURE_DEVOPS_PAT': 'Personal Access Token for Azure DevOps' } missing_vars = [] for var, description in required_vars.items(): value = os.getenv(var) if not value: missing_vars.append(var) self.log_issue(f"Missing environment variable: {var} ({description})") else: # Mask PAT for security display_value = value if var != 'AZURE_DEVOPS_PAT' else f"{value[:8]}...{value[-4:]}" self.log_info(f"Environment variable {var} is set: {display_value}") return len(missing_vars) == 0 def validate_azure_devops_connection(self) -> bool: """Test Azure DevOps connection.""" try: from mcp_azure_devops.azure_devops_client import AzureDevOpsClient client = AzureDevOpsClient() projects = client.get_projects() self.log_info(f"Successfully connected to Azure DevOps. Found {len(projects)} projects:") for project in projects[:5]: # Show first 5 projects self.log_info(f" - {project.name}") if len(projects) > 5: self.log_info(f" ... and {len(projects) - 5} more projects") return True except Exception as e: self.log_issue(f"Failed to connect to Azure DevOps: {str(e)}") return False def validate_mcp_server_executable(self) -> bool: """Validate the MCP server executable exists and is accessible.""" try: # Try to find the executable result = subprocess.run([sys.executable, '-m', 'mcp_azure_devops.server', '--help'], capture_output=True, text=True, timeout=10) if result.returncode == 0: self.log_info("MCP server executable is accessible") return True else: self.log_issue("MCP server executable failed to run") return False except subprocess.TimeoutExpired: self.log_warning("MCP server executable test timed out") return False except Exception as e: self.log_issue(f"Failed to test MCP server executable: {str(e)}") return False def validate_mcp_server_tools(self) -> bool: """Test that the MCP server can list its tools.""" try: from mcp_azure_devops.server import MCPAzureDevOpsServer server = MCPAzureDevOpsServer() tools_count = len(server.tools) self.log_info(f"MCP server defines {tools_count} tools") # List some key tools key_tools = ['create_work_item', 'get_work_item', 'create_wiki_page', 'server_health_check'] found_tools = [tool.name for tool in server.tools if tool.name in key_tools] for tool in found_tools: self.log_info(f" ✓ {tool}") missing_tools = set(key_tools) - set(found_tools) for tool in missing_tools: self.log_warning(f" ✗ {tool} (not found)") return tools_count > 0 except Exception as e: self.log_issue(f"Failed to validate MCP server tools: {str(e)}") return False def find_cline_config_files(self) -> List[Path]: """Find potential Cline MCP configuration files.""" possible_paths = [ Path.home() / "AppData" / "Roaming" / "Code" / "User" / "globalStorage" / "saoudrizwan.claude-dev" / "settings" / "cline_mcp_settings.json", Path.home() / ".config" / "Code" / "User" / "globalStorage" / "saoudrizwan.claude-dev" / "settings" / "cline_mcp_settings.json", Path.home() / "Library" / "Application Support" / "Code" / "User" / "globalStorage" / "saoudrizwan.claude-dev" / "settings" / "cline_mcp_settings.json", ] found_files = [] for path in possible_paths: if path.exists(): found_files.append(path) return found_files def validate_cline_configuration(self) -> bool: """Validate Cline MCP configuration.""" config_files = self.find_cline_config_files() if not config_files: self.log_warning("No Cline MCP configuration files found") self.log_info("Expected location (Windows): %APPDATA%\\Code\\User\\globalStorage\\saoudrizwan.claude-dev\\settings\\cline_mcp_settings.json") return False for config_file in config_files: self.log_info(f"Found Cline config: {config_file}") try: with open(config_file, 'r') as f: config = json.load(f) if 'mcpServers' not in config: self.log_warning(f"No mcpServers section in {config_file}") continue if 'mcp-azure-devops' not in config['mcpServers']: self.log_warning(f"No mcp-azure-devops server configured in {config_file}") continue server_config = config['mcpServers']['mcp-azure-devops'] # Check command path command = server_config.get('command', '') if not command: self.log_issue(f"No command specified for mcp-azure-devops in {config_file}") elif not Path(command).exists(): self.log_issue(f"Command path does not exist: {command}") else: self.log_info(f"Command path exists: {command}") # Check environment variables env = server_config.get('env', {}) required_env_vars = ['AZURE_DEVOPS_ORG_URL', 'AZURE_DEVOPS_PAT'] for var in required_env_vars: if var not in env: self.log_issue(f"Missing {var} in server environment configuration") else: display_value = env[var] if var != 'AZURE_DEVOPS_PAT' else f"{env[var][:8]}...{env[var][-4:]}" self.log_info(f"Environment variable {var} configured: {display_value}") # Check if disabled if server_config.get('disabled', False): self.log_warning("mcp-azure-devops server is disabled in configuration") else: self.log_info("mcp-azure-devops server is enabled") return True except Exception as e: self.log_issue(f"Failed to parse config file {config_file}: {str(e)}") return False def generate_sample_config(self) -> str: """Generate a sample Cline configuration.""" venv_path = Path(sys.prefix) if sys.platform == "win32": executable_path = venv_path / "Scripts" / "mcp-azure-devops.exe" else: executable_path = venv_path / "bin" / "mcp-azure-devops" sample_config = { "mcpServers": { "mcp-azure-devops": { "command": str(executable_path), "args": [], "env": { "AZURE_DEVOPS_ORG_URL": "https://dev.azure.com/your-organization", "AZURE_DEVOPS_PAT": "your-personal-access-token" }, "disabled": False, "autoApprove": [] } } } return json.dumps(sample_config, indent=2) def run_validation(self) -> bool: """Run all validation checks.""" print("🔍 MCP Azure DevOps Server Setup Validation") print("=" * 50) checks = [ ("Python Version", self.validate_python_version), ("Virtual Environment", self.validate_virtual_environment), ("Dependencies", self.validate_dependencies), ("Environment Variables", self.validate_environment_variables), ("Azure DevOps Connection", self.validate_azure_devops_connection), ("MCP Server Executable", self.validate_mcp_server_executable), ("MCP Server Tools", self.validate_mcp_server_tools), ("Cline Configuration", self.validate_cline_configuration), ] results = {} for check_name, check_func in checks: print(f"\n🔍 Checking {check_name}...") try: results[check_name] = check_func() except Exception as e: self.log_issue(f"Validation check '{check_name}' failed with error: {str(e)}") results[check_name] = False # Print results print("\n" + "=" * 50) print("📋 VALIDATION RESULTS") print("=" * 50) # Print issues if self.issues: print("\n❌ CRITICAL ISSUES:") for issue in self.issues: print(f" {issue}") # Print warnings if self.warnings: print("\n⚠️ WARNINGS:") for warning in self.warnings: print(f" {warning}") # Print info if self.info: print("\n✅ SUCCESS:") for info in self.info: print(f" {info}") # Overall status has_critical_issues = len(self.issues) > 0 print(f"\n{'=' * 50}") if has_critical_issues: print("❌ VALIDATION FAILED - Critical issues found") print("\n📝 SAMPLE CONFIGURATION:") print("Add this to your cline_mcp_settings.json file:") print("-" * 40) print(self.generate_sample_config()) return False else: print("✅ VALIDATION PASSED - Setup looks good!") if self.warnings: print("⚠️ Some warnings were found, but they shouldn't prevent the server from working.") return True def main(): """Main entry point.""" validator = SetupValidator() success = validator.run_validation() if not success: print("\n🔧 NEXT STEPS:") print("1. Fix the critical issues listed above") print("2. Restart VS Code/Cline after making changes") print("3. Run this validation script again") print("4. Check the MCP server logs for additional details") sys.exit(0 if success else 1) 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/xrmghost/mcp-azure-devops'

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