Skip to main content
Glama
installer.py5.02 kB
import json import os import platform import shutil import sys from pathlib import Path from jinja2 import Template _HERE = Path(__file__).parent CLAUDE_DESKTOP_CONFIG_TEMPLATE = _HERE / "claude_desktop_config.json" system = platform.system() if system == "Darwin": CLAUDE_DESKTOP_CONFIG_PATH = os.path.expanduser("~/Library/Application Support/Claude/claude_desktop_config.json") elif system == "Windows": CLAUDE_DESKTOP_CONFIG_PATH = os.path.join(os.environ["APPDATA"], "Claude", "claude_desktop_config.json") else: CLAUDE_DESKTOP_CONFIG_PATH = None def get_endpoint_path() -> str: """ Find the path to the mcp-email-server script. Similar to the 'which' command in Unix-like systems. Returns: str: The full path to the mcp-email-server script """ # First try using shutil.which to find the script in PATH script_path = shutil.which("mcp-email-server") if script_path: return script_path # If not found in PATH, try to find it in the current Python environment # This handles cases where the script is installed but not in PATH bin_dir = Path(sys.executable).parent possible_paths = [ bin_dir / "mcp-email-server", bin_dir / "mcp-email-server.exe", # For Windows ] for path in possible_paths: if path.exists(): return str(path) # If we can't find it, return the script name and hope it's in PATH when executed return "mcp-email-server" def install_claude_desktop(): # Read the template config template_content = CLAUDE_DESKTOP_CONFIG_TEMPLATE.read_text() rendered_content = Template(template_content).render(ENTRYPOINT=get_endpoint_path()) template_config = json.loads(rendered_content) if not CLAUDE_DESKTOP_CONFIG_PATH: raise NotImplementedError # Read the existing config file or create an empty JSON object try: with open(CLAUDE_DESKTOP_CONFIG_PATH) as f: existing_config = json.load(f) except FileNotFoundError: existing_config = {} # Merge the template config into the existing config if "mcpServers" not in existing_config: existing_config["mcpServers"] = {} existing_config["mcpServers"].update(template_config["mcpServers"]) # Write the merged config back to the Claude config file os.makedirs(os.path.dirname(CLAUDE_DESKTOP_CONFIG_PATH), exist_ok=True) with open(CLAUDE_DESKTOP_CONFIG_PATH, "w") as f: json.dump(existing_config, f, indent=4) def uninstall_claude_desktop(): if not CLAUDE_DESKTOP_CONFIG_PATH: raise NotImplementedError try: with open(CLAUDE_DESKTOP_CONFIG_PATH) as f: existing_config = json.load(f) except FileNotFoundError: return if "mcpServers" not in existing_config: return if "zerolib-email" in existing_config["mcpServers"]: del existing_config["mcpServers"]["zerolib-email"] with open(CLAUDE_DESKTOP_CONFIG_PATH, "w") as f: json.dump(existing_config, f, indent=4) def is_installed() -> bool: """ Check if the MCP email server is installed in the Claude desktop configuration. Returns: bool: True if installed, False otherwise """ if not CLAUDE_DESKTOP_CONFIG_PATH: return False try: with open(CLAUDE_DESKTOP_CONFIG_PATH) as f: config = json.load(f) return "mcpServers" in config and "zerolib-email" in config["mcpServers"] except (FileNotFoundError, json.JSONDecodeError): return False def need_update() -> bool: """ Check if the installed configuration needs to be updated. Returns: bool: True if an update is needed, False otherwise """ if not is_installed(): return True try: # Get the template config template_content = CLAUDE_DESKTOP_CONFIG_TEMPLATE.read_text() rendered_content = Template(template_content).render(ENTRYPOINT=get_endpoint_path()) template_config = json.loads(rendered_content) # Get the installed config with open(CLAUDE_DESKTOP_CONFIG_PATH) as f: installed_config = json.load(f) # Compare the relevant parts of the configs template_server = template_config["mcpServers"]["zerolib-email"] installed_server = installed_config["mcpServers"]["zerolib-email"] # Check if any key configuration elements differ return ( template_server.get("command") != installed_server.get("command") or template_server.get("args") != installed_server.get("args") or template_server.get("env") != installed_server.get("env") ) except (FileNotFoundError, json.JSONDecodeError, KeyError): # If any error occurs during comparison, suggest an update return True def get_claude_desktop_config() -> str: if not CLAUDE_DESKTOP_CONFIG_PATH: raise NotImplementedError with open(CLAUDE_DESKTOP_CONFIG_PATH) as f: return f.read()

Latest Blog Posts

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/ai-zerolab/mcp-email-server'

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