Major Changes: - Implemented MCP HTTP/SSE transport server for n8n and web clients - Created mcp_server/http_server.py with FastAPI for JSON-RPC 2.0 over HTTP - Added health check endpoint (/health) for container monitoring - Refactored mcp-server/ to mcp_server/ (Python module structure) - Updated Dockerfile.mcp to run HTTP server with health checks MCP Server Features: - 7 memory tools exposed via MCP (add, search, get, update, delete) - HTTP/SSE transport on port 8765 for n8n integration - stdio transport for Claude Code integration - JSON-RPC 2.0 protocol implementation - CORS support for web clients n8n Integration: - Successfully tested with AI Agent workflows - MCP Client Tool configuration documented - Working webhook endpoint tested and verified - System prompt optimized for automatic user_id usage Documentation: - Created comprehensive Mintlify documentation site - Added docs/mcp/introduction.mdx - MCP server overview - Added docs/mcp/installation.mdx - Installation guide - Added docs/mcp/tools.mdx - Complete tool reference - Added docs/examples/n8n.mdx - n8n integration guide - Added docs/examples/claude-code.mdx - Claude Code setup - Updated README.md with MCP HTTP server info - Updated roadmap to mark Phase 1 as complete Bug Fixes: - Fixed synchronized delete operations across Supabase and Neo4j - Updated memory_service.py with proper error handling - Fixed Neo4j connection issues in delete operations Configuration: - Added MCP_HOST and MCP_PORT environment variables - Updated .env.example with MCP server configuration - Updated docker-compose.yml with MCP container health checks Testing: - Added test scripts for MCP HTTP endpoint verification - Created test workflows in n8n - Verified all 7 memory tools working correctly - Tested synchronized operations across both stores Version: 1.0.0 Status: Phase 1 Complete - Production Ready 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
5.3 KiB
Memory Store Synchronization Fix
Date: 2025-10-15 Issue: Neo4j graph store not cleaned when deleting memories from Supabase
Problem
User reported: "I can see a lot of nodes in neo4j but only one memory in supabase"
Root Cause
mem0ai v0.1.118's delete_all() and _delete_memory() methods only clean up the vector store (Supabase) but NOT the graph store (Neo4j). This is a design limitation in the mem0 library.
Evidence from mem0 source code (mem0/memory/main.py):
def _delete_memory(self, memory_id):
logger.info(f"Deleting memory with {memory_id=}")
existing_memory = self.vector_store.get(vector_id=memory_id)
prev_value = existing_memory.payload["data"]
self.vector_store.delete(vector_id=memory_id) # ✓ Deletes from Supabase
self.db.add_history(...) # ✓ Updates history
# ✗ Does NOT delete from self.graph (Neo4j)
return memory_id
Solution
Created memory_cleanup.py utility that ensures synchronized deletion across both stores:
Implementation
File: /home/klas/mem0/memory_cleanup.py
class MemoryCleanup:
"""Utilities for cleaning up memories across both vector and graph stores"""
def delete_all_synchronized(
self,
user_id: Optional[str] = None,
agent_id: Optional[str] = None,
run_id: Optional[str] = None
) -> dict:
"""
Delete all memories from BOTH Supabase and Neo4j
Steps:
1. Delete from Supabase using mem0's delete_all()
2. Delete matching nodes from Neo4j using Cypher queries
Returns deletion statistics for both stores.
"""
Integration
REST API (api/memory_service.py):
- Added
MemoryCleanuptoMemoryService.__init__ - Updated
delete_all_memories()to usecleanup.delete_all_synchronized()
MCP Server (mcp_server/tools.py):
- Added
MemoryCleanuptoMemoryTools.__init__ - Updated
handle_delete_all_memories()to usecleanup.delete_all_synchronized()
Testing
Before Fix
Supabase (Vector Store): 0 memories
Neo4j (Graph Store): 27 nodes, 18 relationships
⚠️ WARNING: Inconsistency detected!
→ Supabase has 0 memories but Neo4j has nodes
→ This suggests orphaned graph data
After Fix
[2/5] Checking stores BEFORE deletion...
Supabase: 2 memories
Neo4j: 3 nodes
[3/5] Performing synchronized deletion...
✓ Deletion result:
Supabase: ✓
Neo4j: 3 nodes deleted
[4/5] Checking stores AFTER deletion...
Supabase: 0 memories
Neo4j: 0 nodes
✅ SUCCESS: Both stores are empty - synchronized deletion works!
Cleanup Utilities
For Development
cleanup-neo4j.py - Remove all orphaned Neo4j data:
NEO4J_URI="neo4j://172.21.0.10:7687" python3 cleanup-neo4j.py
check-store-sync.py - Check synchronization status:
NEO4J_URI="neo4j://172.21.0.10:7687" python3 check-store-sync.py
test-synchronized-delete.py - Test synchronized deletion:
NEO4J_URI="neo4j://172.21.0.10:7687" python3 test-synchronized-delete.py
API Impact
REST API
Before: DELETE /v1/memories/user/{user_id} only cleaned Supabase
After: DELETE /v1/memories/user/{user_id} cleans both Supabase AND Neo4j
MCP Server
Before: delete_all_memories tool only cleaned Supabase
After: delete_all_memories tool cleans both Supabase AND Neo4j
Tool response now includes:
All memories deleted for user_id=test_user.
Supabase: ✓, Neo4j: 3 nodes deleted
Implementation Details
Cypher Queries Used
Delete by user_id:
MATCH (n {user_id: $user_id})
DETACH DELETE n
RETURN count(n) as deleted
Delete by agent_id:
MATCH (n {agent_id: $agent_id})
DETACH DELETE n
RETURN count(n) as deleted
Delete all nodes (when no filter specified):
MATCH ()-[r]->() DELETE r; -- Delete relationships first
MATCH (n) DELETE n; -- Then delete nodes
Files Modified
memory_cleanup.py- New utility module for synchronized cleanupapi/memory_service.py- Integrated cleanup in REST APImcp_server/tools.py- Integrated cleanup in MCP server
Files Created
cleanup-neo4j.py- Manual Neo4j cleanup scriptcheck-store-sync.py- Store synchronization checkertest-synchronized-delete.py- Automated test for synchronized deletionSYNC_FIX_SUMMARY.md- This documentation
Deployment Status
✅ Code updated in local development environment ⚠️ Docker containers need to be rebuilt with updated code
To Deploy
# Rebuild containers
docker compose build api mcp-server
# Restart with new code
docker compose down
docker compose up -d
Future Considerations
This is a workaround for a limitation in mem0ai v0.1.118. Future options:
- Upstream fix: Report issue to mem0ai project and request graph store cleanup in delete methods
- Override delete methods: Extend mem0.Memory class and override delete methods
- Continue using wrapper: Current solution is clean and maintainable
Conclusion
✅ Synchronization issue resolved ✅ Both stores now cleaned properly when deleting memories ✅ Comprehensive testing utilities created ✅ Documentation complete
The fix ensures data consistency between Supabase (vector embeddings) and Neo4j (knowledge graph) when deleting memories.