#!/usr/bin/env python3
"""
Interactive setup script for Wealthfolio MCP Server.
Automatically detects paths and configures Claude Desktop.
"""
import json
import os
import platform
import sys
from pathlib import Path
# Fix Windows console encoding for Unicode characters
if platform.system() == "Windows":
try:
sys.stdout.reconfigure(encoding='utf-8')
except Exception:
pass # Fallback to default encoding
def get_os_type():
"""Detect the operating system."""
system = platform.system()
if system == "Windows":
return "windows"
elif system == "Darwin":
return "macos"
elif system == "Linux":
return "linux"
else:
return "unknown"
def find_wealthfolio_db():
"""Try to find the Wealthfolio database in standard locations."""
os_type = get_os_type()
possible_paths = []
if os_type == "windows":
appdata = os.environ.get("APPDATA")
if appdata:
possible_paths.append(Path(appdata) / "com.teymz.wealthfolio" / "app.db")
elif os_type == "macos":
home = Path.home()
possible_paths.append(home / "Library" / "Application Support" / "com.teymz.wealthfolio" / "app.db")
elif os_type == "linux":
home = Path.home()
possible_paths.append(home / ".local" / "share" / "com.teymz.wealthfolio" / "app.db")
# Check which paths exist
for path in possible_paths:
if path.exists():
return path
return None
def get_claude_config_path():
"""Get the Claude Desktop configuration file path."""
os_type = get_os_type()
if os_type == "windows":
appdata = os.environ.get("APPDATA")
if appdata:
return Path(appdata) / "Claude" / "claude_desktop_config.json"
elif os_type == "macos":
home = Path.home()
return home / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json"
elif os_type == "linux":
home = Path.home()
return home / ".config" / "Claude" / "claude_desktop_config.json"
return None
def get_project_directory():
"""Get the absolute path to this project directory."""
return Path(__file__).parent.resolve()
def load_or_create_config(config_path):
"""Load existing config or create new one."""
if config_path.exists():
try:
with open(config_path, 'r', encoding='utf-8') as f:
return json.load(f)
except json.JSONDecodeError:
print(f"⚠️ Warning: Existing config file is invalid JSON")
return {}
else:
return {}
def format_path_for_json(path, os_type):
"""Format path appropriately for JSON (escape backslashes on Windows)."""
path_str = str(path)
if os_type == "windows":
# Use forward slashes or escaped backslashes
return path_str.replace("\\", "\\\\")
return path_str
def main():
print("=" * 60)
print("Wealthfolio MCP Server - Setup Wizard")
print("=" * 60)
print()
# Detect OS
os_type = get_os_type()
print(f"[OK] Detected OS: {os_type}")
if os_type == "unknown":
print("[ERROR] Unsupported operating system")
sys.exit(1)
# Get project directory (where this script is)
project_dir = get_project_directory()
print(f"[OK] Project directory: {project_dir}")
print()
# Find Wealthfolio database
print("Looking for Wealthfolio database...")
db_path = find_wealthfolio_db()
if db_path:
print(f"[OK] Found database: {db_path}")
response = input(" Use this path? (Y/n): ").strip().lower()
if response and response != 'y':
db_path = None
if not db_path:
print("\nPlease enter the path to your Wealthfolio database:")
if os_type == "windows":
print(" (Example: C:\\Users\\YourName\\AppData\\Roaming\\com.teymz.wealthfolio\\app.db)")
elif os_type == "macos":
print(" (Example: /Users/yourname/Library/Application Support/com.teymz.wealthfolio/app.db)")
else:
print(" (Example: /home/username/.local/share/com.teymz.wealthfolio/app.db)")
db_input = input("Database path: ").strip()
db_path = Path(db_input)
if not db_path.exists():
print(f"[WARNING] Database file not found at {db_path}")
response = input(" Continue anyway? (y/N): ").strip().lower()
if response != 'y':
print("Setup cancelled.")
sys.exit(1)
print()
# Get Claude config path
config_path = get_claude_config_path()
if not config_path:
print("[ERROR] Could not determine Claude Desktop config location")
sys.exit(1)
print(f"Claude Desktop config: {config_path}")
# Ensure config directory exists
config_path.parent.mkdir(parents=True, exist_ok=True)
# Load or create config
config = load_or_create_config(config_path)
# Ensure mcpServers section exists
if "mcpServers" not in config:
config["mcpServers"] = {}
# Create Wealthfolio MCP configuration
project_dir_str = format_path_for_json(project_dir, os_type)
db_path_str = format_path_for_json(db_path, os_type)
config["mcpServers"]["wealthfolio"] = {
"command": "uv",
"args": [
"--directory",
project_dir_str,
"run",
"python",
"mcp_server.py"
],
"env": {
"DB_PATH": db_path_str
}
}
# Check if config already has wealthfolio
if config_path.exists():
existing_config = load_or_create_config(config_path)
if "mcpServers" in existing_config and "wealthfolio" in existing_config.get("mcpServers", {}):
print("\n[WARNING] Wealthfolio MCP server is already configured.")
response = input(" Overwrite existing configuration? (y/N): ").strip().lower()
if response != 'y':
print("Setup cancelled.")
sys.exit(0)
# Write config
try:
with open(config_path, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2)
print("\n[OK] Configuration saved successfully!")
except Exception as e:
print(f"\n[ERROR] Error writing config file: {e}")
sys.exit(1)
# Summary
print("\n" + "=" * 60)
print("Setup Complete!")
print("=" * 60)
print("\nConfiguration summary:")
print(f" Project: {project_dir}")
print(f" Database: {db_path}")
print(f" Config: {config_path}")
print("\nNext steps:")
print(" 1. Restart Claude Desktop completely")
print(" 2. Ask Claude: 'What MCP servers are available?'")
print(" 3. Try: 'What's my total portfolio value?'")
print("\nEnjoy analyzing your portfolio with Claude!\n")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\nSetup cancelled by user.")
sys.exit(0)
except Exception as e:
print(f"\n[ERROR] Unexpected error: {e}")
sys.exit(1)