Skip to main content
Glama

Yango Tech MCP Server

by zamb124
install.py25.3 kB
#!/usr/bin/env python3 """ 🚀 Universal installer for Yango Tech MCP server Works on Mac and Windows. One command - and everything is ready! Usage: python3 install.py """ import json import os import platform import subprocess import sys from pathlib import Path def print_header(): """Beautiful header.""" print("=" * 60) print("🚀 YANGO TECH MCP SERVER INSTALLATION") print("=" * 60) print() def print_step(step, description): """Print current step.""" print(f"📋 Step {step}: {description}") def print_success(message): """Print success message.""" print(f"✅ {message}") def print_error(message): """Print error message.""" print(f"❌ {message}") def print_info(message): """Print informational message.""" print(f"ℹ️ {message}") def get_os_info(): """Determine operating system.""" system = platform.system().lower() if system == "darwin": return "macos" elif system == "windows": return "windows" elif system == "linux": return "linux" else: return "unknown" def find_python(): """Find Python interpreter and check version.""" python_commands = ["python3", "python", "py"] print_info("Checking Python installation...") for cmd in python_commands: try: result = subprocess.run([cmd, "--version"], capture_output=True, text=True, check=True) # Parse version version_output = result.stdout.strip() if "Python" not in version_output: continue # Extract version numbers (e.g., "Python 3.9.7" -> "3.9.7") version_str = version_output.split("Python ")[1].split()[0] version_parts = version_str.split(".") try: major = int(version_parts[0]) minor = int(version_parts[1]) if len(version_parts) > 1 else 0 print_info(f"Found {version_output} via '{cmd}'") # Check version requirements if major < 3: print_error(f"Python {major}.{minor} is too old. Python 3.8+ required.") continue elif major == 3 and minor < 8: print_error(f"Python 3.{minor} is too old. Python 3.8+ required for FastMCP.") continue else: print_success(f"Python {major}.{minor} meets requirements (3.8+)") return cmd except (ValueError, IndexError): print_error(f"Could not parse Python version: {version_str}") continue except (subprocess.CalledProcessError, FileNotFoundError): continue return None def show_python_installation_guide(os_type): """Show Python installation instructions for different operating systems.""" print() print("=" * 60) print("🐍 PYTHON INSTALLATION REQUIRED") print("=" * 60) print() print("This installer requires Python 3.8 or newer.") print("Please install Python and try again.") print() if os_type == "macos": print("📱 macOS Installation Options:") print() print("Option 1: Official Python (Recommended)") print("1. Visit: https://www.python.org/downloads/") print("2. Download Python 3.12+ for macOS") print("3. Run the installer") print("4. Restart Terminal") print() print("Option 2: Homebrew") print("1. Install Homebrew: https://brew.sh") print("2. Run: brew install python@3.12") print("3. Restart Terminal") print() print("Option 3: pyenv (Advanced)") print("1. Install pyenv: brew install pyenv") print("2. Run: pyenv install 3.12.5") print("3. Run: pyenv global 3.12.5") elif os_type == "windows": print("🪟 Windows Installation Options:") print() print("Option 1: Official Python (Recommended)") print("1. Visit: https://www.python.org/downloads/windows/") print("2. Download Python 3.12+ for Windows") print("3. ⚠️ IMPORTANT: Check 'Add Python to PATH' during installation") print("4. Restart Command Prompt") print() print("Option 2: Microsoft Store") print("1. Open Microsoft Store") print("2. Search for 'Python 3.12'") print("3. Install Python from Microsoft") print("4. Restart Command Prompt") print() print("Option 3: Chocolatey") print("1. Install Chocolatey: https://chocolatey.org") print("2. Run: choco install python") print("3. Restart Command Prompt") elif os_type == "linux": print("🐧 Linux Installation Options:") print() print("Ubuntu/Debian:") print("sudo apt update") print("sudo apt install python3.12 python3.12-venv python3.12-pip") print() print("CentOS/RHEL/Fedora:") print("sudo dnf install python3.12 python3.12-pip") print("# or for older versions:") print("sudo yum install python3.12 python3.12-pip") print() print("Arch Linux:") print("sudo pacman -S python python-pip") print() print("From source (any Linux):") print("1. Download: https://www.python.org/downloads/source/") print("2. Extract and compile Python 3.12+") else: print("🌍 General Installation:") print("1. Visit: https://www.python.org/downloads/") print("2. Download Python 3.12+ for your system") print("3. Follow installation instructions") print("4. Make sure Python is added to PATH") print() print("🔍 Verify Installation:") print("After installation, run:") print(" python3 --version") print(" # or") print(" python --version") print() print("Expected output: Python 3.8.0 or higher") print() print("💡 Then run this installer again:") print(" python3 install.py") print() print("=" * 60) def install_dependencies(python_cmd, project_dir): """Install dependencies.""" print_step(2, "Creating virtual environment and installing dependencies") # Create virtual environment venv_dir = project_dir / ".venv" if not venv_dir.exists(): print_info("Creating virtual environment...") result = subprocess.run([python_cmd, "-m", "venv", str(venv_dir)], cwd=project_dir, capture_output=True, text=True) if result.returncode != 0: print_error(f"Error creating virtual environment: {result.stderr}") return False print_success("Virtual environment created") else: print_success("Virtual environment already exists") # Determine path to Python in virtual environment if get_os_info() == "windows": python_venv_path = venv_dir / "Scripts" / "python.exe" else: python_venv_path = venv_dir / "bin" / "python" # Install project and all dependencies (including FastMCP from pyproject.toml) print_info("Installing project and dependencies...") result = subprocess.run([str(python_venv_path), "-m", "pip", "install", "-e", "."], cwd=project_dir, capture_output=True, text=True) if result.returncode != 0: print_error(f"Error installing project: {result.stderr}") return False print_success("All dependencies installed") return str(python_venv_path) def get_claude_config_path(os_type): """Get path to Claude Desktop configuration.""" if os_type == "macos": return Path.home() / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json" elif os_type == "windows": return Path(os.environ.get("APPDATA", "")) / "Claude" / "claude_desktop_config.json" elif os_type == "linux": return Path.home() / ".config" / "Claude" / "claude_desktop_config.json" else: return None def get_cursor_config_path(os_type): """Get path to Cursor IDE configuration.""" if os_type == "macos": return Path.home() / "Library" / "Application Support" / "Cursor" / "User" / "settings.json" elif os_type == "windows": return Path(os.environ.get("APPDATA", "")) / "Cursor" / "User" / "settings.json" elif os_type == "linux": return Path.home() / ".config" / "Cursor" / "User" / "settings.json" else: return None def check_ide_installations(os_type): """Check which IDEs are installed.""" print_info("Checking installed IDEs...") installed_ides = [] # Check Claude Desktop claude_path = get_claude_config_path(os_type) if claude_path and claude_path.parent.exists(): installed_ides.append("Claude Desktop") print_success("Claude Desktop found") # Check Cursor IDE cursor_path = get_cursor_config_path(os_type) if cursor_path and cursor_path.parent.parent.exists(): # Check Cursor folder exists installed_ides.append("Cursor IDE") print_success("Cursor IDE found") if not installed_ides: print_info("No supported IDEs found") return installed_ides def get_api_credentials(): """Request API key and URL from user.""" print() print("🔑 API Access Setup:") print("To work with Yango Tech API, you need an API key and server URL.") print() # Offer test settings print("Option 1: Use test settings (for demonstration)") print("Option 2: Enter your own settings") print() choice = input("Choose option (1 or 2): ").strip() if choice == "1": api_key = "SBW45ZNrp13OoU4Jps/GiAeFlJR4kB/8leInLS8DwZbYizPL2j2id44dRh/3mK7o5ouvLNE0ZWDqZ8xTP9FQ.DXFjZlsGtCKFIsncT4K6XlzUJJ+ewe7Xre50Yoksz2WSJ8YnaFc6Noqlqrn2GnKHy5Ptju3hsVcO18uFjrlrB4gPFvnpcFxQsni1WFds2quS8F08/Ezx8A8MwQt39WKRCwQ3wpMgwhVpzLrwDj65C/LozcH7fq22rg8opzZzjglc2ThJp4hnbhoYQyw44pp4g4WpKRNsquln7NoubRbeZOaAeaADiJppbn4GwP2OwewEijOgy9ROCW4SWw2lPPeaS7LPr4+j/Oofw7cokgZDXXG0b20b/drI3kdKx6vQx0C36JrM1ud8DnpGhxnCsFqfBu3vfeNXsOAeq+5DDrfITQ==" base_url = "https://api.tst.eu.cloudretail.tech" print_success("Using test settings") return api_key, base_url elif choice == "2": print() api_key = input("Enter your API key: ").strip() if not api_key: print_error("API key cannot be empty") return get_api_credentials() print() print("URL examples:") print("• Test: https://api.tst.eu.cloudretail.tech") print("• Production: https://api.retailtech.yango.com") print() base_url = input("Enter API server URL: ").strip() if not base_url: print_error("URL cannot be empty") return get_api_credentials() # Check URL format if not base_url.startswith(('http://', 'https://')): print_error("URL must start with http:// or https://") return get_api_credentials() print_success("Settings entered") return api_key, base_url else: print_error("Invalid choice. Please try again.") return get_api_credentials() def create_env_file(project_dir, api_key, base_url): """Create .env file.""" print_info("Creating .env file...") env_content = f"""YANGO_TECH_API_KEY={api_key} YANGO_TECH_BASE_URL={base_url} YANGO_TECH_TIMEOUT=30 YANGO_TECH_MAX_RETRIES=3 """ env_path = project_dir / ".env" try: with open(env_path, 'w', encoding='utf-8') as f: f.write(env_content) print_success(f".env file created: {env_path}") return True except Exception as e: print_error(f"Error creating .env file: {e}") return False def create_claude_config(project_dir, python_venv_path, api_key, base_url, os_type): """Create Claude Desktop configuration.""" print_info("Creating Claude Desktop configuration...") config_path = get_claude_config_path(os_type) if not config_path: print_error("Unsupported operating system for Claude Desktop configuration") return False # Create configuration folder if not exists config_path.parent.mkdir(parents=True, exist_ok=True) # Use Python from virtual environment if os_type == "windows": python_command = str(project_dir / ".venv" / "Scripts" / "python.exe") else: python_command = str(project_dir / ".venv" / "bin" / "python") # Create configuration config = { "mcpServers": { "yango-tech": { "command": python_command, "args": [str(project_dir / "server.py")], "cwd": str(project_dir), "env": { "YANGO_TECH_API_KEY": api_key, "YANGO_TECH_BASE_URL": base_url, "YANGO_TECH_TIMEOUT": "30", "YANGO_TECH_MAX_RETRIES": "3" } } } } # Read existing configuration if exists existing_config = {} if config_path.exists(): try: with open(config_path, 'r', encoding='utf-8') as f: existing_config = json.load(f) except json.JSONDecodeError: print_info("Existing Claude configuration file corrupted, creating new one") # Merge configurations if "mcpServers" not in existing_config: existing_config["mcpServers"] = {} existing_config["mcpServers"]["yango-tech"] = config["mcpServers"]["yango-tech"] # Write configuration try: with open(config_path, 'w', encoding='utf-8') as f: json.dump(existing_config, f, indent=2, ensure_ascii=False) print_success(f"Claude Desktop configuration created: {config_path}") return True except Exception as e: print_error(f"Error writing Claude configuration: {e}") return False def create_cursor_config(project_dir, python_venv_path, api_key, base_url, os_type): """Create Cursor IDE configuration.""" print_info("Creating Cursor IDE configuration...") config_path = get_cursor_config_path(os_type) if not config_path: print_error("Unsupported operating system for Cursor IDE configuration") return False # Create configuration folder if not exists config_path.parent.mkdir(parents=True, exist_ok=True) # Use Python from virtual environment if os_type == "windows": python_command = str(project_dir / ".venv" / "Scripts" / "python.exe") else: python_command = str(project_dir / ".venv" / "bin" / "python") # Create MCP server configuration mcp_server_config = { "command": python_command, "args": [str(project_dir / "server.py")], "cwd": str(project_dir), "env": { "YANGO_TECH_API_KEY": api_key, "YANGO_TECH_BASE_URL": base_url, "YANGO_TECH_TIMEOUT": "30", "YANGO_TECH_MAX_RETRIES": "3" } } # Read existing configuration if exists existing_config = {} if config_path.exists(): try: with open(config_path, 'r', encoding='utf-8') as f: existing_config = json.load(f) except json.JSONDecodeError: print_info("Existing Cursor configuration file corrupted, creating new one") # Ensure MCP configuration structure exists if "mcp" not in existing_config: existing_config["mcp"] = {} if "servers" not in existing_config["mcp"]: existing_config["mcp"]["servers"] = {} # Add Yango Tech server existing_config["mcp"]["servers"]["yango-tech"] = mcp_server_config # Write configuration try: with open(config_path, 'w', encoding='utf-8') as f: json.dump(existing_config, f, indent=2, ensure_ascii=False) print_success(f"Cursor IDE configuration created: {config_path}") return True except Exception as e: print_error(f"Error writing Cursor configuration: {e}") return False def generate_config_files(project_dir, python_venv_path, api_key, base_url, os_type): """Generate configuration files in project root for manual setup.""" print_info("Generating configuration files in project root...") # Use Python from virtual environment if os_type == "windows": python_command = str(project_dir / ".venv" / "Scripts" / "python.exe") else: python_command = str(project_dir / ".venv" / "bin" / "python") # Claude Desktop configuration claude_config = { "mcpServers": { "yango-tech": { "command": python_command, "args": [str(project_dir / "server.py")], "cwd": str(project_dir), "env": { "YANGO_TECH_API_KEY": api_key, "YANGO_TECH_BASE_URL": base_url, "YANGO_TECH_TIMEOUT": "30", "YANGO_TECH_MAX_RETRIES": "3" } } } } # Cursor IDE configuration cursor_config = { "mcp": { "servers": { "yango-tech": { "command": python_command, "args": [str(project_dir / "server.py")], "cwd": str(project_dir), "env": { "YANGO_TECH_API_KEY": api_key, "YANGO_TECH_BASE_URL": base_url, "YANGO_TECH_TIMEOUT": "30", "YANGO_TECH_MAX_RETRIES": "3" } } } } } try: # Save Claude Desktop config claude_config_path = project_dir / "claude_desktop_config.json" with open(claude_config_path, 'w', encoding='utf-8') as f: json.dump(claude_config, f, indent=2, ensure_ascii=False) print_success(f"Claude Desktop config saved: {claude_config_path}") # Save Cursor IDE config cursor_config_path = project_dir / "cursor_settings.json" with open(cursor_config_path, 'w', encoding='utf-8') as f: json.dump(cursor_config, f, indent=2, ensure_ascii=False) print_success(f"Cursor IDE config saved: {cursor_config_path}") return True except Exception as e: print_error(f"Error generating config files: {e}") return False def test_installation(python_venv_path, project_dir, api_key, base_url): """Test installation.""" # Create test script test_script = f''' import sys import os sys.path.insert(0, "{project_dir}") os.environ["YANGO_TECH_API_KEY"] = "{api_key}" os.environ["YANGO_TECH_BASE_URL"] = "{base_url}" os.environ["YANGO_TECH_TIMEOUT"] = "10" os.environ["YANGO_TECH_MAX_RETRIES"] = "1" try: from client import YangoTechClient, YangoTechAPIError from models import AuthConfig # Simple configuration test config = AuthConfig( api_key=os.environ["YANGO_TECH_API_KEY"], base_url=os.environ["YANGO_TECH_BASE_URL"], timeout=10, max_retries=1 ) # Create client instance to verify configuration works client = YangoTechClient(config) print("✅ All modules loaded correctly") print("✅ Client configuration created successfully") except Exception as e: print(f"❌ Test error: {{e}}") sys.exit(1) ''' # Run test result = subprocess.run([str(python_venv_path), "-c", test_script], cwd=project_dir, capture_output=True, text=True) if result.returncode == 0: print(result.stdout) return True else: print_error(f"Test error: {result.stderr}") return False def main(): """Main installation function.""" print_header() # Determine current project directory project_dir = Path(__file__).parent.absolute() print_info(f"Project folder: {project_dir}") # Determine OS os_type = get_os_info() print_info(f"Operating system: {os_type}") # Check installed IDEs installed_ides = check_ide_installations(os_type) # Find Python print_step(1, "Finding Python interpreter") python_cmd = find_python() if not python_cmd: show_python_installation_guide(os_type) sys.exit(1) print_success(f"Found Python: {python_cmd}") # Install dependencies python_venv_path = install_dependencies(python_cmd, project_dir) if not python_venv_path: print_error("Error installing dependencies") print_info("Use manual setup in MANUAL_SETUP.md") sys.exit(1) # Get API settings print_step(3, "API access setup") api_key, base_url = get_api_credentials() print_success("API settings saved") # Create .env file if not create_env_file(project_dir, api_key, base_url): print_error("Error creating .env file") sys.exit(1) # Create configurations for installed IDEs print_step(4, "Creating IDE configurations") configs_created = [] configs_attempted = [] # Create Claude Desktop configuration if installed if "Claude Desktop" in installed_ides: configs_attempted.append("Claude Desktop") if create_claude_config(project_dir, python_venv_path, api_key, base_url, os_type): configs_created.append("Claude Desktop") else: print_error("Error creating Claude Desktop configuration") # Create Cursor IDE configuration if installed if "Cursor IDE" in installed_ides: configs_attempted.append("Cursor IDE") if create_cursor_config(project_dir, python_venv_path, api_key, base_url, os_type): configs_created.append("Cursor IDE") else: print_error("Error creating Cursor IDE configuration") # Always generate configuration files in project root print_step(5, "Generating configuration files") if generate_config_files(project_dir, python_venv_path, api_key, base_url, os_type): print_success("Configuration files generated in project root") else: print_error("Error generating configuration files") # Summary of what was configured if configs_created: print_success(f"Direct IDE configurations created for: {', '.join(configs_created)}") if not installed_ides: print_info("No IDEs detected. Configuration files saved in project root for manual setup.") elif not configs_created: print_info("IDE configurations failed. Use manual setup with generated files.") # Testing print_step(6, "Testing installation") if not test_installation(python_venv_path, project_dir, api_key, base_url): print_error("Error testing installation") print_info("Check settings manually using generated configuration files") # Final instructions print() print("🎉 INSTALLATION COMPLETED SUCCESSFULLY!") print("=" * 60) print() if configs_created or not installed_ides: print("📋 What's next:") step_num = 1 if "Claude Desktop" in configs_created: print(f"{step_num}. Restart Claude Desktop") step_num += 1 if "Cursor IDE" in configs_created: print(f"{step_num}. Restart Cursor IDE") step_num += 1 if not installed_ides: print(f"{step_num}. Install Claude Desktop or Cursor IDE") print(f"{step_num + 1}. Use generated configuration files for manual setup") step_num += 2 print(f"{step_num}. You should see 6 Yango Tech tools") print(f"{step_num + 1}. Test: 'Get product information'") print() print("🧪 Test commands:") print("• 'Show status of order 240920-728268'") print("• 'What about order 240920-728268?'") print("• 'Show 5 products from catalog'") print("• 'Show product stocks in stores'") print() print("📁 Generated configuration files:") print(f" Claude Desktop: {project_dir}/claude_desktop_config.json") print(f" Cursor IDE: {project_dir}/cursor_settings.json") print() if configs_created: print("📁 Active configurations:") if "Claude Desktop" in configs_created: print(f" Claude Desktop: {get_claude_config_path(os_type)}") if "Cursor IDE" in configs_created: print(f" Cursor IDE: {get_cursor_config_path(os_type)}") print() if not installed_ides: print("💡 Next steps for manual setup:") print("1. Install Claude Desktop and/or Cursor IDE") print("2. Copy contents from generated config files to IDE settings") print("3. See MANUAL_SETUP.md for detailed instructions") print() if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\n⏹️ Installation interrupted by user") print() print("📖 For manual setup use: MANUAL_SETUP.md") sys.exit(1) except Exception as e: print_error(f"Critical error: {e}") print() print("📖 If installer doesn't work, use manual setup instructions:") print(" 👉 Open MANUAL_SETUP.md file") print(" 👉 It contains detailed instructions for Claude Desktop and Cursor IDE") sys.exit(1)

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/zamb124/yangotech_mcp'

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