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()