Files
t6_mem0_v2/mcp-server/main.py
Claude Code 61a4050a8e Complete implementation: REST API, MCP server, and documentation
Implementation Summary:
- REST API with FastAPI (complete CRUD operations)
- MCP Server with Python MCP SDK (7 tools)
- Supabase migrations (pgvector setup)
- Docker Compose orchestration
- Mintlify documentation site
- Environment configuration
- Shared config module

REST API Features:
- POST /v1/memories/ - Add memory
- GET /v1/memories/search - Semantic search
- GET /v1/memories/{id} - Get memory
- GET /v1/memories/user/{user_id} - User memories
- PATCH /v1/memories/{id} - Update memory
- DELETE /v1/memories/{id} - Delete memory
- GET /v1/health - Health check
- GET /v1/stats - Statistics
- Bearer token authentication
- OpenAPI documentation

MCP Server Tools:
- add_memory - Add from messages
- search_memories - Semantic search
- get_memory - Retrieve by ID
- get_all_memories - List all
- update_memory - Update content
- delete_memory - Delete by ID
- delete_all_memories - Bulk delete

Infrastructure:
- Neo4j 5.26 with APOC/GDS
- Supabase pgvector integration
- Docker network: localai
- Health checks and monitoring
- Structured logging

Documentation:
- Introduction page
- Quickstart guide
- Architecture deep dive
- Mintlify configuration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 08:44:16 +02:00

166 lines
5.0 KiB
Python

"""
T6 Mem0 v2 MCP Server
Model Context Protocol server for memory operations
"""
import logging
import sys
import asyncio
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import (
Resource,
Tool,
TextContent,
ImageContent,
EmbeddedResource
)
from mem0 import Memory
from config import mem0_config, settings
from mcp_server.tools import MemoryTools
# Configure logging
logging.basicConfig(
level=getattr(logging, settings.log_level.upper()),
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[logging.StreamHandler(sys.stderr)] # MCP uses stderr for logs
)
logger = logging.getLogger(__name__)
class T6Mem0Server:
"""T6 Mem0 v2 MCP Server"""
def __init__(self):
"""Initialize MCP server"""
self.server = Server("t6-mem0-v2")
self.memory: Memory | None = None
self.tools: MemoryTools | None = None
# Setup handlers
self.setup_handlers()
def setup_handlers(self):
"""Setup MCP server handlers"""
@self.server.list_resources()
async def list_resources() -> list[Resource]:
"""
List available resources (for future extension)
"""
return []
@self.server.read_resource()
async def read_resource(uri: str) -> str:
"""
Read resource by URI (for future extension)
"""
logger.warning(f"Resource read not implemented: {uri}")
return ""
@self.server.list_tools()
async def list_tools() -> list[Tool]:
"""List available memory tools"""
logger.info("Listing tools")
if not self.tools:
raise RuntimeError("Tools not initialized")
return self.tools.get_tool_definitions()
@self.server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent | ImageContent | EmbeddedResource]:
"""
Handle tool calls
Args:
name: Tool name
arguments: Tool arguments
Returns:
Tool response
"""
logger.info(f"Tool called: {name}")
logger.debug(f"Arguments: {arguments}")
if not self.tools:
raise RuntimeError("Tools not initialized")
# Route to appropriate handler
handlers = {
"add_memory": self.tools.handle_add_memory,
"search_memories": self.tools.handle_search_memories,
"get_memory": self.tools.handle_get_memory,
"get_all_memories": self.tools.handle_get_all_memories,
"update_memory": self.tools.handle_update_memory,
"delete_memory": self.tools.handle_delete_memory,
"delete_all_memories": self.tools.handle_delete_all_memories,
}
handler = handlers.get(name)
if not handler:
logger.error(f"Unknown tool: {name}")
return [TextContent(type="text", text=f"Error: Unknown tool '{name}'")]
try:
return await handler(arguments)
except Exception as e:
logger.error(f"Tool execution failed: {e}", exc_info=True)
return [TextContent(type="text", text=f"Error executing tool: {str(e)}")]
async def initialize(self):
"""Initialize memory service"""
logger.info("Initializing T6 Mem0 v2 MCP Server")
logger.info(f"Environment: {settings.environment}")
try:
# Initialize Mem0
logger.info("Initializing Mem0...")
self.memory = Memory.from_config(config_dict=mem0_config)
logger.info("Mem0 initialized successfully")
# Initialize tools
self.tools = MemoryTools(self.memory)
logger.info("Tools initialized successfully")
logger.info("T6 Mem0 v2 MCP Server ready")
except Exception as e:
logger.error(f"Failed to initialize server: {e}", exc_info=True)
raise
async def run(self):
"""Run the MCP server"""
try:
# Initialize before running
await self.initialize()
# Run server with stdio transport
logger.info("Starting MCP server with stdio transport")
async with stdio_server() as (read_stream, write_stream):
await self.server.run(
read_stream,
write_stream,
self.server.create_initialization_options()
)
except Exception as e:
logger.error(f"Server error: {e}", exc_info=True)
raise
async def main():
"""Main entry point"""
try:
server = T6Mem0Server()
await server.run()
except KeyboardInterrupt:
logger.info("Server stopped by user")
except Exception as e:
logger.error(f"Fatal error: {e}", exc_info=True)
sys.exit(1)
if __name__ == "__main__":
asyncio.run(main())