OpenMemory MCP Server Validation Error Fix
Executive Summary
The OpenMemory MCP server contains a critical bug in the add_memories function that causes Pydantic validation errors when used with Claude Desktop via Supergateway. The function returns a Python dictionary object instead of a string, violating the MCP protocol specification and causing tool execution failures.
Problem Description
Error Symptoms
- Users experience validation errors when using OpenMemory MCP tools in Claude Desktop
- Error message:
Error executing tool add_memories: 1 validation error for add_memoriesOutput result Input should be a valid string [type=string_type, input_value={'results': [{'id': '549e...', 'event': 'ADD'}]}, input_type=dict]
- Memory data is successfully stored but tool appears to fail due to response format mismatch
Technical Root Cause
- File:
/usr/src/openmemory/app/mcp_server.py
- Function:
add_memories (line ~137)
- Issue: Function returns raw dictionary object instead of string-serialized response
- MCP protocol expects string return type for tool responses, not complex objects
Architecture Context
Claude Desktop → Supergateway → OpenMemory MCP Server → Memory Client
↑
Protocol validation error occurs here
Current Problematic Code
Location
- File:
/usr/src/openmemory/app/mcp_server.py
- Function:
add_memories
- Line: Approximately 137
Current Implementation
@mcp.tool(description="Add a new memory...")
async def add_memories(text: str) -> str:
# ... processing logic ...
response = memory_client.add(text,
user_id=uid,
metadata={
"source_app": "openmemory",
"mcp_client": client_name,
})
# Process response and update database
if isinstance(response, dict) and 'results' in response:
# ... database operations ...
return response # ← PROBLEM: Returns dict instead of string
Response Object Structure
The memory_client.add() method returns a dictionary with this structure:
{
"results": [
{
"id": "549e4d2a-8b2f-4c7e-9a1d-3f5b8c2e4a7d",
"memory": "User's memory text content",
"event": "ADD"
}
]
}
Solution Implementation
Required Change
Replace the return statement in the add_memories function to serialize the response as a JSON string.
Updated Code
@mcp.tool(description="Add a new memory...")
async def add_memories(text: str) -> str:
# ... existing processing logic remains unchanged ...
response = memory_client.add(text,
user_id=uid,
metadata={
"source_app": "openmemory",
"mcp_client": client_name,
})
# Process response and update database
if isinstance(response, dict) and 'results' in response:
# ... existing database operations remain unchanged ...
# Convert response dict to string for MCP protocol compatibility
if isinstance(response, dict):
return json.dumps(response)
return str(response)
Import Requirements
Ensure the json module is imported at the top of the file:
(Note: This import already exists in the current file)
Implementation Steps
Step 1: Locate the File
# In the OpenMemory repository root
ls app/mcp_server.py
Step 2: Identify the Function
Search for the add_memories function:
grep -n "async def add_memories" app/mcp_server.py
Step 3: Find the Return Statement
Look for line containing return response within the add_memories function (approximately line 137).
Step 4: Apply the Fix
Replace:
With:
# Convert response dict to string for MCP protocol compatibility
if isinstance(response, dict):
return json.dumps(response)
return str(response)
Step 5: Verify JSON Import
Confirm import json exists at the top of the file (it should already be present).
Testing Instructions
Unit Test Case
import json
import pytest
from unittest.mock import AsyncMock, MagicMock
async def test_add_memories_returns_string():
"""Test that add_memories returns a JSON string, not a dict."""
# Mock the memory client response
mock_response = {
"results": [
{
"id": "test-id-123",
"memory": "Test memory content",
"event": "ADD"
}
]
}
# Mock dependencies
mock_memory_client = MagicMock()
mock_memory_client.add.return_value = mock_response
# Call the function (assuming proper mocking of context vars and DB)
result = await add_memories("Test memory text")
# Verify result is a string
assert isinstance(result, str)
# Verify result can be parsed as JSON
parsed = json.loads(result)
assert parsed == mock_response
# Verify structure
assert "results" in parsed
assert len(parsed["results"]) == 1
assert parsed["results"][0]["event"] == "ADD"
Integration Test
- Deploy the fix to a test environment
- Configure Claude Desktop with OpenMemory MCP via Supergateway
- Execute
add_memories tool through Claude Desktop
- Verify no validation errors occur
- Confirm memory is successfully stored in the database
Docker Testing
If testing with Docker:
# Build image with fix
docker build -t openmemory-fixed .
# Run with proper port mapping
docker run -p 8765:8765 openmemory-fixed
# Test endpoint
curl -X GET "http://localhost:8765/mcp/claude/sse/testuser"
Validation Checklist
Impact Assessment
Positive Impact
- ✅ Fixes validation errors in Claude Desktop
- ✅ Maintains backward compatibility
- ✅ Improves MCP protocol compliance
- ✅ No functional changes to memory storage
- ✅ Minimal code change with low risk
Potential Risks
- ⚠️ Clients expecting raw dict objects may need updates (unlikely as MCP specifies string responses)
- ⚠️ JSON serialization adds minimal computational overhead
- ⚠️ Requires testing across all MCP client implementations
Breaking Changes
- None - this is a bug fix that makes the implementation compliant with the MCP specification
Repository Information
Target Repository
- GitHub:
https://github.com/mem0ai/mem0
- Directory:
openmemory/app/
- File:
mcp_server.py
Suggested Pull Request
- Title: "Fix MCP protocol compliance: Return JSON string from add_memories tool"
- Branch:
fix/mcp-response-format
- Labels:
bug, mcp, protocol-compliance
Commit Message Template
fix(mcp): return JSON string from add_memories tool
- Convert dict response to JSON string for MCP protocol compliance
- Fixes Pydantic validation error in Claude Desktop integration
- Maintains all existing functionality and error handling
- Addresses issue where tool responses violated MCP string requirement
Closes #[ISSUE_NUMBER]
Additional Notes
MCP Protocol Reference
According to the Model Context Protocol specification, tool responses should return string values. Complex objects should be JSON-serialized when returned from MCP tools.
Alternative Solutions Considered
- Modify Supergateway: Would require changes to external dependency
- Change MCP Client: Would affect all users, not just this tool
- Update Protocol Specification: Not practical for this specific case
The chosen solution (JSON serialization) is the most appropriate as it:
- Fixes the immediate problem
- Maintains compatibility
- Follows MCP best practices
- Requires minimal code changes
Future Improvements
Consider implementing similar fixes for other tools in the MCP server that may have the same issue:
search_memory function
list_memories function (if it exists)
- Any other tools returning complex objects
Contact Information
This fix was identified and tested by analyzing the integration between:
- OpenMemory MCP Server v[current]
- Supergateway v3.4.0
- Claude Desktop on macOS
- Docker containers:
mem0/openmemory-mcp
OpenMemory MCP Server Validation Error Fix
Executive Summary
The OpenMemory MCP server contains a critical bug in the
add_memoriesfunction that causes Pydantic validation errors when used with Claude Desktop via Supergateway. The function returns a Python dictionary object instead of a string, violating the MCP protocol specification and causing tool execution failures.Problem Description
Error Symptoms
Error executing tool add_memories: 1 validation error for add_memoriesOutput result Input should be a valid string [type=string_type, input_value={'results': [{'id': '549e...', 'event': 'ADD'}]}, input_type=dict]Technical Root Cause
/usr/src/openmemory/app/mcp_server.pyadd_memories(line ~137)Architecture Context
Current Problematic Code
Location
/usr/src/openmemory/app/mcp_server.pyadd_memoriesCurrent Implementation
Response Object Structure
The
memory_client.add()method returns a dictionary with this structure:{ "results": [ { "id": "549e4d2a-8b2f-4c7e-9a1d-3f5b8c2e4a7d", "memory": "User's memory text content", "event": "ADD" } ] }Solution Implementation
Required Change
Replace the return statement in the
add_memoriesfunction to serialize the response as a JSON string.Updated Code
Import Requirements
Ensure the
jsonmodule is imported at the top of the file:(Note: This import already exists in the current file)
Implementation Steps
Step 1: Locate the File
# In the OpenMemory repository root ls app/mcp_server.pyStep 2: Identify the Function
Search for the
add_memoriesfunction:grep -n "async def add_memories" app/mcp_server.pyStep 3: Find the Return Statement
Look for line containing
return responsewithin theadd_memoriesfunction (approximately line 137).Step 4: Apply the Fix
Replace:
With:
Step 5: Verify JSON Import
Confirm
import jsonexists at the top of the file (it should already be present).Testing Instructions
Unit Test Case
Integration Test
add_memoriestool through Claude DesktopDocker Testing
If testing with Docker:
Validation Checklist
jsonmodule is importedadd_memoriesfunction signature unchanged:async def add_memories(text: str) -> strImpact Assessment
Positive Impact
Potential Risks
Breaking Changes
Repository Information
Target Repository
https://github.com/mem0ai/mem0openmemory/app/mcp_server.pySuggested Pull Request
fix/mcp-response-formatbug,mcp,protocol-complianceCommit Message Template
Additional Notes
MCP Protocol Reference
According to the Model Context Protocol specification, tool responses should return string values. Complex objects should be JSON-serialized when returned from MCP tools.
Alternative Solutions Considered
The chosen solution (JSON serialization) is the most appropriate as it:
Future Improvements
Consider implementing similar fixes for other tools in the MCP server that may have the same issue:
search_memoryfunctionlist_memoriesfunction (if it exists)Contact Information
This fix was identified and tested by analyzing the integration between:
mem0/openmemory-mcp