Unified Dynamic MCP Server
Single MCP server with progressive discovery for 96-160x token reduction
Consolidates code understanding (Codanna), documentation (Context7), browser automation (Playwright), memory (Claude-mem), and knowledge graph (Graphiti+LadybugDB) into one unified server.
✨ NEW: Graphiti knowledge graph now supports Google Gemini! Use free Gemini API with embedded LadybugDB (no Docker required).
Features
✨ Progressive Discovery - 3-step pattern reduces tokens from 10,000+ to 50-200 🔧 Dynamic Tool Loading - Lazy load capabilities only when needed 🎯 5 Integrated Capabilities - Code, docs, browser, memory, knowledge graph 🚀 Git Submodules - Auto-update with git submodule update --remote ⚡ Fast - Sub-10ms symbol lookup (Codanna), embedded LadybugDB (no Docker)
Quick Start
# 1. Clone with submodules
git clone --recursive https://github.com/yourusername/unified-mcp.git
cd unified-mcp
# 2. Install dependencies (using uv - recommended)
uv pip install -r requirements.txt
# 3. Install Claude-mem plugin (required for memory capability)
# In Claude Code terminal:
/plugin marketplace add thedotmack/claude-mem
/plugin install claude-mem
# Then restart Claude Code
# 4. Add to Claude Code (replace /path/to/unified-mcp with actual path)
claude mcp add --transport stdio \
unified-mcp \
-- uv --directory /absolute/path/to/unified-mcp run server.py
# 5. For Graphiti + Google Gemini support (optional)
claude mcp add --transport stdio unified-mcp \
-e GRAPHITI_ENABLED=true \
-e GRAPHITI_LLM_PROVIDER=google_ai \
-e GRAPHITI_EMBEDDER_PROVIDER=google_ai \
-e GOOGLE_API_KEY=your-gemini-api-key-here \
-e GRAPHITI_LLM_MODEL=gemini-1.5-pro \
-e GRAPHITI_EMBEDDER_MODEL=text-embedding-004 \
-- uv --directory /absolute/path/to/unified-mcp run server.py
# 6. Restart Claude Code and verify
# Ask Claude: "What tools do you have available?"
Manual Testing (optional): ```bash
Run tests
pytest tests/ -v
Start server directly
uv run server.py ```
Progressive Discovery Pattern
Traditional approach: Load all 20 tools upfront = 10,000 tokens
Our approach:
- Search (
search_tools) → Find relevant tools → ~50 tokens - Describe (
describe_tools) → Get full schemas → ~200 tokens/tool - Execute (
execute_tool) → Run the tool → Variable
Result: 98% token reduction 🎉
Architecture
Unified MCP Server
├── Progressive Discovery Engine
├── Dynamic Tool Registry
├── 5 Capability Modules
│ ├── Codanna (code understanding)
│ ├── Context7 (documentation)
│ ├── Playwright (browser automation)
│ ├── Claude-mem (memory)
│ └── Graphiti+LadybugDB (knowledge graph)
Installation
Requirements
- Python 3.12+ (for LadybugDB)
- Rust/Cargo (for Codanna) - Install Rust
- Node.js 18+ (for Context7/Playwright) - Install Node
- Claude Code (for Claude-mem plugin) - Install Claude Code
Claude-Mem Setup (Memory Capability)
Important: Claude-mem is a separate MCP server that runs as a Claude Code plugin. It must be installed before the unified-mcp memory capability will work.
Installation Steps:
- Install via Claude Code Plugin Marketplace:
# In Claude Code terminal
/plugin marketplace add thedotmack/claude-mem
/plugin install claude-mem
- Restart Claude Code - The plugin auto-starts the HTTP API on
http://localhost:37777
- Verify Installation:
# Check the service is running
curl http://localhost:37777
# Or visit the web UI
open http://localhost:37777
- Troubleshooting:
# Use the built-in troubleshooting skill
/claude-mem:troubleshoot
What Gets Installed:
- HTTP API service on port 37777 (auto-managed by Bun)
- SQLite database at
~/.claude-mem/claude-mem.db - Web UI for browsing stored memories
- 5 lifecycle hooks for automatic memory capture
- Vector search via Chroma for semantic queries
Architecture:
- The unified-mcp server connects to claude-mem's HTTP API
- No direct npm installation needed - plugin handles all dependencies
- Auto-starts when Claude Code is running
- Stores observations across sessions with semantic search
For more details, see the claude-mem documentation.
Install Dependencies
# Python dependencies
pip install -r requirements.txt
# Codanna (code understanding)
cargo install codanna --all-features
# Git submodules (for Context7 and Playwright only - claude-mem is a plugin)
git submodule update --init --recursive
cd capabilities/context7 && npm install
cd ../playwright-mcp && npm install
# Note: claude-mem is installed as a Claude Code plugin (see above), not via npm
Codanna Auto-Indexing:
The server automatically creates and manages Codanna indexes:
- ✅ Automatic indexing on first run (indexes
src,lib,handlers,coredirectories) - ✅ No manual setup required - just install Codanna and start the server
- 🔄 Optional file watching - enable
watch_changes: trueinconfig/catalog.yamlto auto-reindex on file changes
To customize auto-indexing, edit config/catalog.yaml:
code_understanding:
auto_index: true # Auto-create index if missing
watch_changes: false # Watch files and re-index (requires watchdog)
index_dirs: # Directories to index
- src
- lib
- your-custom-dir
Usage
Start Server
python server.py
Server runs on stdio (MCP protocol).
Configure with Claude Code
Option 1: Using claude mcp add (Recommended)
Replace /absolute/path/to/unified-mcp with your actual installation path.
Basic Configuration (No Graphiti): ``bash claude mcp add --transport stdio \ unified-mcp \ -- uv --directory /absolute/path/to/unified-mcp run server.py ``
With Graphiti + Google Gemini: ``bash claude mcp add --transport stdio unified-mcp \ -e GRAPHITI_ENABLED=true \ -e GRAPHITI_LLM_PROVIDER=google_ai \ -e GRAPHITI_EMBEDDER_PROVIDER=google_ai \ -e GOOGLE_API_KEY=your-gemini-api-key-here \ -e GRAPHITI_LLM_MODEL=gemini-1.5-pro \ -e GRAPHITI_EMBEDDER_MODEL=text-embedding-004 \ -- uv --directory /absolute/path/to/unified-mcp run server.py ``
With Graphiti + OpenAI: ``bash claude mcp add --transport stdio unified-mcp \ -e GRAPHITI_ENABLED=true \ -e GRAPHITI_LLM_PROVIDER=openai \ -e GRAPHITI_EMBEDDER_PROVIDER=openai \ -e OPENAI_API_KEY=sk-your-openai-key-here \ -e GRAPHITI_LLM_MODEL=gpt-4o \ -e GRAPHITI_EMBEDDER_MODEL=text-embedding-3-small \ -- uv --directory /absolute/path/to/unified-mcp run server.py ``
With Graphiti + Anthropic Claude + Voyage Embeddings: ``bash claude mcp add --transport stdio unified-mcp \ -e GRAPHITI_ENABLED=true \ -e GRAPHITI_LLM_PROVIDER=anthropic \ -e GRAPHITI_EMBEDDER_PROVIDER=voyage_ai \ -e ANTHROPIC_API_KEY=sk-ant-your-key-here \ -e VOYAGE_API_KEY=pa-your-voyage-key-here \ -e GRAPHITI_LLM_MODEL=claude-3-5-sonnet-20241022 \ -e GRAPHITI_EMBEDDER_MODEL=voyage-3 \ -- uv --directory /absolute/path/to/unified-mcp run server.py ``
With Graphiti + Local Ollama (Free): ``bash claude mcp add --transport stdio unified-mcp \ -e GRAPHITI_ENABLED=true \ -e GRAPHITI_LLM_PROVIDER=ollama \ -e GRAPHITI_EMBEDDER_PROVIDER=ollama \ -e OLLAMA_BASE_URL=http://localhost:11434 \ -e GRAPHITI_LLM_MODEL=llama3.1 \ -e GRAPHITI_EMBEDDER_MODEL=nomic-embed-text \ -- uv --directory /absolute/path/to/unified-mcp run server.py ``
Full Configuration Example (All Options): ``bash claude mcp add --transport stdio unified-mcp \ -e CODANNA_INDEX_DIR=.codanna \ -e CLAUDE_MEM_API_URL=http://localhost:37777 \ -e GRAPHITI_ENABLED=true \ -e GRAPHITI_LLM_PROVIDER=google_ai \ -e GRAPHITI_EMBEDDER_PROVIDER=google_ai \ -e GOOGLE_API_KEY=your-gemini-api-key-here \ -e GRAPHITI_LLM_MODEL=gemini-1.5-pro \ -e GRAPHITI_EMBEDDER_MODEL=text-embedding-004 \ -e GRAPHITI_DB_PATH=.graphiti/ladybug.db \ -- uv --directory /absolute/path/to/unified-mcp run server.py ``
Option 2: Manual Configuration
Add to your MCP settings file (~/.config/claude/mcp_settings.json):
{
"mcpServers": {
"unified-mcp": {
"command": "uv",
"args": [
"--directory",
"/absolute/path/to/unified-mcp",
"run",
"server.py"
],
"env": {
"CODANNA_INDEX_DIR": "${workspaceFolder}/.codanna",
"CLAUDE_MEM_API_URL": "http://localhost:37777",
"GRAPHITI_ENABLED": "true",
"GOOGLE_API_KEY": "your-gemini-api-key-here"
}
}
}
}
With Graphiti + Google Gemini (Full Configuration):
{
"mcpServers": {
"unified-mcp": {
"command": "uv",
"args": [
"--directory",
"/absolute/path/to/unified-mcp",
"run",
"server.py"
],
"env": {
"CODANNA_INDEX_DIR": "${workspaceFolder}/.codanna",
"CLAUDE_MEM_API_URL": "http://localhost:37777",
"GRAPHITI_ENABLED": "true",
"GRAPHITI_LLM_PROVIDER": "google_ai",
"GRAPHITI_EMBEDDER_PROVIDER": "google_ai",
"GOOGLE_API_KEY": "your-gemini-api-key-here",
"GRAPHITI_LLM_MODEL": "gemini-1.5-pro",
"GRAPHITI_EMBEDDER_MODEL": "text-embedding-004"
}
}
}
}
Environment Variables:
| Variable | Required | Default | Description | |----------|----------|---------|-------------| | CODANNA_INDEX_DIR | No | .codanna | Codanna index directory | | CLAUDE_MEM_API_URL | No | http://localhost:37777 | Claude-mem API endpoint | | GRAPHITI_ENABLED | No | false | Enable Graphiti knowledge graph | | GRAPHITI_LLM_PROVIDER | No | openai | LLM provider: openai, anthropic, azure_openai, ollama, google_ai | | GRAPHITI_EMBEDDER_PROVIDER | No | openai | Embedder: openai, voyage_ai, azure_openai, ollama, google_ai | | GRAPHITI_LLM_MODEL | No | (varies) | Model name (e.g., gemini-2.5-flash, gpt-4o, claude-3-5-sonnet-20241022) | | GRAPHITI_EMBEDDER_MODEL | No | (varies) | Embedder model (e.g., text-embedding-004, text-embedding-3-small) | | GRAPHITI_RERANKER_MODEL | No | gemini-2.5-flash-lite | Reranker model (Gemini only) | | GOOGLE_API_KEY | If using Gemini | - | Google AI API key for Gemini | | OPENAI_API_KEY | If using OpenAI | - | OpenAI API key | | ANTHROPIC_API_KEY | If using Claude | - | Anthropic API key |
Playwright Browser Configuration:
Browser automation runs with headless=false by default (shows browser window). Configure in config/catalog.yaml:
browser_automation:
headless: false # Set to true to run browser in background
Restart Claude Code to load the server.
Verify it's working:
- Ask Claude: "What tools do you have available?"
- You should see tools like
search_tools,describe_tools,execute_tool, etc.
Configuration
Edit config/catalog.yaml:
capabilities:
code_understanding:
enabled: true # Toggle capabilities
tools: [search_code, get_call_graph, ...]
Tools Available
Progressive Discovery (Meta-tools):
search_tools(query)- Find relevant toolsdescribe_tools([names])- Get full schemasexecute_tool(name, args)- Run a tool
Capability Management:
list_capabilities()- See all capabilitiesenable_capability(name)- Enable at runtimedisable_capability(name)- Disable at runtime
Code Understanding (Codanna - Phase 2):
search_code- Semantic code searchget_call_graph- Function relationshipsfind_symbol- Symbol lookup (sub-10ms)find_implementations- Find implementations
Documentation (Context7 - Phase 3):
resolve_library_id- Resolve library nameget_library_docs- Fetch documentation
Browser Automation (Playwright - Phase 3):
playwright_navigate- Navigate to URLplaywright_screenshot- Take screenshotplaywright_click- Click elementplaywright_fill- Fill form fieldplaywright_evaluate- Execute JavaScript
Memory (Claude-mem - Phase 4):
mem_search- Search observationsmem_get_observation- Get by IDmem_recent_context- Recent sessionsmem_timeline- Timeline view
Knowledge Graph (Graphiti - Phase 4):
store_insight- Store knowledgesearch_insights- Search insightsquery_graph- Cypher queriesadd_episode- Add episode
Development
Run Tests
# All tests
pytest tests/ -v
# Unit tests only
pytest tests/unit/ -v
# With coverage
pytest tests/ --cov=. --cov-report=term-missing
# Skip slow tests
pytest tests/ -m "not slow"
Project Structure
unified-mcp/
├── server.py # Main MCP server
├── config/
│ └── catalog.yaml # Capability configuration
├── core/
│ ├── dynamic_registry.py
│ ├── progressive_discovery.py
│ └── capability_loader.py
├── handlers/ # Capability handlers
├── capabilities/ # Git submodules
├── tests/ # Comprehensive test suite
└── docs/ # Documentation
Implementation Status
- ✅ Phase 1: Foundation (Dynamic registry, progressive discovery)
- ✅ Phase 2: Codanna integration (4 code understanding tools)
- ✅ Phase 3: Context7 + Playwright (7 tools: docs + browser automation)
- ✅ Phase 4: Claude-mem + Graphiti (8 tools: memory + knowledge graph)
- ✅ Phase 5: Comprehensive testing (Unit + Integration + E2E, 80%+ coverage, CI/CD)
- ✅ Phase 6: Documentation (Complete)
License
Apache 2.0






