Unified Dynamic MCP Server
by sasajib
README.md
# 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
```bash
# 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:
1. **Search** (`search_tools`) ā Find relevant tools ā **~50 tokens**
2. **Describe** (`describe_tools`) ā Get full schemas ā **~200 tokens/tool**
3. **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](https://rustup.rs/)
- **Node.js 18+** (for Context7/Playwright) - [Install Node](https://nodejs.org/)
- **Claude Code** (for Claude-mem plugin) - [Install Claude Code](https://claude.ai/download)
### 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:**
1. **Install via Claude Code Plugin Marketplace:**
```bash
# In Claude Code terminal
/plugin marketplace add thedotmack/claude-mem
/plugin install claude-mem
```
2. **Restart Claude Code** - The plugin auto-starts the HTTP API on `http://localhost:37777`
3. **Verify Installation:**
```bash
# Check the service is running
curl http://localhost:37777
# Or visit the web UI
open http://localhost:37777
```
4. **Troubleshooting:**
```bash
# 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](https://github.com/thedotmack/claude-mem).
### Install Dependencies
```bash
# 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`, `core` directories)
- ā
**No manual setup required** - just install Codanna and start the server
- š **Optional file watching** - enable `watch_changes: true` in `config/catalog.yaml` to auto-reindex on file changes
To customize auto-indexing, edit `config/catalog.yaml`:
```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
```bash
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`):
```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):**
```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",
"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`:
```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`:
```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 tools
- `describe_tools([names])` - Get full schemas
- `execute_tool(name, args)` - Run a tool
**Capability Management**:
- `list_capabilities()` - See all capabilities
- `enable_capability(name)` - Enable at runtime
- `disable_capability(name)` - Disable at runtime
**Code Understanding** (Codanna - Phase 2):
- `search_code` - Semantic code search
- `get_call_graph` - Function relationships
- `find_symbol` - Symbol lookup (sub-10ms)
- `find_implementations` - Find implementations
**Documentation** (Context7 - Phase 3):
- `resolve_library_id` - Resolve library name
- `get_library_docs` - Fetch documentation
**Browser Automation** (Playwright - Phase 3):
- `playwright_navigate` - Navigate to URL
- `playwright_screenshot` - Take screenshot
- `playwright_click` - Click element
- `playwright_fill` - Fill form field
- `playwright_evaluate` - Execute JavaScript
**Memory** (Claude-mem - Phase 4):
- `mem_search` - Search observations
- `mem_get_observation` - Get by ID
- `mem_recent_context` - Recent sessions
- `mem_timeline` - Timeline view
**Knowledge Graph** (Graphiti - Phase 4):
- `store_insight` - Store knowledge
- `search_insights` - Search insights
- `query_graph` - Cypher queries
- `add_episode` - Add episode
## Development
### Run Tests
```bash
# 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
## References
- [MCP Specification](https://modelcontextprotocol.io/)
- [Docker MCP Gateway](https://github.com/docker/mcp-gateway)
- [Codanna](https://github.com/bartolli/codanna)
- [Context7](https://github.com/upstash/context7)
- [Playwright MCP](https://github.com/microsoft/playwright-mcp)
- [Claude-mem](https://github.com/thedotmack/claude-mem)
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues