Feature (OpenMemory): Add support for LLM and Embedding Providers in OpenMemory (#2794)

This commit is contained in:
Saket Aryan
2025-05-25 13:31:23 +05:30
committed by GitHub
parent b339cab3c1
commit 5c6fbcaab0
20 changed files with 1586 additions and 123 deletions

View File

@@ -1,3 +1,20 @@
"""
MCP Server for OpenMemory with resilient memory client handling.
This module implements an MCP (Model Context Protocol) server that provides
memory operations for OpenMemory. The memory client is initialized lazily
to prevent server crashes when external dependencies (like Ollama) are
unavailable. If the memory client cannot be initialized, the server will
continue running with limited functionality and appropriate error messages.
Key features:
- Lazy memory client initialization
- Graceful error handling for unavailable dependencies
- Fallback to database-only mode when vector store is unavailable
- Proper logging for debugging connection issues
- Environment variable parsing for API keys
"""
import logging
import json
from mcp.server.fastmcp import FastMCP
@@ -19,14 +36,17 @@ from qdrant_client import models as qdrant_models
# Load environment variables
load_dotenv()
# Initialize MCP and memory client
# Initialize MCP
mcp = FastMCP("mem0-mcp-server")
# Check if OpenAI API key is set
if not os.getenv("OPENAI_API_KEY"):
raise Exception("OPENAI_API_KEY is not set in .env file")
memory_client = get_memory_client()
# Don't initialize memory client at import time - do it lazily when needed
def get_memory_client_safe():
"""Get memory client with error handling. Returns None if client cannot be initialized."""
try:
return get_memory_client()
except Exception as e:
logging.warning(f"Failed to get memory client: {e}")
return None
# Context variables for user_id and client_name
user_id_var: contextvars.ContextVar[str] = contextvars.ContextVar("user_id")
@@ -48,6 +68,11 @@ async def add_memories(text: str) -> str:
if not client_name:
return "Error: client_name not provided"
# Get memory client safely
memory_client = get_memory_client_safe()
if not memory_client:
return "Error: Memory system is currently unavailable. Please try again later."
try:
db = SessionLocal()
try:
@@ -113,6 +138,7 @@ async def add_memories(text: str) -> str:
finally:
db.close()
except Exception as e:
logging.exception(f"Error adding to memory: {e}")
return f"Error adding to memory: {e}"
@@ -124,6 +150,12 @@ async def search_memory(query: str) -> str:
return "Error: user_id not provided"
if not client_name:
return "Error: client_name not provided"
# Get memory client safely
memory_client = get_memory_client_safe()
if not memory_client:
return "Error: Memory system is currently unavailable. Please try again later."
try:
db = SessionLocal()
try:
@@ -216,6 +248,12 @@ async def list_memories() -> str:
return "Error: user_id not provided"
if not client_name:
return "Error: client_name not provided"
# Get memory client safely
memory_client = get_memory_client_safe()
if not memory_client:
return "Error: Memory system is currently unavailable. Please try again later."
try:
db = SessionLocal()
try:
@@ -267,6 +305,7 @@ async def list_memories() -> str:
finally:
db.close()
except Exception as e:
logging.exception(f"Error getting memories: {e}")
return f"Error getting memories: {e}"
@@ -278,6 +317,12 @@ async def delete_all_memories() -> str:
return "Error: user_id not provided"
if not client_name:
return "Error: client_name not provided"
# Get memory client safely
memory_client = get_memory_client_safe()
if not memory_client:
return "Error: Memory system is currently unavailable. Please try again later."
try:
db = SessionLocal()
try:
@@ -289,7 +334,10 @@ async def delete_all_memories() -> str:
# delete the accessible memories only
for memory_id in accessible_memory_ids:
memory_client.delete(memory_id)
try:
memory_client.delete(memory_id)
except Exception as delete_error:
logging.warning(f"Failed to delete memory {memory_id} from vector store: {delete_error}")
# Update each memory's state and create history entries
now = datetime.datetime.now(datetime.UTC)
@@ -322,6 +370,7 @@ async def delete_all_memories() -> str:
finally:
db.close()
except Exception as e:
logging.exception(f"Error deleting memories: {e}")
return f"Error deleting memories: {e}"