mem0 Memory System

#!/usr/bin/env python3 """ ✨ mem0 MCP Server Launcher ✨ Made with ❤️ by Pink Pixel This script launches the mem0 MCP server with configurable options. It's designed to be used as a command for MCP-compatible applications like Cursor, Claude Desktop, etc. Usage: python start_mem0_server.py [options] Options: --host HOST Host to bind the server to (default: 0.0.0.0) --port PORT Port to bind the server to (default: 8000) --provider PROVIDER LLM provider to use (default: from .env or ollama) --embedding-provider EP Embedding provider to use (default: from .env or ollama) --data-dir DIR Directory to store memory data (default: from .env or ~/mem0_memories) --no-auto-port Disable automatic port finding --reload Enable auto-reload for development --quiet Reduce output verbosity --debug Enable debug mode """ import os import sys import argparse import subprocess import signal import time import socket import json from pathlib import Path from dotenv import load_dotenv # Colors for terminal output BOLD = '\033[1m' GREEN = '\033[0;32m' YELLOW = '\033[0;33m' BLUE = '\033[0;34m' PURPLE = '\033[0;35m' CYAN = '\033[0;36m' WHITE = '\033[0;37m' RED = '\033[0;31m' NC = '\033[0m' # No Color # ASCII Art Banner BANNER = f""" {BOLD}# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓{NC} {BOLD}# ┃ ┃{NC} {BOLD}# ┃ {GREEN}███╗ ███╗███████╗███╗ ███╗ ██████╗ ███╗ ███╗ ██████╗██████╗{NC} {BOLD}┃{NC} {BOLD}# ┃ {GREEN}████╗ ████║██╔════╝████╗ ████║██╔═══██╗ ████╗ ████║██╔════╝██╔══██╗{NC} {BOLD}┃{NC} {BOLD}# ┃ {GREEN}██╔████╔██║█████╗ ██╔████╔██║██║ ██║ ██╔████╔██║██║ ██████╔╝{NC} {BOLD}┃{NC} {BOLD}# ┃ {GREEN}██║╚██╔╝██║██╔══╝ ██║╚██╔╝██║██║ ██║ ██║╚██╔╝██║██║ ██╔═══╝{NC} {BOLD}┃{NC} {BOLD}# ┃ {GREEN}██║ ╚═╝ ██║███████╗██║ ╚═╝ ██║╚██████╔╝ ██║ ╚═╝ ██║╚██████╗██║{NC} {BOLD}┃{NC} {BOLD}# ┃ {GREEN}╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚═╝{NC} {BOLD}┃{NC} {BOLD}# ┃ ┃{NC} {BOLD}# ┃ {GREEN}✨ SERVER LAUNCHER ✨{NC} {BOLD}┃{NC} {BOLD}# ┃ {GREEN}Made with ❤️ by Pink Pixel{NC} {BOLD}┃{NC} {BOLD}# ┃ ┃{NC} {BOLD}# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛{NC} """ def is_port_in_use(port, host="0.0.0.0"): """Check if a port is in use.""" with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: return s.connect_ex((host, port)) == 0 def find_available_port(start_port, host="0.0.0.0"): """Find an available port starting from start_port.""" port = start_port while is_port_in_use(port, host): port += 1 return port def get_server_status(host, port): """Check if the server is running and get its status.""" try: import requests response = requests.get(f"http://{host}:{port}/health", timeout=2) if response.status_code == 200: return True, response.json() return True, {"status": "running", "details": "Health check failed"} except Exception: return False, None def start_server(args): """Start the mem0 MCP server with the given arguments.""" # Get the directory of this script script_dir = Path(__file__).parent.absolute() # Construct the command to run the server cmd = [sys.executable, os.path.join(script_dir, "server.py")] # Add arguments if args.host: cmd.extend(["--host", args.host]) if args.port: cmd.extend(["--port", str(args.port)]) if args.provider: cmd.extend(["--provider", args.provider]) if args.embedding_provider: cmd.extend(["--embedding-provider", args.embedding_provider]) if args.data_dir: cmd.extend(["--data-dir", args.data_dir]) if args.no_auto_port: cmd.append("--no-auto-port") if args.reload: cmd.append("--reload") if args.debug: cmd.append("--debug") # Start the server if not args.quiet: print(f"{GREEN}Starting mem0 MCP server with command: {' '.join(cmd)}{NC}") # Use subprocess.Popen to start the server process = subprocess.Popen( cmd, stdout=subprocess.PIPE if args.quiet else None, stderr=subprocess.PIPE if args.quiet else None, text=True ) # Wait a moment for the server to start time.sleep(2) # Check if the server started successfully if process.poll() is not None: print(f"{RED}Failed to start mem0 MCP server{NC}") if args.quiet: stdout, stderr = process.communicate() print(f"STDOUT: {stdout}") print(f"STDERR: {stderr}") return None # Return the process return process def output_mcp_info(host, port): """Output MCP server information in the format expected by MCP clients.""" mcp_info = { "name": "mem0", "capabilities": ["memory"], "url": f"http://{host}:{port}", "version": "1.0.0" } print(json.dumps(mcp_info)) def main(): """Main function.""" # Load environment variables from .env file load_dotenv() # Parse command line arguments parser = argparse.ArgumentParser(description="Start the mem0 MCP server") parser.add_argument("--host", help=f"Host to bind the server to (default: 0.0.0.0)") parser.add_argument("--port", type=int, help=f"Port to bind the server to (default: 8000)") parser.add_argument("--provider", help=f"LLM provider to use (default: from .env or ollama)") parser.add_argument("--embedding-provider", help=f"Embedding provider to use (default: from .env or ollama)") parser.add_argument("--data-dir", help=f"Directory to store memory data (default: from .env or ~/mem0_memories)") parser.add_argument("--no-auto-port", action="store_true", help="Disable automatic port finding") parser.add_argument("--reload", action="store_true", help="Enable auto-reload for development") parser.add_argument("--quiet", action="store_true", help="Reduce output verbosity") parser.add_argument("--debug", action="store_true", help="Enable debug mode") args = parser.parse_args() # Set default values from environment variables if not specified if not args.host: args.host = os.environ.get("MEM0_HOST", "0.0.0.0") if not args.port: args.port = int(os.environ.get("MEM0_PORT", 8000)) if not args.provider: args.provider = os.environ.get("MEM0_PROVIDER", "ollama") if not args.embedding_provider: args.embedding_provider = os.environ.get("MEM0_EMBEDDING_PROVIDER", "ollama") if not args.data_dir: args.data_dir = os.environ.get("MEM0_DATA_DIR", "~/mem0_memories") # Expand user directory if needed if args.data_dir: args.data_dir = os.path.expanduser(args.data_dir) # Check if the server is already running if not args.no_auto_port and is_port_in_use(args.port, args.host): if not args.quiet: print(f"{YELLOW}Port {args.port} is already in use{NC}") # Check if it's our server is_running, status = get_server_status(args.host, args.port) if is_running: if not args.quiet: print(f"{GREEN}mem0 MCP server is already running at http://{args.host}:{args.port}{NC}") output_mcp_info(args.host, args.port) return # Find an available port if not args.quiet: print(f"{YELLOW}Finding an available port...{NC}") args.port = find_available_port(args.port, args.host) if not args.quiet: print(f"{GREEN}Using port {args.port}{NC}") # Print banner if not args.quiet: print(BANNER) # Start the server process = start_server(args) if not process: sys.exit(1) # Output MCP info for MCP clients output_mcp_info(args.host, args.port) try: # Keep the script running process.wait() except KeyboardInterrupt: # Handle Ctrl+C if not args.quiet: print(f"{YELLOW}\nShutting down mem0 MCP server...{NC}") process.send_signal(signal.SIGINT) process.wait() if __name__ == "__main__": main()