-
-
Notifications
You must be signed in to change notification settings - Fork 108
Development Journey & Real‐World Examples
A collection of real conversations and debugging sessions that shaped the MCP Memory Server project
- Introduction
- The Architecture Pivot
- The Tool Registration Breakthrough
- The "Never Executes" Debugging Marathon
- The Lazy Loading Discovery
- Project Completion & Success Metrics
- Key Learnings & Best Practices
This page documents the real development journey of the MCP Memory Server through actual conversations and debugging sessions. These examples showcase not just the final solution, but the problem-solving process, architectural decisions, and breakthrough moments that shaped the project.
Whether you're troubleshooting an issue, understanding our design decisions, or learning from our experiences, these real-world examples provide valuable insights into building MCP-based applications.
January 2025 - How we discovered and fixed a fundamental design flaw
Our dashboard initially assumed it needed Claude Desktop to access MCP tools via the window interface. This seemed logical but severely limited the memory service's broader usability.
CONTEXT:
Initial approach assumed Claude Desktop dependency for accessing MCP tools
via window interface. Discussion revealed this limited the memory service's
broader usability.
CRITICAL INSIGHTS:
1. MCP Memory Service Design Intent:
- Should be usable outside Claude Desktop
- Follows MCP protocol using stdin/stdout
- Independent of specific client implementation
We pivoted to a two-process architecture:
- Memory service process: Handles all memory operations
- Dashboard client process: Standalone React application
- Communication: Standard MCP protocol via stdin/stdout
- ✅ Broader compatibility with any MCP client
- ✅ Clean separation of concerns
- ✅ Standard protocol compliance
- ✅ No vendor lock-in
Lesson Learned: Always design for the broadest possible use case. Don't assume a specific client implementation.
The moment when tools finally appeared in the MCP server
Despite successful server startup, no tools were visible to clients. The server would initialize, but Claude couldn't see any of the memory management tools.
# What we had (not working):
class MemoryServer:
def __init__(self):
self.tools = [...] # Tools defined but not registered
# What fixed it:
@server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="store_memory",
description="Store new information with optional tags",
inputSchema={
"type": "object",
"properties": {
"content": {
"type": "string",
"description": "The memory content to store"
},
"metadata": {
"type": "object",
"properties": {
"tags": {"type": "array", "items": {"type": "string"}}
}
}
},
"required": ["content"]
}
),
# ... other tools
]
- Proper tool registration using
@server.list_tools()
decorator - Detailed JSON Schema input definitions for each tool
- Implementation of
handle_call_tool
for request processing - Correct server initialization with capabilities
Lesson Learned: MCP protocol requires explicit tool registration. Simply defining tools isn't enough - they must be properly exposed through the protocol.
June 2025 - When tool calls were received but never executed
Tool calls were being sent and received by the server, but the handle_call_tool
function never executed. This was particularly frustrating because everything seemed correct on the surface.
**Working Components:**
- MCP protocol handshake ✅
- Handler registration ✅
- Server ready state ✅
- Tool capability declaration ✅
**Failing Component:**
- Tool call message routing from MCP framework to decorated handler ❌
We created three test implementations to isolate the issue:
-
minimal_uv_server.py
- Baseline MCP functionality test -
simplified_memory_server.py
- Basic memory server without complexity - Current memory service - Complex implementation (failing)
The complex memory service implementation was interfering with MCP framework's internal message routing. The issue wasn't in:
- The MCP library itself
- Basic handler registration
- Protocol communication
But rather in how our complex async initialization was interacting with the MCP message dispatch system.
Lesson Learned: When debugging protocol-level issues, create minimal reproducible examples to isolate the problem.
How we solved ChromaDB initialization hanging
ChromaDB initialization during server startup was causing the entire MCP server to hang indefinitely. This made the service unusable in production.
class MemoryServer:
def __init__(self):
# This would hang during startup
self.storage = ChromaMemoryStorage(db_path)
self.storage.initialize() # Blocking call
class MemoryServer:
def __init__(self):
self.storage = None # Don't initialize yet
self.db_path = db_path
async def _ensure_storage_initialized(self):
if self.storage is None:
self.storage = ChromaMemoryStorage(self.db_path)
await self.storage.initialize() # Async, on-demand
- Before: Infinite hang on startup
- After: 2323ms startup time
- First operation: Additional 3-5 seconds for lazy initialization
- Subsequent operations: < 100ms
- Defer ChromaDB initialization until first tool use
- Add
_ensure_storage_initialized()
method for on-demand loading - Make initialization async to prevent blocking
- Cache the initialized instance for subsequent calls
Lesson Learned: Not everything needs to be initialized at startup. Lazy loading can dramatically improve perceived performance.
June 7, 2025 - The victory lap
🎉 PROJECT COMPLETED SUCCESSFULLY
CURRENT STATUS:
✅ All dashboard functionality working perfectly
✅ Real data displayed: 189 memories, 404 unique tags, 100% health
✅ MCP protocol integration fully functional
✅ All tool execution working correctly
✅ Memory storage, search, and tag management operational
✅ Successfully committed and pushed to GitHub (hash: ba4a5ee)
- Complete MCP server communication via stdin/stdout JSON-RPC
- Dashboard-specific MCP tools implementation successful
- Lazy ChromaDB initialization working correctly
- Professional Electron + React + TypeScript desktop application
- Cross-platform compatibility (macOS, Windows, Linux)
- Real-time statistics and health monitoring
- Initial startup: 10-30 seconds (includes Electron app)
- MCP server startup: 2-3 seconds
- Memory operations: 50-200ms
- Search operations: 100-500ms depending on corpus size
- Dashboard refresh: < 100ms
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Claude Desktop │────▶│ MCP Memory │────▶│ ChromaDB │
│ or Dashboard │ MCP │ Service │ │ Storage │
└─────────────────┘ └──────────────────┘ └─────────────┘
│
▼
┌─────────────────┐
│ Sentence │
│ Transformers │
└─────────────────┘
From our recovery experience:
- Always maintain backup copies of working code (
server copy.py
saved the project) - Systematic testing approach is crucial
- Create multiple test scripts to verify functionality
- MCP protocol requires proper tool registration in
list_tools()
handler - Dashboard integration needs both dashboard health tools AND full memory service tools
Essential commands and paths:
# Installation
python install.py
# Run server
uv run memory
# Run tests
pytest tests/
# Key paths (macOS)
Memory Service: ~/Documents/GitHub/mcp-memory-service
Dashboard: ~/Documents/GitHub/mcp-memory-dashboard
ChromaDB: ~/Library/Application Support/mcp-memory/chroma_db
- Handler registration must happen before server start
- Use proper JSON Schema for tool input definitions
- Implement comprehensive error handling
- Test with minimal examples when debugging
- Always validate protocol compliance
- Implement lazy loading for heavy resources
- Use async operations throughout
- Cache initialized instances
- Monitor startup times
- Profile memory operations
When facing issues:
- Check paths and permissions
- Test individual components in isolation
- Verify MCP routing with debug logs
- Create minimal reproducible examples
- Use systematic elimination approach
The MCP Memory Server journey demonstrates that building robust MCP applications requires:
- Architectural flexibility - Be ready to pivot when assumptions prove limiting
- Systematic debugging - Create test matrices to isolate issues
- Performance awareness - Not everything needs immediate initialization
- Protocol compliance - Understanding MCP deeply is crucial
- Persistence - Complex integration issues require methodical approaches
These real-world examples show that even challenging technical problems can be overcome with the right approach and determination. The project evolved from a Claude Desktop-dependent concept to a standalone, cross-platform memory management solution that showcases the power of the MCP protocol.
Last updated: July 2025 *Contributors: Development team conversations captured in MCP Memory Service