From c7d5ee2006e405f359ecd6cf37535495e9db2bd9 Mon Sep 17 00:00:00 2001 From: Spaike Date: Thu, 7 May 2026 23:10:54 +0200 Subject: [PATCH] Add interactive setup wizard - setup.py detects OS, installs deps, opens browser for API key, and writes claude_desktop_config.json automatically - README: quick-install section with 3 commands at the top --- README.md | 54 ++++++++------ setup.py | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 241 insertions(+), 23 deletions(-) create mode 100644 setup.py diff --git a/README.md b/README.md index baa19ec..3a4810e 100644 --- a/README.md +++ b/README.md @@ -2,49 +2,60 @@ Collega Claude Desktop (o qualsiasi client MCP) al portale Cauldron. -## Prerequisiti +## Installazione rapida (3 comandi) + +```bash +git clone https://git.zerotohero.it/Spaike/cauldron-mcp.git +cd cauldron-mcp +python setup.py +``` + +Il wizard: +1. Installa le dipendenze automaticamente +2. Apre il browser sulla pagina API Keys del portale +3. Legge la chiave che incolli nel terminale +4. Scrive `claude_desktop_config.json` senza toccare le altre configurazioni + +Poi riavvia Claude Desktop — fatto. + +--- + +## Installazione manuale (alternativa) + +### Prerequisiti - Python 3.10+ -- Pip +- pip -## Installazione +### Dipendenze ```bash pip install mcp httpx ``` -Oppure con un virtual environment (consigliato): +### Ottenere la API Key -```bash -python -m venv .venv -source .venv/bin/activate # Linux/Mac -# oppure: .venv\Scripts\activate # Windows -pip install -r requirements.txt -``` - -## Ottenere la propria API Key - -Accedere al portale Cauldron → Profilo → API Keys → "Genera nuova chiave". +Accedere al portale Cauldron → menu utente → **API Keys** → "Generate". La chiave ha il formato: `cldrn_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` -> La chiave viene mostrata UNA SOLA VOLTA. Conservarla in modo sicuro. +> La chiave viene mostrata **una sola volta**. Conservarla in modo sicuro. -## Configurazione Claude Desktop +### Configurazione Claude Desktop -Aprire il file di configurazione di Claude Desktop: +Aprire il file di configurazione: - **Mac**: `~/Library/Application Support/Claude/claude_desktop_config.json` - **Linux**: `~/.config/Claude/claude_desktop_config.json` - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` -Aggiungere (o completare) la sezione `mcpServers`: +Aggiungere la sezione `mcpServers`: ```json { "mcpServers": { "cauldron": { "command": "python", - "args": ["/percorso/assoluto/al/server.py"], + "args": ["/percorso/assoluto/cauldron-mcp/server.py"], "env": { "CAULDRON_API_KEY": "cldrn_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } @@ -53,10 +64,7 @@ Aggiungere (o completare) la sezione `mcpServers`: } ``` -Sostituire `/percorso/assoluto/al/server.py` con il path reale del file. -Se si usa un venv: `"command": "/percorso/.venv/bin/python"`. - -Riavviare Claude Desktop per caricare la configurazione. +Riavviare Claude Desktop. ## Tool disponibili diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..439c811 --- /dev/null +++ b/setup.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python3 +""" +Cauldron Cloud MCP — Setup wizard +Installs dependencies and writes Claude Desktop config automatically. +""" + +import json +import os +import platform +import shutil +import subprocess +import sys +import webbrowser +from pathlib import Path + +# ── Colours ────────────────────────────────────────────────────────────────── + +def _supports_colour() -> bool: + return sys.stdout.isatty() and platform.system() != "Windows" + +if _supports_colour(): + RESET = "\033[0m" + BOLD = "\033[1m" + GREEN = "\033[32m" + YELLOW = "\033[33m" + RED = "\033[31m" + CYAN = "\033[36m" +else: + RESET = BOLD = GREEN = YELLOW = RED = CYAN = "" + +def ok(msg: str) -> None: print(f"{GREEN} ✓ {RESET}{msg}") +def info(msg: str) -> None: print(f"{CYAN} → {RESET}{msg}") +def warn(msg: str) -> None: print(f"{YELLOW} ⚠ {RESET}{msg}") +def err(msg: str) -> None: print(f"{RED} ✗ {RESET}{msg}") +def bold(msg: str) -> str: return f"{BOLD}{msg}{RESET}" + +# ── Helpers ─────────────────────────────────────────────────────────────────── + +def _python_executable() -> str: + """Return the Python executable that is running this script.""" + return sys.executable + + +def _config_path() -> Path: + system = platform.system() + if system == "Windows": + base = Path(os.environ.get("APPDATA", "~")).expanduser() + return base / "Claude" / "claude_desktop_config.json" + if system == "Darwin": + return Path.home() / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json" + # Linux / other + xdg = os.environ.get("XDG_CONFIG_HOME", "") + base = Path(xdg) if xdg else Path.home() / ".config" + return base / "Claude" / "claude_desktop_config.json" + + +def _read_config(path: Path) -> dict: + if path.exists(): + try: + return json.loads(path.read_text(encoding="utf-8")) + except json.JSONDecodeError: + warn("Existing config file contains invalid JSON — it will be backed up and rewritten.") + backup = path.with_suffix(".json.bak") + shutil.copy(path, backup) + info(f"Backup saved to {backup}") + return {} + + +def _write_config(path: Path, data: dict) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8") + + +def _install_deps() -> bool: + packages = ["mcp>=1.0.0", "httpx>=0.27.0"] + info("Installing Python dependencies...") + result = subprocess.run( + [_python_executable(), "-m", "pip", "install", "--quiet", *packages], + capture_output=True, + text=True, + ) + if result.returncode != 0: + err("pip install failed:") + print(result.stderr.strip()) + return False + return True + + +def _check_deps() -> bool: + try: + import mcp # noqa: F401 + import httpx # noqa: F401 + return True + except ImportError: + return False + + +def _validate_key(key: str) -> bool: + key = key.strip() + return key.startswith("cldrn_") and len(key) >= 20 + +# ── Main ────────────────────────────────────────────────────────────────────── + +def main() -> None: + print() + print(bold("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")) + print(bold(" Cauldron Cloud — MCP Server Setup")) + print(bold("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")) + print() + + # ── 1. Python version check ─────────────────────────────────────────────── + if sys.version_info < (3, 10): + err(f"Python 3.10+ required (you have {platform.python_version()}).") + sys.exit(1) + ok(f"Python {platform.python_version()}") + + # ── 2. Dependencies ─────────────────────────────────────────────────────── + if _check_deps(): + ok("Dependencies already installed (mcp, httpx)") + else: + if not _install_deps(): + err("Could not install dependencies. Try manually: pip install mcp httpx") + sys.exit(1) + if not _check_deps(): + err("Dependencies installed but import still fails. Check your Python environment.") + sys.exit(1) + ok("Dependencies installed (mcp, httpx)") + + # ── 3. Locate server.py ─────────────────────────────────────────────────── + server_py = Path(__file__).resolve().parent / "server.py" + if not server_py.exists(): + err(f"server.py not found at {server_py}") + sys.exit(1) + ok(f"Server script: {server_py}") + + # ── 4. Get the API key ──────────────────────────────────────────────────── + print() + print(bold(" Step: Generate your API key")) + print() + print(" A browser window will open to the Cauldron portal.") + print(" Log in, click Generate , copy the key and paste it below.") + print() + input(" Press ENTER to open the browser...") + + portal_url = "https://cauldron.cloud/mcpKeys" + webbrowser.open(portal_url) + info(f"Opened: {portal_url}") + print() + + api_key = "" + for attempt in range(3): + raw = input(" Paste your API key here: ").strip() + if _validate_key(raw): + api_key = raw + break + err("Key must start with cldrn_ and be at least 20 characters. Try again.") + else: + err("No valid key provided. Run setup.py again when you have a key.") + sys.exit(1) + + ok(f"Key accepted: {api_key[:14]}…") + + # ── 5. Detect Claude Desktop config ─────────────────────────────────────── + config_path = _config_path() + print() + info(f"Config file: {config_path}") + + config = _read_config(config_path) + + # ── 6. Merge mcpServers entry ───────────────────────────────────────────── + python_cmd = _python_executable() + + mcp_entry = { + "command": python_cmd, + "args": [str(server_py)], + "env": {"CAULDRON_API_KEY": api_key}, + } + + if "mcpServers" not in config: + config["mcpServers"] = {} + + existing = config["mcpServers"].get("cauldron") + config["mcpServers"]["cauldron"] = mcp_entry + + _write_config(config_path, config) + + if existing: + ok("Updated existing cauldron entry in Claude Desktop config") + else: + ok("Added cauldron entry to Claude Desktop config") + + # ── 7. Done ─────────────────────────────────────────────────────────────── + print() + print(bold("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")) + print(bold(" Setup complete!")) + print(bold("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")) + print() + print(" Next steps:") + print(f" 1. {bold('Restart Claude Desktop')}") + print(" 2. Open a new Chat") + print(" 3. Look for the 🔌 icon — cauldron should appear in the tool list") + print() + print(" Try asking Claude:") + print(f" {CYAN}\"Show me all open Sell Side deals in the Automotive sector\"{RESET}") + print(f" {CYAN}\"Are there any incoming Requests for Help we haven't answered?\"{RESET}") + print() + + +if __name__ == "__main__": + main()