Files
t6_mem0_v2/SYNC_FIX_SUMMARY.md
Claude Code 1998bef6f4 Add MCP HTTP/SSE server and complete n8n integration
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>
2025-10-15 13:56:41 +02:00

204 lines
5.3 KiB
Markdown

# 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`):
```python
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`
```python
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 `MemoryCleanup` to `MemoryService.__init__`
- Updated `delete_all_memories()` to use `cleanup.delete_all_synchronized()`
**MCP Server** (`mcp_server/tools.py`):
- Added `MemoryCleanup` to `MemoryTools.__init__`
- Updated `handle_delete_all_memories()` to use `cleanup.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:
```bash
NEO4J_URI="neo4j://172.21.0.10:7687" python3 cleanup-neo4j.py
```
**`check-store-sync.py`** - Check synchronization status:
```bash
NEO4J_URI="neo4j://172.21.0.10:7687" python3 check-store-sync.py
```
**`test-synchronized-delete.py`** - Test synchronized deletion:
```bash
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**:
```cypher
MATCH (n {user_id: $user_id})
DETACH DELETE n
RETURN count(n) as deleted
```
**Delete by agent_id**:
```cypher
MATCH (n {agent_id: $agent_id})
DETACH DELETE n
RETURN count(n) as deleted
```
**Delete all nodes** (when no filter specified):
```cypher
MATCH ()-[r]->() DELETE r; -- Delete relationships first
MATCH (n) DELETE n; -- Then delete nodes
```
## Files Modified
1. **`memory_cleanup.py`** - New utility module for synchronized cleanup
2. **`api/memory_service.py`** - Integrated cleanup in REST API
3. **`mcp_server/tools.py`** - Integrated cleanup in MCP server
## Files Created
1. **`cleanup-neo4j.py`** - Manual Neo4j cleanup script
2. **`check-store-sync.py`** - Store synchronization checker
3. **`test-synchronized-delete.py`** - Automated test for synchronized deletion
4. **`SYNC_FIX_SUMMARY.md`** - This documentation
## Deployment Status
✅ Code updated in local development environment
⚠️ Docker containers need to be rebuilt with updated code
### To Deploy
```bash
# 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:
1. **Upstream fix**: Report issue to mem0ai project and request graph store cleanup in delete methods
2. **Override delete methods**: Extend mem0.Memory class and override delete methods
3. **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.