Feature (OpenMemory): Add support for LLM and Embedding Providers in OpenMemory (#2794)
This commit is contained in:
@@ -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}"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user