Skip to content

Development Journey & Real‐World Examples

Henry edited this page Aug 23, 2025 · 1 revision

MCP Memory Server - Development Journey & Real-World Examples

A collection of real conversations and debugging sessions that shaped the MCP Memory Server project

Table of Contents

  1. Introduction
  2. The Architecture Pivot
  3. The Tool Registration Breakthrough
  4. The "Never Executes" Debugging Marathon
  5. The Lazy Loading Discovery
  6. Project Completion & Success Metrics
  7. Key Learnings & Best Practices

Introduction

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.


The Architecture Pivot

January 2025 - How we discovered and fixed a fundamental design flaw

The Initial Assumption

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.

The Critical Realization

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

The New Architecture

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

Impact of This Decision

  • ✅ 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 Tool Registration Breakthrough

The moment when tools finally appeared in the MCP server

The Problem

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.

The Investigation Process

# What we had (not working):
class MemoryServer:
    def __init__(self):
        self.tools = [...] # Tools defined but not registered

The Solution

# 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
    ]

Key Implementation Requirements

  1. Proper tool registration using @server.list_tools() decorator
  2. Detailed JSON Schema input definitions for each tool
  3. Implementation of handle_call_tool for request processing
  4. 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.


The "Never Executes" Debugging Marathon

June 2025 - When tool calls were received but never executed

The Mystery

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.

Diagnostic Evidence

**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 ❌

The Debugging Matrix

We created three test implementations to isolate the issue:

  1. minimal_uv_server.py - Baseline MCP functionality test
  2. simplified_memory_server.py - Basic memory server without complexity
  3. Current memory service - Complex implementation (failing)

The Root Cause

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.


The Lazy Loading Discovery

How we solved ChromaDB initialization hanging

The Problem

ChromaDB initialization during server startup was causing the entire MCP server to hang indefinitely. This made the service unusable in production.

Initial Approach (Hanging)

class MemoryServer:
    def __init__(self):
        # This would hang during startup
        self.storage = ChromaMemoryStorage(db_path)
        self.storage.initialize()  # Blocking call

The Solution: Lazy Loading

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

Performance Impact

  • Before: Infinite hang on startup
  • After: 2323ms startup time
  • First operation: Additional 3-5 seconds for lazy initialization
  • Subsequent operations: < 100ms

Implementation Details

  1. Defer ChromaDB initialization until first tool use
  2. Add _ensure_storage_initialized() method for on-demand loading
  3. Make initialization async to prevent blocking
  4. Cache the initialized instance for subsequent calls

Lesson Learned: Not everything needs to be initialized at startup. Lazy loading can dramatically improve perceived performance.


Project Completion & Success Metrics

June 7, 2025 - The victory lap

Final Status Update

🎉 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)

Technical Achievements

  • 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

Performance Metrics

  • 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

Architecture Overview

┌─────────────────┐     ┌──────────────────┐     ┌─────────────┐
│ Claude Desktop  │────▶│  MCP Memory      │────▶│  ChromaDB   │
│ or Dashboard    │ MCP │  Service         │     │  Storage    │
└─────────────────┘     └──────────────────┘     └─────────────┘
                              │
                              ▼
                     ┌─────────────────┐
                     │ Sentence        │
                     │ Transformers    │
                     └─────────────────┘

Key Learnings & Best Practices

1. Memory Service Restoration Checklist

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

2. Development Workflow

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

3. MCP Protocol Best Practices

  • 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

4. Performance Optimization

  • Implement lazy loading for heavy resources
  • Use async operations throughout
  • Cache initialized instances
  • Monitor startup times
  • Profile memory operations

5. Debugging Methodology

When facing issues:

  1. Check paths and permissions
  2. Test individual components in isolation
  3. Verify MCP routing with debug logs
  4. Create minimal reproducible examples
  5. Use systematic elimination approach

Conclusion

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

Clone this wiki locally