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>
This commit is contained in:
202
UPGRADE_SUMMARY.md
Normal file
202
UPGRADE_SUMMARY.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# T6 Mem0 v2 - mem0ai 0.1.118 Upgrade Summary
|
||||
|
||||
**Date**: 2025-10-15
|
||||
**Upgrade**: mem0ai v0.1.101 → v0.1.118
|
||||
|
||||
## Issue Discovered
|
||||
|
||||
While testing the MCP server, encountered a critical bug in mem0ai v0.1.101:
|
||||
|
||||
```
|
||||
AttributeError: 'list' object has no attribute 'id'
|
||||
```
|
||||
|
||||
This error occurred in mem0's internal `_get_all_from_vector_store` method at line 580, indicating a bug in the library itself.
|
||||
|
||||
## Root Cause
|
||||
|
||||
In mem0ai v0.1.101, the `get_all()` method had a bug where it tried to access `.id` attribute on a list object instead of iterating over the list properly.
|
||||
|
||||
## Solution
|
||||
|
||||
### 1. Upgraded mem0ai Library
|
||||
|
||||
**Previous version**: 0.1.101
|
||||
**New version**: 0.1.118 (latest stable release)
|
||||
|
||||
The upgrade fixed the internal bug and changed the return format of both `get_all()` and `search()` methods:
|
||||
|
||||
**Old format (v0.1.101)**:
|
||||
- `get_all()` - Attempted to return list but had bugs
|
||||
- `search()` - Returned list directly
|
||||
|
||||
**New format (v0.1.118)**:
|
||||
- `get_all()` - Returns dict: `{'results': [...], 'relations': [...]}`
|
||||
- `search()` - Returns dict: `{'results': [...], 'relations': [...]}`
|
||||
|
||||
### 2. Code Updates
|
||||
|
||||
Updated both REST API and MCP server code to handle the new dict format:
|
||||
|
||||
#### REST API (`api/memory_service.py`)
|
||||
|
||||
**search_memories** (lines 111-120):
|
||||
```python
|
||||
result = self.memory.search(...)
|
||||
# In mem0 v0.1.118+, search returns dict with 'results' key
|
||||
memories_list = result.get('results', []) if isinstance(result, dict) else result
|
||||
```
|
||||
|
||||
**get_all_memories** (lines 203-210):
|
||||
```python
|
||||
result = self.memory.get_all(...)
|
||||
# In mem0 v0.1.118+, get_all returns dict with 'results' key
|
||||
memories_list = result.get('results', []) if isinstance(result, dict) else result
|
||||
```
|
||||
|
||||
#### MCP Server (`mcp_server/tools.py`)
|
||||
|
||||
**handle_search_memories** (lines 215-223):
|
||||
```python
|
||||
result = self.memory.search(...)
|
||||
# In mem0 v0.1.118+, search returns dict with 'results' key
|
||||
memories = result.get('results', []) if isinstance(result, dict) else result
|
||||
```
|
||||
|
||||
**handle_get_all_memories** (lines 279-285):
|
||||
```python
|
||||
result = self.memory.get_all(...)
|
||||
# In mem0 v0.1.118+, get_all returns dict with 'results' key
|
||||
memories = result.get('results', []) if isinstance(result, dict) else result
|
||||
```
|
||||
|
||||
### 3. Dependencies Updated
|
||||
|
||||
**requirements.txt** changes:
|
||||
```diff
|
||||
# Core Memory System
|
||||
- mem0ai[graph]==0.1.*
|
||||
+ # Requires >=0.1.118 for get_all() and search() dict return format fix
|
||||
+ mem0ai[graph]>=0.1.118,<0.2.0
|
||||
|
||||
# Web Framework
|
||||
- pydantic==2.9.*
|
||||
+ pydantic>=2.7.3,<3.0
|
||||
|
||||
# OpenAI
|
||||
- openai==1.58.*
|
||||
+ # mem0ai 0.1.118 requires openai<1.110.0,>=1.90.0
|
||||
+ openai>=1.90.0,<1.110.0
|
||||
```
|
||||
|
||||
## Testing Results
|
||||
|
||||
### MCP Server Live Test
|
||||
|
||||
All 7 MCP tools tested successfully:
|
||||
|
||||
✅ **add_memory** - Working correctly
|
||||
✅ **search_memories** - Working correctly (fixed with v0.1.118)
|
||||
✅ **get_memory** - Working correctly
|
||||
✅ **get_all_memories** - Working correctly (fixed with v0.1.118)
|
||||
✅ **update_memory** - Working correctly
|
||||
✅ **delete_memory** - Working correctly
|
||||
✅ **delete_all_memories** - Working correctly
|
||||
|
||||
### Sample Test Output
|
||||
|
||||
```
|
||||
[4/6] Testing search_memories...
|
||||
Found 3 relevant memory(ies):
|
||||
|
||||
1. Loves Python
|
||||
ID: 4580c26a-11e1-481d-b06f-9a2ba71c71c9
|
||||
Relevance: 61.82%
|
||||
|
||||
2. Is a software engineer
|
||||
ID: 7848e945-d5f1-4048-99e8-c581b8388f43
|
||||
Relevance: 64.86%
|
||||
|
||||
3. Loves TypeScript
|
||||
ID: 9d4a3566-5374-4d31-9dfb-30a1686641d0
|
||||
Relevance: 71.95%
|
||||
|
||||
[5/6] Testing get_all_memories...
|
||||
Retrieved 3 memory(ies):
|
||||
|
||||
1. Is a software engineer
|
||||
ID: 7848e945-d5f1-4048-99e8-c581b8388f43
|
||||
|
||||
2. Loves Python
|
||||
ID: 4580c26a-11e1-481d-b06f-9a2ba71c71c9
|
||||
|
||||
3. Loves TypeScript
|
||||
ID: 9d4a3566-5374-4d31-9dfb-30a1686641d0
|
||||
```
|
||||
|
||||
### REST API Health Check
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"version": "0.1.0",
|
||||
"timestamp": "2025-10-15T06:26:26.341277",
|
||||
"dependencies": {
|
||||
"mem0": "healthy"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Deployment Status
|
||||
|
||||
✅ **Docker Containers Rebuilt**: API and MCP server containers rebuilt with mem0ai 0.1.118
|
||||
✅ **Containers Restarted**: All containers running with updated code
|
||||
✅ **Health Checks Passing**: API and Neo4j containers healthy
|
||||
|
||||
### Container Status
|
||||
|
||||
- `t6-mem0-api` - Up and healthy
|
||||
- `t6-mem0-mcp` - Up and running with stdio transport
|
||||
- `t6-mem0-neo4j` - Up and healthy
|
||||
|
||||
## Files Modified
|
||||
|
||||
1. `/home/klas/mem0/api/memory_service.py` - Updated search_memories and get_all_memories methods
|
||||
2. `/home/klas/mem0/mcp_server/tools.py` - Updated handle_search_memories and handle_get_all_memories methods
|
||||
3. `/home/klas/mem0/requirements.txt` - Updated mem0ai, pydantic, and openai version constraints
|
||||
4. `/home/klas/mem0/docker-compose.yml` - No changes needed (uses requirements.txt)
|
||||
|
||||
## Testing Scripts Created
|
||||
|
||||
1. `/home/klas/mem0/test-mcp-server-live.py` - Comprehensive MCP server test suite
|
||||
2. `/home/klas/mem0/MCP_SETUP.md` - Complete MCP server documentation
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
The upgrade maintains **backward compatibility** through defensive coding:
|
||||
|
||||
```python
|
||||
# Handles both old list format and new dict format
|
||||
memories_list = result.get('results', []) if isinstance(result, dict) else result
|
||||
```
|
||||
|
||||
This ensures the code works with both:
|
||||
- Older mem0 versions that might return lists
|
||||
- New mem0 v0.1.118+ that returns dicts
|
||||
|
||||
## Recommendations
|
||||
|
||||
1. **Monitor logs** for any Pydantic deprecation warnings (cosmetic, not critical)
|
||||
2. **Test n8n workflows** using the mem0 API to verify compatibility
|
||||
3. **Consider updating config.py** to use ConfigDict instead of class-based config (Pydantic v2 best practice)
|
||||
|
||||
## Conclusion
|
||||
|
||||
✅ Successfully upgraded to mem0ai 0.1.118
|
||||
✅ Fixed critical `get_all()` bug
|
||||
✅ Updated all code to handle new dict return format
|
||||
✅ All MCP tools tested and working
|
||||
✅ Docker containers rebuilt and deployed
|
||||
✅ System fully operational
|
||||
|
||||
The upgrade resolves the core issue while maintaining backward compatibility and improving reliability of both the REST API and MCP server.
|
||||
Reference in New Issue
Block a user