-
Notifications
You must be signed in to change notification settings - Fork 28
Open
Description
i have created and make steps easy to Dremio MCP Server Setup Script for Windows and Claude Desktop
#!/usr/bin/env python3
"""
Dremio MCP Server Setup Script for Windows
This script automates the setup of Dremio MCP Server on Windows systems.
It handles Python/pip checks, dynamic path resolution, PAT generation,
repository cloning, configuration, and Claude config management.
Features:
- Works with any Python installation (Windows Store, standard, conda, etc.)
- Dynamically finds executables regardless of installation method
- Handles all dependency installation automatically
- Works across different users without modification
"""
import os
import sys
import subprocess
import json
import platform
import shutil
from pathlib import Path
from urllib.parse import urlparse
import ctypes
import winreg
import tempfile
import traceback
# Global variable to store the uv executable path
UV_EXECUTABLE = None
def is_admin():
"""Check if the script is running with administrator privileges."""
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
def find_python_scripts_dir():
"""Find the Scripts directory for the current Python installation."""
possible_dirs = [
# Standard installation
Path(sys.executable).parent / "Scripts",
# Virtual environment
Path(sys.prefix) / "Scripts",
# Windows Store Python
Path(sys.executable).parent.parent / "Scripts",
# User installation
Path.home() / ".local" / "bin",
# Alternative user installation
Path(os.environ.get('APPDATA', '')) / "Python" / f"Python{sys.version_info.major}{sys.version_info.minor}" / "Scripts",
]
# For Windows Store Python, check LocalCache paths
if 'WindowsApps' in sys.executable:
# Extract the package name from the executable path
parts = Path(sys.executable).parts
for i, part in enumerate(parts):
if 'PythonSoftwareFoundation.Python' in part:
package_name = part
local_packages = Path(os.environ.get('LOCALAPPDATA', '')) / "Packages" / package_name / "LocalCache" / "local-packages"
if local_packages.exists():
for subdir in local_packages.iterdir():
if subdir.is_dir() and subdir.name.startswith('Python'):
scripts_dir = subdir / "Scripts"
if scripts_dir.exists():
possible_dirs.insert(0, scripts_dir)
# Return the first existing directory
for dir_path in possible_dirs:
if dir_path.exists():
return dir_path
# If none found, return the most likely one
return Path(sys.executable).parent / "Scripts"
def add_to_path_temporarily(directory):
"""Add a directory to PATH for the current session."""
if str(directory) not in os.environ.get('PATH', ''):
os.environ['PATH'] = f"{directory};{os.environ.get('PATH', '')}"
print(f"✅ Added {directory} to PATH for this session")
def check_python_installation():
"""Check if Python is properly installed and accessible."""
print("\n=== Checking Python Installation ===")
# Check current Python version
python_version = sys.version_info
print(f"Current Python version: {python_version.major}.{python_version.minor}.{python_version.micro}")
print(f"Python executable: {sys.executable}")
if python_version < (3, 7):
print("❌ Python 3.7 or higher is required")
print("Please download and install Python from: https://www.python.org/downloads/")
return False
print("✅ Python version is compatible")
# Find and add Scripts directory to PATH
scripts_dir = find_python_scripts_dir()
print(f"Python Scripts directory: {scripts_dir}")
add_to_path_temporarily(scripts_dir)
return True
def check_pip_installation():
"""Check if pip is installed and working."""
print("\n=== Checking pip Installation ===")
try:
# Check pip version
result = subprocess.run([sys.executable, "-m", "pip", "--version"],
capture_output=True, text=True)
if result.returncode == 0:
print(f"✅ pip is installed: {result.stdout.strip()}")
# Check if pip is up to date
print("Checking for pip updates...")
update_result = subprocess.run(
[sys.executable, "-m", "pip", "install", "--upgrade", "pip"],
capture_output=True, text=True
)
if "Successfully installed" in update_result.stdout:
print("✅ pip has been updated to the latest version")
else:
print("✅ pip is already up to date")
return True
else:
print("❌ pip is not installed")
return install_pip()
except Exception as e:
print(f"❌ Error checking pip: {e}")
return install_pip()
def install_pip():
"""Install pip if it's not available."""
print("\nAttempting to install pip...")
try:
# Try ensurepip first
print("Trying ensurepip module...")
result = subprocess.run([sys.executable, "-m", "ensurepip", "--default-pip"],
capture_output=True, text=True)
if result.returncode == 0:
print("✅ pip installed successfully using ensurepip")
return True
except:
pass
# If ensurepip fails, try downloading get-pip.py
print("Downloading get-pip.py...")
try:
import urllib.request
get_pip_url = "https://bootstrap.pypa.io/get-pip.py"
get_pip_path = Path(tempfile.gettempdir()) / "get-pip.py"
urllib.request.urlretrieve(get_pip_url, get_pip_path)
print("✅ Downloaded get-pip.py")
# Run get-pip.py
result = subprocess.run([sys.executable, str(get_pip_path)],
capture_output=True, text=True)
if result.returncode == 0:
print("✅ pip installed successfully")
# Clean up
get_pip_path.unlink()
return True
else:
print(f"❌ Failed to install pip: {result.stderr}")
return False
except Exception as e:
print(f"❌ Error installing pip: {e}")
print("\nPlease install pip manually:")
print("1. Download https://bootstrap.pypa.io/get-pip.py")
print("2. Run: python get-pip.py")
return False
def ensure_dependencies():
"""Ensure all required dependencies are installed."""
required_packages = ['requests']
missing_packages = []
for package in required_packages:
try:
__import__(package)
except ImportError:
missing_packages.append(package)
if missing_packages:
print(f"\nInstalling required dependencies: {', '.join(missing_packages)}...")
for package in missing_packages:
try:
subprocess.check_call([sys.executable, "-m", "pip", "install", "--user", package])
print(f"✅ {package} installed successfully")
except subprocess.CalledProcessError:
print(f"❌ Failed to install {package}")
print(f"Please install manually with: pip install {package}")
return False
# Refresh the module path
import site
site.main()
# Verify installation
for package in missing_packages:
try:
__import__(package)
except ImportError:
print(f"❌ {package} is still not available after installation")
return False
return True
def find_executable(name, additional_paths=None):
"""Find an executable in PATH or common locations."""
# First check if it's in PATH
exe_path = shutil.which(name)
if exe_path:
return exe_path
# Windows executable names
exe_names = [name, f"{name}.exe", f"{name}.cmd", f"{name}.bat"]
# Common installation locations
search_paths = [
# Current Python Scripts directory
find_python_scripts_dir(),
# System Python scripts
Path(sys.prefix) / "Scripts",
# User local
Path.home() / ".local" / "bin",
# Cargo/Rust installations
Path.home() / ".cargo" / "bin",
# Program Files
Path(os.environ.get('PROGRAMFILES', 'C:\\Program Files')),
Path(os.environ.get('PROGRAMFILES(X86)', 'C:\\Program Files (x86)')),
# AppData locations
Path(os.environ.get('LOCALAPPDATA', '')) / "Programs",
]
if additional_paths:
search_paths.extend(additional_paths)
# Search for the executable
for path in search_paths:
if path.exists():
for exe_name in exe_names:
exe_path = path / exe_name
if exe_path.exists() and exe_path.is_file():
return str(exe_path)
# Also check in subdirectories one level deep
try:
for subdir in path.iterdir():
if subdir.is_dir():
sub_exe_path = subdir / exe_name
if sub_exe_path.exists() and sub_exe_path.is_file():
return str(sub_exe_path)
except:
pass
return None
def find_uv_executable():
"""Find the uv executable with comprehensive search."""
global UV_EXECUTABLE
# Check if already found
if UV_EXECUTABLE:
return UV_EXECUTABLE
print("Searching for uv executable...")
# First try standard search
uv_path = find_executable("uv")
if uv_path:
UV_EXECUTABLE = uv_path
return uv_path
# Check if uv is installed as a Python module
try:
import uv
# If we can import it, we can run it with python -m
UV_EXECUTABLE = "python -m uv"
print("✅ Found uv as Python module")
return UV_EXECUTABLE
except ImportError:
pass
return None
def run_uv_command(args, cwd=None):
"""Run a uv command with proper executable handling."""
global UV_EXECUTABLE
if not UV_EXECUTABLE:
raise Exception("uv executable not found")
if UV_EXECUTABLE == "python -m uv":
cmd = [sys.executable, "-m", "uv"] + args
else:
cmd = [UV_EXECUTABLE] + args
return subprocess.run(cmd, capture_output=True, text=True, cwd=cwd)
def install_uv():
"""Install uv package manager using multiple methods."""
print("\n=== Installing uv Package Manager ===")
# Method 1: Try pip install
print("Method 1: Installing via pip...")
try:
result = subprocess.run(
[sys.executable, "-m", "pip", "install", "--user", "uv"],
capture_output=True, text=True
)
if result.returncode == 0:
print("✅ uv installed via pip")
# Try to find it again
if find_uv_executable():
print(f"✅ uv executable found at: {UV_EXECUTABLE}")
return True
else:
print("⚠️ uv installed but executable not found, will use 'python -m uv'")
return True
except Exception as e:
print(f"❌ pip install failed: {e}")
# Method 2: Try PowerShell installer (if admin or execution policy allows)
print("\nMethod 2: Trying PowerShell installer...")
try:
# First set execution policy for current process
subprocess.run([
"powershell", "-Command",
"Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force"
], capture_output=True)
# Download and run installer
ps_command = """
$ErrorActionPreference = 'Stop'
try {
Invoke-WebRequest -UseBasicParsing -Uri 'https://astral.sh/uv/install.ps1' | Invoke-Expression
} catch {
Write-Error $_.Exception.Message
exit 1
}
"""
result = subprocess.run(
["powershell", "-Command", ps_command],
capture_output=True, text=True
)
if result.returncode == 0:
print("✅ uv installed via PowerShell")
# Add common uv install location to PATH
uv_install_dir = Path.home() / ".cargo" / "bin"
add_to_path_temporarily(uv_install_dir)
if find_uv_executable():
print(f"✅ uv executable found at: {UV_EXECUTABLE}")
return True
except Exception as e:
print(f"❌ PowerShell install failed: {e}")
# Method 3: Direct download (last resort)
print("\nMethod 3: Direct download method...")
try:
import urllib.request
import zipfile
# Determine architecture
import platform
machine = platform.machine().lower()
if machine in ['amd64', 'x86_64']:
arch = 'x86_64'
else:
arch = 'i686'
# Download URL for Windows
download_url = f"https://github.com/astral-sh/uv/releases/latest/download/uv-{arch}-pc-windows-msvc.zip"
# Download to temp directory
temp_dir = Path(tempfile.gettempdir()) / "uv_install"
temp_dir.mkdir(exist_ok=True)
zip_path = temp_dir / "uv.zip"
print(f"Downloading from: {download_url}")
urllib.request.urlretrieve(download_url, zip_path)
# Extract
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
zip_ref.extractall(temp_dir)
# Find uv.exe in extracted files
for root, dirs, files in os.walk(temp_dir):
if 'uv.exe' in files:
uv_exe = Path(root) / 'uv.exe'
# Copy to Python Scripts directory
scripts_dir = find_python_scripts_dir()
target_path = scripts_dir / 'uv.exe'
shutil.copy2(uv_exe, target_path)
print(f"✅ uv installed to: {target_path}")
UV_EXECUTABLE = str(target_path)
return True
except Exception as e:
print(f"❌ Direct download failed: {e}")
return False
def check_prerequisites():
"""Check if required tools are installed."""
print("\n=== Checking Prerequisites ===")
# Check for Git
git_path = find_executable("git", [
Path(os.environ.get('PROGRAMFILES', 'C:\\Program Files')) / "Git" / "bin",
Path(os.environ.get('PROGRAMFILES(X86)', 'C:\\Program Files (x86)')) / "Git" / "bin",
])
if not git_path:
print("❌ Git is not installed.")
print("\nGit is required for this setup. Would you like to:")
print("1. Download Git installer (recommended)")
print("2. Continue without Git (manual setup required)")
choice = input("\nEnter your choice (1 or 2): ").strip()
if choice == "1":
print("\nOpening Git download page...")
import webbrowser
webbrowser.open("https://git-scm.com/download/win")
print("\nPlease install Git and run this script again.")
return False
else:
print("⚠️ Continuing without Git. You'll need to download the repository manually.")
else:
print(f"✅ Git is installed at: {git_path}")
# Check for uv
if not find_uv_executable():
if not install_uv():
print("\n❌ Failed to install uv package manager")
print("Please install uv manually from https://docs.astral.sh/uv/")
return False
else:
print(f"✅ uv is available: {UV_EXECUTABLE}")
return True
def fix_claude_config():
"""Fix the Claude desktop configuration JSON file if it has syntax errors."""
print("\n=== Checking Claude Configuration ===")
# Path to Claude config file
config_path = Path(os.environ['APPDATA']) / 'Claude' / 'claude_desktop_config.json'
print(f"Checking Claude config at: {config_path}")
if not config_path.exists():
print("Claude configuration file not found. Will create a new one.")
return create_minimal_claude_config()
try:
# Try to read and parse the existing config
with open(config_path, 'r', encoding='utf-8') as f:
content = f.read()
# Test if JSON is valid
json.loads(content)
print("✅ Claude configuration file is valid")
return True
except json.JSONDecodeError as e:
print(f"❌ JSON syntax error in Claude config: {e}")
print(f"Error at line {e.lineno}, column {e.colno}")
# Create backup before fixing
backup_path = config_path.with_suffix('.json.backup')
shutil.copy2(config_path, backup_path)
print(f"✅ Created backup at: {backup_path}")
# Attempt to fix common JSON issues
return attempt_json_fix(config_path, content)
except Exception as e:
print(f"❌ Error reading Claude config: {e}")
return False
def attempt_json_fix(config_path, content):
"""Attempt to automatically fix common JSON syntax errors."""
print("Attempting to fix JSON syntax errors...")
try:
# Common fixes for JSON syntax errors
lines = content.split('\n')
fixed_lines = []
for i, line in enumerate(lines):
# Remove comments (not valid in JSON)
if '//' in line:
comment_pos = line.find('//')
line = line[:comment_pos].rstrip()
# Fix missing commas between objects/arrays
stripped = line.strip()
if i < len(lines) - 1: # Not the last line
next_line = lines[i + 1].strip()
# Check if we need a comma
needs_comma = (
(stripped.endswith('}') or stripped.endswith(']') or stripped.endswith('"')) and
(next_line.startswith('"') or next_line.startswith('{') or next_line.startswith('[')) and
not stripped.endswith(',')
)
if needs_comma:
# Add comma to the original line (preserving indentation)
line = line.rstrip() + ','
# Remove trailing commas before closing braces/brackets
if stripped.endswith(',}'):
line = line.replace(',}', '}')
elif stripped.endswith(',]'):
line = line.replace(',]', ']')
fixed_lines.append(line)
fixed_content = '\n'.join(fixed_lines)
# Try to parse the fixed content
parsed = json.loads(fixed_content)
# Pretty print and save
formatted_json = json.dumps(parsed, indent=2)
with open(config_path, 'w', encoding='utf-8') as f:
f.write(formatted_json)
print("✅ JSON file fixed and reformatted successfully!")
return True
except json.JSONDecodeError as e:
print(f"❌ Auto-fix failed: {e}")
print("Creating a fresh minimal configuration...")
return create_minimal_claude_config()
except Exception as e:
print(f"❌ Error during fix attempt: {e}")
return False
def create_minimal_claude_config():
"""Create a minimal valid Claude configuration."""
config_path = Path(os.environ['APPDATA']) / 'Claude' / 'claude_desktop_config.json'
minimal_config = {
"mcpServers": {}
}
try:
# Create directory if it doesn't exist
config_path.parent.mkdir(parents=True, exist_ok=True)
with open(config_path, 'w', encoding='utf-8') as f:
json.dump(minimal_config, f, indent=2)
print(f"✅ Created minimal Claude configuration at: {config_path}")
return True
except Exception as e:
print(f"❌ Error creating minimal config: {e}")
return False
def get_user_inputs():
"""Get Dremio connection details from user."""
print("\n=== Dremio Connection Details ===")
# Get server IP/hostname
server_ip = input("Enter Dremio server IP address or hostname (e.g., localhost or 192.168.1.100): ").strip()
if not server_ip:
server_ip = "localhost"
# Get port
port = input("Enter Dremio port (default: 9047): ").strip()
if not port:
port = "9047"
# Get protocol
print("\nDoes your Dremio server use HTTPS? (Usually 'no' for local/development servers)")
use_https = input("Use HTTPS? (y/N): ").strip().lower()
protocol = "https" if use_https == 'y' else "http"
# Get username
username = input("\nEnter Dremio username: ").strip()
if not username:
print("❌ Username is required")
sys.exit(1)
# Get password
import getpass
password = getpass.getpass("Enter Dremio password: ")
if not password:
print("❌ Password is required")
sys.exit(1)
# Construct URI
uri = f"{protocol}://{server_ip}:{port}"
print(f"\nUsing Dremio server at: {uri}")
return {
"uri": uri,
"username": username,
"password": password
}
def generate_pat(uri, username, password):
"""Generate Personal Access Token from Dremio."""
print("\n=== Generating Personal Access Token ===")
# Import requests here after ensuring it's installed
import requests
login_endpoint = f"{uri}/apiv2/login"
try:
# Disable SSL warnings for self-signed certificates
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Make login request
response = requests.post(
login_endpoint,
json={"userName": username, "password": password},
headers={"Content-Type": "application/json"},
verify=False, # For self-signed certificates
timeout=10 # Add timeout
)
if response.status_code == 200:
token = response.json().get("token")
if token:
print("✅ PAT generated successfully")
return token
else:
print("❌ Failed to extract token from response")
return None
else:
print(f"❌ Login failed with status code: {response.status_code}")
print(f"Response: {response.text}")
return None
except requests.exceptions.SSLError as e:
print(f"❌ SSL Error: {str(e)}")
print("\nThis usually means the server is using HTTP, not HTTPS.")
print("Please run the script again and choose 'N' when asked about HTTPS.")
return None
except requests.exceptions.ConnectionError as e:
print(f"❌ Connection Error: {str(e)}")
print("\nPlease check:")
print("1. The server IP address is correct")
print("2. The port is correct (default is 9047)")
print("3. The Dremio server is running")
print("4. Your firewall allows the connection")
return None
except Exception as e:
print(f"❌ Error generating PAT: {str(e)}")
return None
def clone_mcp_repository(target_dir=None):
"""Clone the Dremio MCP Server repository."""
print("\n=== Setting up Dremio MCP Server Repository ===")
if target_dir is None:
target_dir = Path.home() / "dremio-mcp"
else:
target_dir = Path(target_dir)
# Check if directory already exists
if target_dir.exists():
response = input(f"Directory {target_dir} already exists. Remove and re-clone? (y/n): ")
if response.lower() == 'y':
shutil.rmtree(target_dir)
else:
print("Using existing directory")
return str(target_dir)
# Check if Git is available
git_path = find_executable("git")
if git_path:
try:
subprocess.run([
git_path, "clone", "https://github.com/dremio/dremio-mcp", str(target_dir)
], check=True)
print("✅ Repository cloned successfully")
return str(target_dir)
except subprocess.CalledProcessError as e:
print(f"❌ Failed to clone repository: {str(e)}")
return None
else:
# Manual download option
print("\n⚠️ Git is not available. Would you like to:")
print("1. Download the repository as ZIP (manual)")
print("2. Cancel setup")
choice = input("\nEnter your choice (1 or 2): ").strip()
if choice == "1":
print("\nOpening repository page...")
import webbrowser
webbrowser.open("https://github.com/dremio/dremio-mcp/archive/refs/heads/main.zip")
print(f"\nPlease extract the downloaded ZIP to: {target_dir}")
input("Press Enter after extracting the files...")
# Check if files were extracted properly
if target_dir.exists():
# Look for main directory structure
possible_dirs = [
target_dir,
target_dir / "dremio-mcp-main",
target_dir / "dremio-mcp"
]
for dir_check in possible_dirs:
if (dir_check / "pyproject.toml").exists():
if dir_check != target_dir:
# Move contents to target directory
print(f"Moving files from {dir_check} to {target_dir}")
for item in dir_check.iterdir():
shutil.move(str(item), str(target_dir))
dir_check.rmdir()
print("✅ Repository files found and organized")
return str(target_dir)
print("❌ Repository files not found in expected structure")
return None
else:
print("❌ Repository files not found at expected location")
return None
else:
return None
def setup_mcp_server(repo_dir, uri, pat):
"""Configure the Dremio MCP Server."""
print("\n=== Configuring Dremio MCP Server ===")
os.chdir(repo_dir)
# Create dremioai configuration
print("Creating dremioai configuration...")
try:
result = run_uv_command([
"run", "dremio-mcp-server", "config", "create", "dremioai",
"--uri", uri,
"--pat", pat
], cwd=repo_dir)
if result.returncode == 0:
print("✅ Dremioai configuration created")
else:
print(f"❌ Failed to create dremioai configuration: {result.stderr}")
return False
except Exception as e:
print(f"❌ Failed to create dremioai configuration: {str(e)}")
return False
# Create Claude configuration
print("Creating Claude configuration...")
try:
result = run_uv_command([
"run", "dremio-mcp-server", "config", "create", "claude"
], cwd=repo_dir)
if result.returncode == 0:
print("✅ Claude configuration created")
else:
print(f"❌ Failed to create Claude configuration.")
print(f"Error output: {result.stderr}")
# Try manual approach
print("Attempting manual Claude configuration...")
if create_manual_claude_mcp_config(repo_dir):
print("✅ Manual Claude configuration successful")
else:
return False
except Exception as e:
print(f"❌ Failed to create Claude configuration: {str(e)}")
print("Attempting manual Claude configuration...")
if not create_manual_claude_mcp_config(repo_dir):
return False
# Verify configurations
print("\n=== Verifying Configurations ===")
try:
# Verify dremioai config
result = run_uv_command([
"run", "dremio-mcp-server", "config", "list", "--type", "dremioai"
], cwd=repo_dir)
print("Dremioai configuration:")
print(result.stdout)
# Verify Claude config
result = run_uv_command([
"run", "dremio-mcp-server", "config", "list", "--type", "claude"
], cwd=repo_dir)
print("\nClaude configuration:")
print(result.stdout)
except Exception as e:
print(f"❌ Failed to verify configurations: {str(e)}")
# Continue anyway as configs might still work
return True
def create_manual_claude_mcp_config(repo_dir):
"""Manually create Claude MCP configuration if automated method fails."""
try:
config_path = Path(os.environ['APPDATA']) / 'Claude' / 'claude_desktop_config.json'
# Read existing config
if config_path.exists():
with open(config_path, 'r', encoding='utf-8') as f:
config = json.load(f)
else:
config = {}
# Ensure mcpServers section exists
if 'mcpServers' not in config:
config['mcpServers'] = {}
# Determine the command to use
if UV_EXECUTABLE == "python -m uv":
command = sys.executable
args = ["-m", "uv", "run", "--directory", str(repo_dir), "dremio-mcp-server", "run"]
else:
command = UV_EXECUTABLE
args = ["run", "--directory", str(repo_dir), "dremio-mcp-server", "run"]
# Add Dremio MCP server configuration
config['mcpServers']['Dremio'] = {
"command": command,
"args": args
}
# Write updated config
with open(config_path, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2)
print("✅ Manually added Dremio MCP configuration to Claude")
return True
except Exception as e:
print(f"❌ Error creating manual Claude configuration: {e}")
return False
def create_startup_script(repo_dir):
"""Create a batch file to easily start the MCP server."""
print("\n=== Creating Startup Script ===")
# Determine the command to use
if UV_EXECUTABLE == "python -m uv":
command = f'"{sys.executable}" -m uv'
else:
command = f'"{UV_EXECUTABLE}"'
batch_content = f"""@echo off
cd /d "{repo_dir}"
echo Starting Dremio MCP Server...
{command} run dremio-mcp-server run
pause
"""
# Save to desktop
desktop = Path.home() / "Desktop"
batch_file = desktop / "Start_Dremio_MCP_Server.bat"
try:
with open(batch_file, 'w') as f:
f.write(batch_content)
print(f"✅ Startup script created at: {batch_file}")
return str(batch_file)
except Exception as e:
print(f"❌ Failed to create startup script: {str(e)}")
return None
def main():
"""Main execution function."""
print("=== Dremio MCP Server Setup for Windows ===")
print("This script will set up the Dremio MCP Server on your Windows system.")
print("Version: 3.0 (Fully Dynamic Multi-User Support)")
print(f"Current user: {os.environ.get('USERNAME', 'Unknown')}")
# Check if running as admin
if not is_admin():
print("\n⚠️ Running without administrator privileges")
print(" Some features may be limited")
print(" For best results, run this script as Administrator")
response = input("\nContinue anyway? (y/n): ").strip().lower()
if response != 'y':
sys.exit(0)
# Check Python installation
if not check_python_installation():
print("\n❌ Python installation check failed.")
input("Press Enter to exit...")
sys.exit(1)
# Check pip installation
if not check_pip_installation():
print("\n❌ pip installation check failed.")
input("Press Enter to exit...")
sys.exit(1)
# Ensure required Python packages
if not ensure_dependencies():
print("\n❌ Failed to install required Python packages.")
input("Press Enter to exit...")
sys.exit(1)
# Check and fix Claude configuration
if not fix_claude_config():
print("\n❌ Failed to prepare Claude configuration. Please fix manually.")
input("Press Enter to exit...")
sys.exit(1)
# Check other prerequisites (Git, uv)
if not check_prerequisites():
print("\n❌ Prerequisites check failed. Please install missing components.")
input("Press Enter to exit...")
sys.exit(1)
# Get user inputs
config = get_user_inputs()
# Generate PAT
pat = generate_pat(config["uri"], config["username"], config["password"])
if not pat:
print("\n❌ Failed to generate PAT. Please check your credentials and server connection.")
input("Press Enter to exit...")
sys.exit(1)
# Clone repository
repo_dir = clone_mcp_repository()
if not repo_dir:
print("\n❌ Failed to set up repository.")
input("Press Enter to exit...")
sys.exit(1)
# Setup MCP server
if not setup_mcp_server(repo_dir, config["uri"], pat):
print("\n❌ Failed to configure MCP server.")
input("Press Enter to exit...")
sys.exit(1)
# Create startup script
startup_script = create_startup_script(repo_dir)
# Final instructions
print("\n=== Setup Complete! ===")
print("\n✅ Dremio MCP Server has been successfully configured!")
print("\nNext steps:")
print("1. Restart Claude Desktop (close and reopen it)")
print("2. The Dremio MCP Server should automatically appear in Claude")
print("3. Start a new chat and ask about available tables in Dremio")
if startup_script:
print(f"\nYou can also manually start the MCP server by running: {startup_script}")
print("\nFor more information, visit: https://docs.dremio.com/current/mcp-server/")
# Summary of installation
print("\n=== Installation Summary ===")
print(f"Python: {sys.executable}")
print(f"uv: {UV_EXECUTABLE}")
print(f"Repository: {repo_dir}")
print(f"Claude config: {Path(os.environ['APPDATA']) / 'Claude' / 'claude_desktop_config.json'}")
input("\nPress Enter to exit...")
if __name__ == "__main__":
# Ensure we're running on Windows
if platform.system() != "Windows":
print("This script is designed for Windows systems.")
sys.exit(1)
try:
main()
except KeyboardInterrupt:
print("\n\nSetup cancelled by user.")
sys.exit(0)
except Exception as e:
print(f"\n❌ Unexpected error: {str(e)}")
print("\n=== Debug Information ===")
traceback.print_exc()
print(f"\nPython: {sys.executable}")
print(f"Platform: {platform.platform()}")
print(f"Working directory: {os.getcwd()}")
input("\nPress Enter to exit...")
sys.exit(1)
Metadata
Metadata
Assignees
Labels
No labels