Skip to main content
Glama

Gemini MCP Server

run-server.ps164.1 kB
<# .SYNOPSIS Installation, configuration, and launch script for Zen MCP server on Windows. .DESCRIPTION This PowerShell script prepares the environment for the Zen MCP server: - Installs and checks Python 3.10+ (with venv or uv if available) - Installs required Python dependencies - Configures environment files (.env) - Validates presence of required API keys - Cleans Python caches and obsolete Docker artifacts - Offers automatic integration with Claude Desktop, Gemini CLI, VSCode, Cursor, Windsurf, and Trae - Manages configuration file backups (max 3 retained) - Allows real-time log following or server launch .PARAMETER Help Shows script help. .PARAMETER Version Shows Zen MCP server version. .PARAMETER Follow Follows server logs in real time. .PARAMETER Config Shows configuration instructions for Claude and other compatible clients. .PARAMETER ClearCache Removes Python cache files (__pycache__, .pyc). .PARAMETER SkipVenv Skips Python virtual environment creation. .PARAMETER SkipDocker Skips Docker checks and cleanup. .PARAMETER Force Forces recreation of the Python virtual environment. .PARAMETER VerboseOutput Enables more detailed output (currently unused). .PARAMETER Dev Installs development dependencies from requirements-dev.txt if available. .PARAMETER Docker Uses Docker to build and run the MCP server instead of Python virtual environment. .EXAMPLE .\run-server.ps1 Prepares the environment and starts the Zen MCP server. .\run-server.ps1 -Follow Follows server logs in real time. .\run-server.ps1 -Config Shows configuration instructions for clients. .\run-server.ps1 -Dev Prepares the environment with development dependencies and starts the server. .\run-server.ps1 -Docker Builds and runs the server using Docker containers. .\run-server.ps1 -Docker -Follow Builds and runs the server using Docker containers and follows the logs. .\run-server.ps1 -Docker -Force Forces rebuilding of the Docker image and runs the server. .NOTES Project Author : BeehiveInnovations Script Author : GiGiDKR (https://github.com/GiGiDKR) Date : 07-05-2025 Version : See config.py (__version__) References : https://github.com/BeehiveInnovations/zen-mcp-server #> #Requires -Version 5.1 [CmdletBinding()] param( [switch]$Help, [switch]$Version, [switch]$Follow, [switch]$Config, [switch]$ClearCache, [switch]$SkipVenv, [switch]$SkipDocker, [switch]$Force, [switch]$VerboseOutput, [switch]$Dev, [switch]$Docker ) # ============================================================================ # Zen MCP Server Setup Script for Windows # # A Windows-compatible setup script that handles environment setup, # dependency installation, and configuration. # ============================================================================ # Set error action preference $ErrorActionPreference = "Stop" # ---------------------------------------------------------------------------- # Constants and Configuration # ---------------------------------------------------------------------------- $script:VENV_PATH = ".zen_venv" $script:DOCKER_CLEANED_FLAG = ".docker_cleaned" $script:DESKTOP_CONFIG_FLAG = ".desktop_configured" $script:LOG_DIR = "logs" $script:LOG_FILE = "mcp_server.log" # ---------------------------------------------------------------------------- # Utility Functions # ---------------------------------------------------------------------------- function Write-Success { param([string]$Message) Write-Host "✓ " -ForegroundColor Green -NoNewline Write-Host $Message } function Write-Error { param([string]$Message) Write-Host "✗ " -ForegroundColor Red -NoNewline Write-Host $Message } function Write-Warning { param([string]$Message) Write-Host "⚠ " -ForegroundColor Yellow -NoNewline Write-Host $Message } function Write-Info { param([string]$Message) Write-Host "ℹ " -ForegroundColor Cyan -NoNewline Write-Host $Message } function Write-Step { param([string]$Message) Write-Host "" Write-Host "=== $Message ===" -ForegroundColor Cyan } # Check if command exists function Test-Command { param([string]$Command) try { $null = Get-Command $Command -ErrorAction Stop return $true } catch { return $false } } # Alternative method to force remove locked directories function Remove-LockedDirectory { param([string]$Path) if (!(Test-Path $Path)) { return $true } try { # Try standard removal first Remove-Item -Recurse -Force $Path -ErrorAction Stop return $true } catch { Write-Warning "Standard removal failed, trying alternative methods..." # Method 1: Use takeown and icacls to force ownership try { Write-Info "Attempting to take ownership of locked files..." takeown /F "$Path" /R /D Y 2>$null | Out-Null icacls "$Path" /grant administrators:F /T 2>$null | Out-Null Remove-Item -Recurse -Force $Path -ErrorAction Stop return $true } catch { Write-Warning "Ownership method failed" } # Method 2: Rename and schedule for deletion on reboot try { $tempName = "$Path.delete_$(Get-Random)" Write-Info "Renaming to: $tempName (will be deleted on next reboot)" Rename-Item $Path $tempName -ErrorAction Stop # Schedule for deletion on reboot using movefile if (Get-Command "schtasks" -ErrorAction SilentlyContinue) { Write-Info "Scheduling for deletion on next reboot..." } Write-Warning "Environment renamed to $tempName and will be deleted on next reboot" return $true } catch { Write-Warning "Rename method failed" } # If all methods fail, return false return $false } } # Manage configuration file backups with maximum 3 files retention function Manage-ConfigBackups { param( [string]$ConfigFilePath, [int]$MaxBackups = 3 ) if (!(Test-Path $ConfigFilePath)) { Write-Warning "Configuration file not found: $ConfigFilePath" return $null } try { # Create new backup with timestamp $timestamp = Get-Date -Format 'yyyyMMdd_HHmmss' $backupPath = "$ConfigFilePath.backup_$timestamp" Copy-Item $ConfigFilePath $backupPath -ErrorAction Stop # Find all existing backups for this config file $configDir = Split-Path $ConfigFilePath -Parent $configFileName = Split-Path $ConfigFilePath -Leaf $backupPattern = "$configFileName.backup_*" $existingBackups = Get-ChildItem -Path $configDir -Filter $backupPattern -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending # Keep only the most recent MaxBackups files if ($existingBackups.Count -gt $MaxBackups) { $backupsToRemove = $existingBackups | Select-Object -Skip $MaxBackups foreach ($backup in $backupsToRemove) { try { Remove-Item $backup.FullName -Force -ErrorAction Stop Write-Info "Removed old backup: $($backup.Name)" } catch { Write-Warning "Could not remove old backup: $($backup.Name)" } } Write-Success "Backup retention: kept $MaxBackups most recent backups" } Write-Success "Backup created: $(Split-Path $backupPath -Leaf)" return $backupPath } catch { Write-Warning "Failed to create backup: $_" return $null } } # Get version from config.py function Get-Version { try { if (Test-Path "config.py") { $content = Get-Content "config.py" -ErrorAction Stop $versionLine = $content | Where-Object { $_ -match '^__version__ = ' } if ($versionLine) { return ($versionLine -replace '__version__ = "([^"]*)"', '$1') } } return "unknown" } catch { return "unknown" } } # Clear Python cache files function Clear-PythonCache { Write-Info "Clearing Python cache files..." try { # Remove .pyc files Get-ChildItem -Path . -Recurse -Filter "*.pyc" -ErrorAction SilentlyContinue | Remove-Item -Force # Remove __pycache__ directories Get-ChildItem -Path . -Recurse -Name "__pycache__" -Directory -ErrorAction SilentlyContinue | ForEach-Object { Remove-Item -Path $_ -Recurse -Force } Write-Success "Python cache cleared" } catch { Write-Warning "Could not clear all cache files: $_" } } # Get absolute path function Get-AbsolutePath { param([string]$Path) if (Test-Path $Path) { # Use Resolve-Path for full resolution return Resolve-Path $Path } else { # Use unresolved method return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) } } # Check Python version function Test-PythonVersion { param([string]$PythonCmd) try { $version = & $PythonCmd --version 2>&1 if ($version -match "Python (\d+)\.(\d+)") { $major = [int]$matches[1] $minor = [int]$matches[2] return ($major -gt 3) -or ($major -eq 3 -and $minor -ge 10) } return $false } catch { return $false } } # Find Python installation function Find-Python { $pythonCandidates = @("python", "python3", "py") foreach ($cmd in $pythonCandidates) { if (Test-Command $cmd) { if (Test-PythonVersion $cmd) { $version = & $cmd --version 2>&1 Write-Success "Found Python: $version" return $cmd } } } # Try Windows Python Launcher with specific versions $pythonVersions = @("3.12", "3.11", "3.10", "3.9") foreach ($version in $pythonVersions) { $cmd = "py -$version" try { $null = Invoke-Expression "$cmd --version" 2>$null Write-Success "Found Python via py launcher: $cmd" return $cmd } catch { continue } } Write-Error "Python 3.10+ not found. Please install Python from https://python.org" return $null } # Clean up old Docker artifacts function Cleanup-Docker { if (Test-Path $DOCKER_CLEANED_FLAG) { return } if (!(Test-Command "docker")) { return } try { $null = docker info 2>$null } catch { return } $foundArtifacts = $false # Define containers to remove $containers = @( "gemini-mcp-server", "gemini-mcp-redis", "zen-mcp-server", "zen-mcp-redis", "zen-mcp-log-monitor" ) # Remove containers foreach ($container in $containers) { try { $exists = docker ps -a --format "{{.Names}}" | Where-Object { $_ -eq $container } if ($exists) { if (!$foundArtifacts) { Write-Info "One-time Docker cleanup..." $foundArtifacts = $true } Write-Info " Removing container: $container" docker stop $container 2>$null | Out-Null docker rm $container 2>$null | Out-Null } } catch { # Ignore errors } } # Remove images $images = @("gemini-mcp-server:latest", "zen-mcp-server:latest") foreach ($image in $images) { try { $exists = docker images --format "{{.Repository}}:{{.Tag}}" | Where-Object { $_ -eq $image } if ($exists) { if (!$foundArtifacts) { Write-Info "One-time Docker cleanup..." $foundArtifacts = $true } Write-Info " Removing image: $image" docker rmi $image 2>$null | Out-Null } } catch { # Ignore errors } } # Remove volumes $volumes = @("redis_data", "mcp_logs") foreach ($volume in $volumes) { try { $exists = docker volume ls --format "{{.Name}}" | Where-Object { $_ -eq $volume } if ($exists) { if (!$foundArtifacts) { Write-Info "One-time Docker cleanup..." $foundArtifacts = $true } Write-Info " Removing volume: $volume" docker volume rm $volume 2>$null | Out-Null } } catch { # Ignore errors } } if ($foundArtifacts) { Write-Success "Docker cleanup complete" } New-Item -Path $DOCKER_CLEANED_FLAG -ItemType File -Force | Out-Null } # Validate API keys function Test-ApiKeys { Write-Step "Validating API Keys" if (!(Test-Path ".env")) { Write-Warning "No .env file found. API keys should be configured." return $false } $envContent = Get-Content ".env" $hasValidKey = $false $keyPatterns = @{ "GEMINI_API_KEY" = "AIza[0-9A-Za-z-_]{35}" "OPENAI_API_KEY" = "sk-[a-zA-Z0-9]{20}T3BlbkFJ[a-zA-Z0-9]{20}" "XAI_API_KEY" = "xai-[a-zA-Z0-9-_]+" "OPENROUTER_API_KEY" = "sk-or-[a-zA-Z0-9-_]+" } foreach ($line in $envContent) { if ($line -match '^([^#][^=]*?)=(.*)$') { $key = $matches[1].Trim() $value = $matches[2].Trim() -replace '^["'']|["'']$', '' if ($keyPatterns.ContainsKey($key) -and $value -ne "your_${key.ToLower()}_here" -and $value.Length -gt 10) { Write-Success "Found valid $key" $hasValidKey = $true } } } if (!$hasValidKey) { Write-Warning "No valid API keys found in .env file" Write-Info "Please edit .env file with your actual API keys" return $false } return $true } # Check if uv is available function Test-Uv { return Test-Command "uv" } # Setup environment using uv-first approach function Initialize-Environment { Write-Step "Setting up Python Environment" # Try uv first for faster package management if (Test-Uv) { Write-Info "Using uv for faster package management..." if (Test-Path $VENV_PATH) { if ($Force) { Write-Warning "Removing existing environment..." Remove-Item -Recurse -Force $VENV_PATH } else { Write-Success "Virtual environment already exists" $pythonPath = "$VENV_PATH\Scripts\python.exe" if (Test-Path $pythonPath) { return Get-AbsolutePath $pythonPath } } } try { Write-Info "Creating virtual environment with uv..." uv venv $VENV_PATH --python 3.12 if ($LASTEXITCODE -eq 0) { Write-Success "Environment created with uv" return Get-AbsolutePath "$VENV_PATH\Scripts\python.exe" } } catch { Write-Warning "uv failed, falling back to venv" } } # Fallback to standard venv $pythonCmd = Find-Python if (!$pythonCmd) { throw "Python 3.10+ not found" } if (Test-Path $VENV_PATH) { if ($Force) { Write-Warning "Removing existing environment..." try { # Stop any Python processes that might be using the venv Get-Process python* -ErrorAction SilentlyContinue | Where-Object { $_.Path -like "*$VENV_PATH*" } | Stop-Process -Force -ErrorAction SilentlyContinue # Wait a moment for processes to terminate Start-Sleep -Seconds 2 # Use the robust removal function if (Remove-LockedDirectory $VENV_PATH) { Write-Success "Existing environment removed" } else { throw "Unable to remove existing environment. Please restart your computer and try again." } } catch { Write-Error "Failed to remove existing environment: $_" Write-Host "" Write-Host "Try these solutions:" -ForegroundColor Yellow Write-Host "1. Close all terminals and VS Code instances" -ForegroundColor White Write-Host "2. Run: Get-Process python* | Stop-Process -Force" -ForegroundColor White Write-Host "3. Manually delete: $VENV_PATH" -ForegroundColor White Write-Host "4. Then run the script again" -ForegroundColor White exit 1 } } else { Write-Success "Virtual environment already exists" return Get-AbsolutePath "$VENV_PATH\Scripts\python.exe" } } Write-Info "Creating virtual environment with $pythonCmd..." if ($pythonCmd.StartsWith("py ")) { Invoke-Expression "$pythonCmd -m venv $VENV_PATH" } else { & $pythonCmd -m venv $VENV_PATH } if ($LASTEXITCODE -ne 0) { throw "Failed to create virtual environment" } Write-Success "Virtual environment created" return Get-AbsolutePath "$VENV_PATH\Scripts\python.exe" } # Setup virtual environment (legacy function for compatibility) function Initialize-VirtualEnvironment { Write-Step "Setting up Python Virtual Environment" if (!$SkipVenv -and (Test-Path $VENV_PATH)) { if ($Force) { Write-Warning "Removing existing virtual environment..." try { # Stop any Python processes that might be using the venv Get-Process python* -ErrorAction SilentlyContinue | Where-Object { $_.Path -like "*$VENV_PATH*" } | Stop-Process -Force -ErrorAction SilentlyContinue # Wait a moment for processes to terminate Start-Sleep -Seconds 2 # Use the robust removal function if (Remove-LockedDirectory $VENV_PATH) { Write-Success "Existing environment removed" } else { throw "Unable to remove existing environment. Please restart your computer and try again." } } catch { Write-Error "Failed to remove existing environment: $_" Write-Host "" Write-Host "Try these solutions:" -ForegroundColor Yellow Write-Host "1. Close all terminals and VS Code instances" -ForegroundColor White Write-Host "2. Run: Get-Process python* | Stop-Process -Force" -ForegroundColor White Write-Host "3. Manually delete: $VENV_PATH" -ForegroundColor White Write-Host "4. Then run the script again" -ForegroundColor White exit 1 } } else { Write-Success "Virtual environment already exists" return } } if ($SkipVenv) { Write-Warning "Skipping virtual environment setup" return } $pythonCmd = Find-Python if (!$pythonCmd) { Write-Error "Python 3.10+ not found. Please install Python from https://python.org" exit 1 } Write-Info "Using Python: $pythonCmd" Write-Info "Creating virtual environment..." try { if ($pythonCmd.StartsWith("py ")) { Invoke-Expression "$pythonCmd -m venv $VENV_PATH" } else { & $pythonCmd -m venv $VENV_PATH } if ($LASTEXITCODE -ne 0) { throw "Failed to create virtual environment" } Write-Success "Virtual environment created" } catch { Write-Error "Failed to create virtual environment: $_" exit 1 } } # Install dependencies function - Simplified uv-first approach function Install-Dependencies { param( [Parameter(Mandatory=$true)] [string]$PythonPath, [switch]$InstallDevDependencies = $false ) Write-Step "Installing Dependencies" # Build requirements files list $requirementsFiles = @("requirements.txt") if ($InstallDevDependencies) { if (Test-Path "requirements-dev.txt") { $requirementsFiles += "requirements-dev.txt" Write-Info "Including development dependencies from requirements-dev.txt" } else { Write-Warning "Development dependencies requested but requirements-dev.txt not found" } } # Try uv first for faster package management $useUv = Test-Uv if ($useUv) { Write-Info "Installing dependencies with uv (fast)..." try { foreach ($file in $requirementsFiles) { Write-Info "Installing from $file with uv..." uv pip install -r $file --python $PythonPath if ($LASTEXITCODE -ne 0) { throw "uv failed to install $file" } } Write-Success "Dependencies installed successfully with uv" return } catch { Write-Warning "uv installation failed: $_. Falling back to pip" $useUv = $false } } # Fallback to pip Write-Info "Installing dependencies with pip..." $pipCmd = Join-Path (Split-Path $PythonPath -Parent) "pip.exe" try { # Upgrade pip first & $pipCmd install --upgrade pip | Out-Null } catch { Write-Warning "Could not upgrade pip, continuing..." } try { foreach ($file in $requirementsFiles) { Write-Info "Installing from $file with pip..." & $pipCmd install -r $file if ($LASTEXITCODE -ne 0) { throw "pip failed to install $file" } } Write-Success "Dependencies installed successfully with pip" } catch { Write-Error "Failed to install dependencies with pip: $_" exit 1 } } # ---------------------------------------------------------------------------- # Docker Functions # ============================================================================ # Test Docker availability and requirements function Test-DockerRequirements { Write-Step "Checking Docker Requirements" if (!(Test-Command "docker")) { Write-Error "Docker not found. Please install Docker Desktop from https://docker.com" return $false } try { $null = docker version 2>$null Write-Success "Docker is installed and running" } catch { Write-Error "Docker is installed but not running. Please start Docker Desktop." return $false } if (!(Test-Command "docker-compose")) { Write-Warning "docker-compose not found. Trying docker compose..." try { $null = docker compose version 2>$null Write-Success "Docker Compose (v2) is available" return $true } catch { Write-Error "Docker Compose not found. Please install Docker Compose." return $false } } else { Write-Success "Docker Compose is available" return $true } } # Build Docker image function Build-DockerImage { param([switch]$Force = $false) Write-Step "Building Docker Image" # Check if image exists try { $imageExists = docker images --format "{{.Repository}}:{{.Tag}}" | Where-Object { $_ -eq "zen-mcp-server:latest" } if ($imageExists -and !$Force) { Write-Success "Docker image already exists. Use -Force to rebuild." return $true } } catch { # Continue if command fails } if ($Force -and $imageExists) { Write-Info "Forcing rebuild of Docker image..." try { docker rmi zen-mcp-server:latest 2>$null } catch { Write-Warning "Could not remove existing image, continuing..." } } Write-Info "Building Docker image from Dockerfile..." try { $buildArgs = @() if ($Dev) { # For development builds, we could add specific build args Write-Info "Building with development support..." } docker build -t zen-mcp-server:latest . if ($LASTEXITCODE -ne 0) { throw "Docker build failed" } Write-Success "Docker image built successfully" return $true } catch { Write-Error "Failed to build Docker image: $_" return $false } } # Prepare Docker environment file function Initialize-DockerEnvironment { Write-Step "Preparing Docker Environment" # Ensure .env file exists if (!(Test-Path ".env")) { Write-Warning "No .env file found. Creating default .env file..." $defaultEnv = @" # API Keys - Replace with your actual keys GEMINI_API_KEY=your_gemini_api_key_here GOOGLE_API_KEY=your_google_api_key_here OPENAI_API_KEY=your_openai_api_key_here ANTHROPIC_API_KEY=your_anthropic_api_key_here XAI_API_KEY=your_xai_api_key_here DIAL_API_KEY=your_dial_api_key_here DIAL_API_HOST=your_dial_api_host_here DIAL_API_VERSION=your_dial_api_version_here OPENROUTER_API_KEY=your_openrouter_api_key_here CUSTOM_API_URL=your_custom_api_url_here CUSTOM_API_KEY=your_custom_api_key_here CUSTOM_MODEL_NAME=your_custom_model_name_here # Server Configuration DEFAULT_MODEL=auto LOG_LEVEL=INFO LOG_MAX_SIZE=10MB LOG_BACKUP_COUNT=5 DEFAULT_THINKING_MODE_THINKDEEP=high # Optional Advanced Settings #DISABLED_TOOLS= #MAX_MCP_OUTPUT_TOKENS= #TZ=UTC "@ $defaultEnv | Out-File -FilePath ".env" -Encoding UTF8 Write-Success "Default .env file created" Write-Warning "Please edit .env file with your actual API keys" } else { Write-Success ".env file exists" } # Create logs directory for volume mount Initialize-Logging return $true } # Start Docker services function Start-DockerServices { param([switch]$Follow = $false) Write-Step "Starting Docker Services" # Check if docker-compose.yml exists if (!(Test-Path "docker-compose.yml")) { Write-Error "docker-compose.yml not found in current directory" return $false } try { # Stop any existing services Write-Info "Stopping any existing services..." if (Test-Command "docker-compose") { docker-compose down 2>$null } else { docker compose down 2>$null } # Start services Write-Info "Starting Zen MCP Server with Docker Compose..." if (Test-Command "docker-compose") { if ($Follow) { docker-compose up --build } else { docker-compose up -d --build } } else { if ($Follow) { docker compose up --build } else { docker compose up -d --build } } if ($LASTEXITCODE -ne 0) { throw "Failed to start Docker services" } if (!$Follow) { Write-Success "Docker services started successfully" Write-Info "Container name: zen-mcp-server" Write-Host "" Write-Host "To view logs: " -NoNewline Write-Host "docker logs -f zen-mcp-server" -ForegroundColor Yellow Write-Host "To stop: " -NoNewline Write-Host "docker-compose down" -ForegroundColor Yellow } return $true } catch { Write-Error "Failed to start Docker services: $_" return $false } } # Get Docker container status function Get-DockerStatus { try { $containerStatus = docker ps --filter "name=zen-mcp-server" --format "{{.Status}}" if ($containerStatus) { Write-Success "Container status: $containerStatus" return $true } else { Write-Warning "Container not running" return $false } } catch { Write-Warning "Could not get container status: $_" return $false } } # ============================================================================ # End Docker Functions # ============================================================================ # Setup logging directory function Initialize-Logging { Write-Step "Setting up Logging" if (!(Test-Path $LOG_DIR)) { New-Item -ItemType Directory -Path $LOG_DIR -Force | Out-Null Write-Success "Logs directory created" } else { Write-Success "Logs directory already exists" } } # Check Docker function Test-Docker { Write-Step "Checking Docker Setup" if ($SkipDocker) { Write-Warning "Skipping Docker checks" return } if (Test-Command "docker") { try { $null = docker version 2>$null Write-Success "Docker is installed and running" if (Test-Command "docker-compose") { Write-Success "Docker Compose is available" } else { Write-Warning "Docker Compose not found. Install Docker Desktop for Windows." } } catch { Write-Warning "Docker is installed but not running. Please start Docker Desktop." } } else { Write-Warning "Docker not found. Install Docker Desktop from https://docker.com" } } # ---------------------------------------------------------------------------- # MCP Client Configuration System # ---------------------------------------------------------------------------- # Centralized MCP client definitions $script:McpClientDefinitions = @( @{ Name = "Claude Desktop" DetectionPath = "$env:APPDATA\Claude\claude_desktop_config.json" DetectionType = "Path" ConfigPath = "$env:APPDATA\Claude\claude_desktop_config.json" ConfigJsonPath = "mcpServers.zen" NeedsConfigDir = $true }, @{ Name = "VSCode" DetectionCommand = "code" DetectionType = "Command" ConfigPath = "$env:APPDATA\Code\User\settings.json" ConfigJsonPath = "mcp.servers.zen" IsVSCode = $true }, @{ Name = "VSCode Insiders" DetectionCommand = "code-insiders" DetectionType = "Command" ConfigPath = "$env:APPDATA\Code - Insiders\User\mcp.json" ConfigJsonPath = "servers.zen" IsVSCodeInsiders = $true }, @{ Name = "Cursor" DetectionCommand = "cursor" DetectionType = "Command" ConfigPath = "$env:USERPROFILE\.cursor\mcp.json" ConfigJsonPath = "mcpServers.zen" }, @{ Name = "Windsurf" DetectionPath = "$env:USERPROFILE\.codeium\windsurf" DetectionType = "Path" ConfigPath = "$env:USERPROFILE\.codeium\windsurf\mcp_config.json" ConfigJsonPath = "mcpServers.zen" }, @{ Name = "Trae" DetectionPath = "$env:APPDATA\Trae" DetectionType = "Path" ConfigPath = "$env:APPDATA\Trae\User\mcp.json" ConfigJsonPath = "mcpServers.zen" } ) # Docker MCP configuration template (legacy, kept for backward compatibility) $script:DockerMcpConfig = @{ command = "docker" args = @("exec", "-i", "zen-mcp-server", "python", "server.py") type = "stdio" } # Generate Docker MCP configuration using docker run (recommended for all clients) function Get-DockerMcpConfigRun { param([string]$ServerPath) $scriptDir = Split-Path $ServerPath -Parent $envFile = Join-Path $scriptDir ".env" return @{ command = "docker" args = @("run", "--rm", "-i", "--env-file", $envFile, "zen-mcp-server:latest", "python", "server.py") type = "stdio" } } # Generate Python MCP configuration function Get-PythonMcpConfig { param([string]$PythonPath, [string]$ServerPath) return @{ command = $PythonPath args = @($ServerPath) type = "stdio" } } # Check if client uses mcp.json format with servers structure function Test-McpJsonFormat { param([hashtable]$Client) $configFileName = Split-Path $Client.ConfigPath -Leaf return $configFileName -eq "mcp.json" } # Check if client uses the new VS Code Insiders format (servers instead of mcpServers) function Test-VSCodeInsidersFormat { param([hashtable]$Client) return $Client.IsVSCodeInsiders -eq $true -and $Client.ConfigJsonPath -eq "servers.zen" } # Analyze existing MCP configuration to determine type (Python or Docker) function Get-ExistingMcpConfigType { param( [Parameter(Mandatory=$true)] [hashtable]$Client, [Parameter(Mandatory=$true)] [string]$ConfigPath ) if (!(Test-Path $ConfigPath)) { return @{ Exists = $false Type = "None" Details = "No configuration found" } } try { $content = Get-Content $ConfigPath -Raw | ConvertFrom-Json -ErrorAction SilentlyContinue if (!$content) { return @{ Exists = $false Type = "None" Details = "Invalid JSON configuration" } } # Navigate to zen configuration $pathParts = $Client.ConfigJsonPath.Split('.') $zenKey = $pathParts[-1] $parentPath = $pathParts[0..($pathParts.Length - 2)] $targetObject = $content foreach($key in $parentPath) { if (!$targetObject.PSObject.Properties[$key]) { return @{ Exists = $false Type = "None" Details = "Configuration structure not found" } } $targetObject = $targetObject.$key } if (!$targetObject.PSObject.Properties[$zenKey]) { return @{ Exists = $false Type = "None" Details = "Zen configuration not found" } } $zenConfig = $targetObject.$zenKey # Analyze configuration type if ($zenConfig.command -eq "docker") { $dockerType = "Unknown" $details = "Docker configuration" if ($zenConfig.args -and $zenConfig.args.Count -gt 0) { if ($zenConfig.args[0] -eq "run") { $dockerType = "Docker Run" $details = "Docker run (dedicated container)" } elseif ($zenConfig.args[0] -eq "exec") { $dockerType = "Docker Exec" $details = "Docker exec (existing container)" } else { $details = "Docker ($($zenConfig.args[0]))" } } return @{ Exists = $true Type = "Docker" SubType = $dockerType Details = $details Command = $zenConfig.command Args = $zenConfig.args } } elseif ($zenConfig.command -and $zenConfig.command.EndsWith("python.exe")) { $pythonType = "Python" $details = "Python virtual environment" if ($zenConfig.command.Contains(".zen_venv")) { $details = "Python (zen virtual environment)" } elseif ($zenConfig.command.Contains("venv")) { $details = "Python (virtual environment)" } else { $details = "Python (system installation)" } return @{ Exists = $true Type = "Python" SubType = $pythonType Details = $details Command = $zenConfig.command Args = $zenConfig.args } } else { return @{ Exists = $true Type = "Unknown" Details = "Unknown configuration type: $($zenConfig.command)" Command = $zenConfig.command Args = $zenConfig.args } } } catch { return @{ Exists = $false Type = "Error" Details = "Error reading configuration: $_" } } } # Generic MCP client configuration function function Configure-McpClient { param( [Parameter(Mandatory=$true)] [hashtable]$Client, [Parameter(Mandatory=$true)] [bool]$UseDocker, [string]$PythonPath = "", [string]$ServerPath = "" ) Write-Step "Checking $($Client.Name) Integration" # Client detection $detected = $false if ($Client.DetectionType -eq "Command" -and (Test-Command $Client.DetectionCommand)) { $detected = $true } elseif ($Client.DetectionType -eq "Path" -and (Test-Path ($Client.DetectionPath -as [string]))) { $detected = $true } if (!$detected) { Write-Info "$($Client.Name) not detected - skipping integration" return } Write-Info "Found $($Client.Name)" # Handle VSCode special logic for profiles $configPath = $Client.ConfigPath if ($Client.IsVSCode) { $userPath = Split-Path $configPath -Parent if (!(Test-Path $userPath)) { Write-Warning "$($Client.Name) user directory not found. Skipping." return } # Find most recent settings.json (default or profile) $settingsFiles = @() $defaultSettings = $configPath if (Test-Path $defaultSettings) { $settingsFiles += @{ Path = $defaultSettings LastModified = (Get-Item $defaultSettings).LastWriteTime } } $profilesPath = Join-Path $userPath "profiles" if (Test-Path $profilesPath) { Get-ChildItem $profilesPath -Directory | ForEach-Object { $profileSettings = Join-Path $_.FullName "settings.json" if (Test-Path $profileSettings) { $settingsFiles += @{ Path = $profileSettings LastModified = (Get-Item $profileSettings).LastWriteTime } } } } if ($settingsFiles.Count -gt 0) { $configPath = ($settingsFiles | Sort-Object LastModified -Descending | Select-Object -First 1).Path } } # Handle VSCode Insiders special logic for profiles (uses mcp.json) if ($Client.IsVSCodeInsiders) { $userPath = Split-Path $configPath -Parent if (!(Test-Path $userPath)) { Write-Warning "$($Client.Name) user directory not found. Skipping." return } # Find most recent mcp.json (default or profile) $mcpFiles = @() $defaultMcp = $configPath if (Test-Path $defaultMcp) { $mcpFiles += @{ Path = $defaultMcp LastModified = (Get-Item $defaultMcp).LastWriteTime } } $profilesPath = Join-Path $userPath "profiles" if (Test-Path $profilesPath) { Get-ChildItem $profilesPath -Directory | ForEach-Object { $profileMcp = Join-Path $_.FullName "mcp.json" if (Test-Path $profileMcp) { $mcpFiles += @{ Path = $profileMcp LastModified = (Get-Item $profileMcp).LastWriteTime } } } } if ($mcpFiles.Count -gt 0) { $configPath = ($mcpFiles | Sort-Object LastModified -Descending | Select-Object -First 1).Path } } # Check if already configured and analyze existing configuration $existingConfig = Get-ExistingMcpConfigType -Client $Client -ConfigPath $configPath $newConfigType = if ($UseDocker) { "Docker" } else { "Python" } if ($existingConfig.Exists) { Write-Info "Found existing Zen MCP configuration in $($Client.Name)" Write-Info " Current: $($existingConfig.Details)" Write-Info " New: $newConfigType configuration" if ($existingConfig.Type -eq $newConfigType) { Write-Warning "Same configuration type ($($existingConfig.Type)) already exists" $response = Read-Host "`nOverwrite existing $($existingConfig.Type) configuration? (y/N)" } else { Write-Warning "Different configuration type detected" Write-Info " Replacing: $($existingConfig.Type) → $newConfigType" $response = Read-Host "`nReplace $($existingConfig.Type) with $newConfigType configuration? (y/N)" } if ($response -ne 'y' -and $response -ne 'Y') { Write-Info "Keeping existing configuration in $($Client.Name)" return } Write-Info "Proceeding with configuration update..." } else { # User confirmation for new installation $response = Read-Host "`nConfigure Zen MCP for $($Client.Name) (mode: $newConfigType)? (y/N)" if ($response -ne 'y' -and $response -ne 'Y') { Write-Info "Skipping $($Client.Name) integration" return } } try { # Create config directory if needed $configDir = Split-Path $configPath -Parent if (!(Test-Path $configDir)) { New-Item -ItemType Directory -Path $configDir -Force | Out-Null } # Backup existing config if (Test-Path $configPath) { Manage-ConfigBackups -ConfigFilePath $configPath } # Read or create config $config = New-Object PSObject $usesMcpJsonFormat = Test-McpJsonFormat -Client $Client $usesVSCodeInsidersFormat = Test-VSCodeInsidersFormat -Client $Client if (Test-Path $configPath) { $fileContent = Get-Content $configPath -Raw if ($fileContent.Trim()) { $config = $fileContent | ConvertFrom-Json -ErrorAction SilentlyContinue } if ($null -eq $config) { $config = New-Object PSObject } } # Initialize structure for mcp.json format files if they don't exist or are empty if ($usesMcpJsonFormat) { if ($usesVSCodeInsidersFormat) { # For VS Code Insiders format: {"servers": {...}} if (!$config.PSObject.Properties["servers"]) { $config | Add-Member -MemberType NoteProperty -Name "servers" -Value (New-Object PSObject) } } else { # For other clients format: {"mcpServers": {...}} if (!$config.PSObject.Properties["mcpServers"]) { $config | Add-Member -MemberType NoteProperty -Name "mcpServers" -Value (New-Object PSObject) } } } # Initialize MCP structure for VS Code settings.json if it doesn't exist if ($Client.IsVSCode -and $Client.ConfigJsonPath.StartsWith("mcp.")) { if (!$config.PSObject.Properties["mcp"]) { $config | Add-Member -MemberType NoteProperty -Name "mcp" -Value (New-Object PSObject) } if (!$config.mcp.PSObject.Properties["servers"]) { $config.mcp | Add-Member -MemberType NoteProperty -Name "servers" -Value (New-Object PSObject) } } # Generate server config $serverConfig = if ($UseDocker) { # Use docker run for all clients (more reliable than docker exec) Get-DockerMcpConfigRun $ServerPath } else { Get-PythonMcpConfig $PythonPath $ServerPath } # Navigate and set configuration $pathParts = $Client.ConfigJsonPath.Split('.') $zenKey = $pathParts[-1] $parentPath = $pathParts[0..($pathParts.Length - 2)] $targetObject = $config foreach($key in $parentPath) { if (!$targetObject.PSObject.Properties[$key]) { $targetObject | Add-Member -MemberType NoteProperty -Name $key -Value (New-Object PSObject) } $targetObject = $targetObject.$key } $targetObject | Add-Member -MemberType NoteProperty -Name $zenKey -Value $serverConfig -Force # Write config $config | ConvertTo-Json -Depth 10 | Out-File $configPath -Encoding UTF8 Write-Success "Successfully configured $($Client.Name)" Write-Host " Config: $configPath" -ForegroundColor Gray Write-Host " Restart $($Client.Name) to use the new MCP server" -ForegroundColor Gray } catch { Write-Error "Failed to update $($Client.Name) configuration: $_" } } # Main MCP client configuration orchestrator function Invoke-McpClientConfiguration { param( [Parameter(Mandatory=$true)] [bool]$UseDocker, [string]$PythonPath = "", [string]$ServerPath = "" ) Write-Step "Checking Client Integrations" # Configure GUI clients foreach ($client in $script:McpClientDefinitions) { Configure-McpClient -Client $client -UseDocker $UseDocker -PythonPath $PythonPath -ServerPath $ServerPath } # Handle CLI tools separately (they don't follow JSON config pattern) if (!$UseDocker) { Test-ClaudeCliIntegration $PythonPath $ServerPath Test-GeminiCliIntegration (Split-Path $ServerPath -Parent) } } # Keep existing CLI integration functions function Test-ClaudeCliIntegration { param([string]$PythonPath, [string]$ServerPath) if (!(Test-Command "claude")) { return } Write-Info "Claude CLI detected - checking configuration..." try { $claudeConfig = claude config list 2>$null if ($claudeConfig -match "zen") { Write-Success "Claude CLI already configured for zen server" } else { Write-Info "To add zen server to Claude CLI, run:" Write-Host " claude config add-server zen $PythonPath $ServerPath" -ForegroundColor Cyan } } catch { Write-Info "To configure Claude CLI manually, run:" Write-Host " claude config add-server zen $PythonPath $ServerPath" -ForegroundColor Cyan } } function Test-GeminiCliIntegration { param([string]$ScriptDir) $zenWrapper = Join-Path $ScriptDir "zen-mcp-server.cmd" # Check if Gemini settings file exists (Windows path) $geminiConfig = "$env:USERPROFILE\.gemini\settings.json" if (!(Test-Path $geminiConfig)) { return } # Check if zen is already configured $configContent = Get-Content $geminiConfig -Raw -ErrorAction SilentlyContinue if ($configContent -and $configContent -match '"zen"') { return } # Ask user if they want to add Zen to Gemini CLI Write-Host "" $response = Read-Host "Configure Zen for Gemini CLI? (y/N)" if ($response -ne 'y' -and $response -ne 'Y') { Write-Info "Skipping Gemini CLI integration" return } # Ensure wrapper script exists if (!(Test-Path $zenWrapper)) { Write-Info "Creating wrapper script for Gemini CLI..." @" @echo off cd /d "%~dp0" if exist ".zen_venv\Scripts\python.exe" ( .zen_venv\Scripts\python.exe server.py %* ) else ( python server.py %* ) "@ | Out-File -FilePath $zenWrapper -Encoding ASCII Write-Success "Created zen-mcp-server.cmd wrapper script" } # Update Gemini settings Write-Info "Updating Gemini CLI configuration..." try { # Create backup with retention management $backupPath = Manage-ConfigBackups $geminiConfig # Read existing config or create new one $config = @{} if (Test-Path $geminiConfig) { $config = Get-Content $geminiConfig -Raw | ConvertFrom-Json } # Ensure mcpServers exists if (!$config.mcpServers) { $config | Add-Member -MemberType NoteProperty -Name "mcpServers" -Value @{} -Force } # Add zen server $zenConfig = @{ command = $zenWrapper } $config.mcpServers | Add-Member -MemberType NoteProperty -Name "zen" -Value $zenConfig -Force # Write updated config $config | ConvertTo-Json -Depth 10 | Out-File $geminiConfig -Encoding UTF8 Write-Success "Successfully configured Gemini CLI" Write-Host " Config: $geminiConfig" -ForegroundColor Gray Write-Host " Restart Gemini CLI to use Zen MCP Server" -ForegroundColor Gray } catch { Write-Error "Failed to update Gemini CLI config: $_" Write-Host "" Write-Host "Manual config location: $geminiConfig" Write-Host "Add this configuration:" Write-Host @" { "mcpServers": { "zen": { "command": "$zenWrapper" } } } "@ -ForegroundColor Yellow } } # ---------------------------------------------------------------------------- # End MCP Client Configuration System # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- # User Interface Functions # ---------------------------------------------------------------------------- # Show script help function Show-Help { Write-Host @" Zen MCP Server - Setup and Launch Script USAGE: .\run-server.ps1 [OPTIONS] OPTIONS: -Help Show this help message -Version Show version information -Follow Follow server logs in real time -Config Show configuration instructions for MCP clients -ClearCache Clear Python cache files and exit -Force Force recreation of Python virtual environment -Dev Install development dependencies from requirements-dev.txt -Docker Use Docker instead of Python virtual environment -SkipVenv Skip Python virtual environment creation -SkipDocker Skip Docker checks and cleanup EXAMPLES: .\run-server.ps1 # Normal startup .\run-server.ps1 -Follow # Start and follow logs .\run-server.ps1 -Config # Show configuration help .\run-server.ps1 -Dev # Include development dependencies .\run-server.ps1 -Docker # Use Docker deployment .\run-server.ps1 -Docker -Follow # Docker with log following For more information, visit: https://github.com/BeehiveInnovations/zen-mcp-server "@ -ForegroundColor White } # Show version information function Show-Version { $version = Get-Version Write-Host "Zen MCP Server version: $version" -ForegroundColor Green Write-Host "PowerShell Setup Script for Windows" -ForegroundColor Cyan Write-Host "Author: GiGiDKR (https://github.com/GiGiDKR)" -ForegroundColor Gray Write-Host "Project: BeehiveInnovations/zen-mcp-server" -ForegroundColor Gray } # Show configuration instructions function Show-ConfigInstructions { param( [string]$PythonPath = "", [string]$ServerPath = "", [switch]$UseDocker = $false ) Write-Step "Configuration Instructions" if ($UseDocker) { Write-Host "Docker Configuration:" -ForegroundColor Yellow Write-Host "The MCP clients have been configured to use Docker containers." -ForegroundColor White Write-Host "Make sure the Docker container is running with: docker-compose up -d" -ForegroundColor Cyan Write-Host "" } else { Write-Host "Python Virtual Environment Configuration:" -ForegroundColor Yellow Write-Host "Python Path: $PythonPath" -ForegroundColor Cyan Write-Host "Server Path: $ServerPath" -ForegroundColor Cyan Write-Host "" } Write-Host "Supported MCP Clients:" -ForegroundColor Green Write-Host "✓ Claude Desktop" -ForegroundColor White Write-Host "✓ Claude CLI" -ForegroundColor White Write-Host "✓ VSCode (with MCP extension)" -ForegroundColor White Write-Host "✓ VSCode Insiders" -ForegroundColor White Write-Host "✓ Cursor" -ForegroundColor White Write-Host "✓ Windsurf" -ForegroundColor White Write-Host "✓ Trae" -ForegroundColor White Write-Host "✓ Gemini CLI" -ForegroundColor White Write-Host "" Write-Host "The script automatically detects and configures compatible clients." -ForegroundColor Gray Write-Host "Restart your MCP clients after configuration to use the Zen MCP Server." -ForegroundColor Yellow } # Show setup instructions function Show-SetupInstructions { param( [string]$PythonPath = "", [string]$ServerPath = "", [switch]$UseDocker = $false ) Write-Step "Setup Complete" if ($UseDocker) { Write-Success "Zen MCP Server is configured for Docker deployment" Write-Host "Docker command: docker exec -i zen-mcp-server python server.py" -ForegroundColor Cyan } else { Write-Success "Zen MCP Server is configured for Python virtual environment" Write-Host "Python: $PythonPath" -ForegroundColor Cyan Write-Host "Server: $ServerPath" -ForegroundColor Cyan } Write-Host "" Write-Host "MCP clients will automatically connect to the server." -ForegroundColor Green Write-Host "For manual configuration, use the paths shown above." -ForegroundColor Gray } # Start the server function Start-Server { Write-Step "Starting Zen MCP Server" $pythonPath = "$VENV_PATH\Scripts\python.exe" if (!(Test-Path $pythonPath)) { Write-Error "Python virtual environment not found. Please run setup first." return } $serverPath = "server.py" if (!(Test-Path $serverPath)) { Write-Error "Server script not found: $serverPath" return } try { Write-Info "Launching server..." & $pythonPath $serverPath } catch { Write-Error "Failed to start server: $_" } } # Follow server logs function Follow-Logs { Write-Step "Following Server Logs" $logPath = Join-Path $LOG_DIR $LOG_FILE if (!(Test-Path $logPath)) { Write-Warning "Log file not found: $logPath" Write-Info "Starting server to generate logs..." Start-Server return } try { Write-Info "Following logs at: $logPath" Write-Host "Press Ctrl+C to stop following logs" Write-Host "" Get-Content $logPath -Wait } catch { Write-Error "Failed to follow logs: $_" } } # ---------------------------------------------------------------------------- # Environment File Management # ---------------------------------------------------------------------------- # Initialize .env file if it doesn't exist function Initialize-EnvFile { Write-Step "Setting up Environment File" if (!(Test-Path ".env")) { Write-Info "Creating default .env file..." @" # API Keys - Replace with your actual keys GEMINI_API_KEY=your_gemini_api_key_here GOOGLE_API_KEY=your_google_api_key_here OPENAI_API_KEY=your_openai_api_key_here ANTHROPIC_API_KEY=your_anthropic_api_key_here XAI_API_KEY=your_xai_api_key_here DIAL_API_KEY=your_dial_api_key_here DIAL_API_HOST=your_dial_api_host_here DIAL_API_VERSION=your_dial_api_version_here OPENROUTER_API_KEY=your_openrouter_api_key_here CUSTOM_API_URL=your_custom_api_url_here CUSTOM_API_KEY=your_custom_api_key_here CUSTOM_MODEL_NAME=your_custom_model_name_here # Server Configuration DEFAULT_MODEL=auto LOG_LEVEL=INFO LOG_MAX_SIZE=10MB LOG_BACKUP_COUNT=5 DEFAULT_THINKING_MODE_THINKDEEP=high # Optional Advanced Settings #DISABLED_TOOLS= #MAX_MCP_OUTPUT_TOKENS= #TZ=UTC "@ | Out-File -FilePath ".env" -Encoding UTF8 Write-Success "Default .env file created" Write-Warning "Please edit .env file with your actual API keys" } else { Write-Success ".env file already exists" } } # Import environment variables from .env file function Import-EnvFile { if (!(Test-Path ".env")) { Write-Warning "No .env file found" return } try { $envContent = Get-Content ".env" -ErrorAction Stop foreach ($line in $envContent) { if ($line -match '^([^#][^=]*?)=(.*)$') { $key = $matches[1].Trim() $value = $matches[2].Trim() -replace '^["'']|["'']$', '' # Set environment variable for the current session [Environment]::SetEnvironmentVariable($key, $value, "Process") } } Write-Success "Environment variables loaded from .env file" } catch { Write-Warning "Could not load .env file: $_" } } # ---------------------------------------------------------------------------- # Workflow Functions # ---------------------------------------------------------------------------- # Docker deployment workflow function Invoke-DockerWorkflow { Write-Step "Starting Docker Workflow" Write-Host "Zen MCP Server" -ForegroundColor Green Write-Host "=================" -ForegroundColor Cyan $version = Get-Version Write-Host "Version: $version" Write-Host "Mode: Docker Container" -ForegroundColor Yellow Write-Host "" # Docker setup and validation if (!(Test-DockerRequirements)) { exit 1 } if (!(Initialize-DockerEnvironment)) { exit 1 } Import-EnvFile Test-ApiKeys if (!(Build-DockerImage -Force:$Force)) { exit 1 } # Configure MCP clients for Docker Invoke-McpClientConfiguration -UseDocker $true Show-SetupInstructions -UseDocker # Start Docker services Write-Step "Starting Zen MCP Server" if ($Follow) { Write-Info "Starting server and following logs..." Start-DockerServices -Follow exit 0 } if (!(Start-DockerServices)) { exit 1 } Write-Host "" Write-Success "Zen MCP Server is running in Docker!" Write-Host "" Write-Host "Next steps:" -ForegroundColor Cyan Write-Host "1. Restart your MCP clients (Claude Desktop, etc.)" -ForegroundColor White Write-Host "2. The server is now ready to use" -ForegroundColor White Write-Host "" Write-Host "Useful commands:" -ForegroundColor Cyan Write-Host " View logs: " -NoNewline -ForegroundColor White Write-Host "docker logs -f zen-mcp-server" -ForegroundColor Yellow Write-Host " Stop server: " -NoNewline -ForegroundColor White Write-Host "docker-compose down" -ForegroundColor Yellow Write-Host " Restart server: " -NoNewline -ForegroundColor White Write-Host "docker-compose restart" -ForegroundColor Yellow } # Python virtual environment deployment workflow function Invoke-PythonWorkflow { Write-Step "Starting Python Virtual Environment Workflow" Write-Host "Zen MCP Server" -ForegroundColor Green Write-Host "=================" -ForegroundColor Cyan $version = Get-Version Write-Host "Version: $version" Write-Host "" if (!(Test-Path $VENV_PATH)) { Write-Info "Setting up Python environment for first time..." } # Python environment setup Cleanup-Docker Clear-PythonCache Initialize-EnvFile Import-EnvFile Test-ApiKeys try { $pythonPath = Initialize-Environment } catch { Write-Error "Failed to setup Python environment: $_" exit 1 } try { Install-Dependencies $pythonPath -InstallDevDependencies:$Dev } catch { Write-Error "Failed to install dependencies: $_" exit 1 } $serverPath = Get-AbsolutePath "server.py" # Configure MCP clients for Python Invoke-McpClientConfiguration -UseDocker $false -PythonPath $pythonPath -ServerPath $serverPath Show-SetupInstructions $pythonPath $serverPath Initialize-Logging Write-Host "" Write-Host "Logs will be written to: $(Get-AbsolutePath $LOG_DIR)\$LOG_FILE" Write-Host "" if ($Follow) { Follow-Logs } else { Write-Host "To follow logs: .\run-server.ps1 -Follow" -ForegroundColor Yellow Write-Host "To show config: .\run-server.ps1 -Config" -ForegroundColor Yellow Write-Host "To update: git pull, then run .\run-server.ps1 again" -ForegroundColor Yellow Write-Host "" Write-Host "Happy coding! 🎉" -ForegroundColor Green $response = Read-Host "`nStart the server now? (y/N)" if ($response -eq 'y' -or $response -eq 'Y') { Start-Server } } } # ---------------------------------------------------------------------------- # End Workflow Functions # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- # Main Execution # ---------------------------------------------------------------------------- # Main execution function function Start-MainProcess { # Parse command line arguments if ($Help) { Show-Help exit 0 } if ($Version) { Show-Version exit 0 } if ($ClearCache) { Clear-PythonCache Write-Success "Cache cleared successfully" Write-Host "" Write-Host "You can now run '.\run-server.ps1' normally" exit 0 } if ($Config) { # Setup minimal environment to get paths for config display Write-Info "Setting up environment for configuration display..." Write-Host "" try { if ($Docker) { # Docker configuration mode if (!(Test-DockerRequirements)) { exit 1 } Initialize-DockerEnvironment Show-ConfigInstructions "" "" -UseDocker } else { # Python virtual environment configuration mode $pythonPath = Initialize-Environment $serverPath = Get-AbsolutePath "server.py" Show-ConfigInstructions $pythonPath $serverPath } } catch { Write-Error "Failed to setup environment for configuration: $_" exit 1 } exit 0 } # ============================================================================ # Docker Workflow # ============================================================================ if ($Docker) { Invoke-DockerWorkflow exit 0 } # ============================================================================ # Python Virtual Environment Workflow (Default) # ============================================================================ Invoke-PythonWorkflow exit 0 } # ============================================================================ # Main Script Execution # ============================================================================ # Execute main process Start-MainProcess

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/BeehiveInnovations/gemini-mcp-server'

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