DMCP - Dynamic Model Context Protocol
Semantic tool discovery for MCP - Solves the "too many tools" problem by making tool discovery query-driven with vector search.
π― The Problem
When you aggregate 20+ MCP servers (~300+ tools):
- Token explosion: 100,000+ tokens just listing tools
- LLM confusion: Too many choices = poor tool selection
- No filtering: Standard MCP returns ALL tools upfront
β¨ The Solution
DMCP uses semantic vector search to discover tools on-demand:
User: "Create a GitHub issue for this bug"
LLM calls: search_tools(query="create GitHub issue")
β Returns top-15 relevant tools (via semantic vector search)
β Tools become available for use
LLM calls: github_create_issue(...)
β Issue created!
Key insight: The LLM discovers tools by asking, not by loading everything upfront.
β¨ Features
- π Semantic Search: ToolRet-trained E5 model for accurate tool retrieval
- β‘ Fast: ~50ms search latency, 98% token reduction
- π Connection Resilience: Auto-retry, health checks, reconnection
- π³ Docker Ready: Full stack with Redis VSS + Embedding service
- π Observable: Health endpoints, session logging, connection status
- β Tested: 56 unit tests with vitest
ποΈ Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β VS Code / GitHub Copilot β
β β
β User: "search for kubernetes tools" β
β β search_tools("kubernetes") β
β β Returns: 15 k8s tools (get_pods, list_deployments, ...) β
βββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββ
β HTTP (Streamable HTTP Transport)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DMCP Server (port 3001) β
β β
β β’ Exposes 1 meta-tool: search_tools β
β β’ Pure vector search (COSINE similarity, HNSW index) β
β β’ Sends listChanged notifications when tools discovered β
β β’ Connection keep-alive with health checks (30s interval) β
β β’ Auto-retry on connection failures (3 attempts, exponential backoff) β
ββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββ¬ββββββββββββββ
β β
β Query embeddings β Tool calls (SSE)
βΌ βΌ
ββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββ
β Redis Stack (port 6380) β β Backend MCP Servers β
β β β (via Agent Gateway) β
β β’ Vector Index (HNSW) β β β
β β’ COSINE similarity β β β’ GitHub, Jira, Confluenceβ
β β’ 400+ tools indexed β β β’ Google Workspace, Notionβ
ββββββββββββββββββββββββββββββββββ β β’ Kubernetes, AWS, Azure β
β² β β’ And more... β
β ββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββ
β Infinity Embedding Service β
β (port 5000) β
β β
β β’ ToolRet e5-large-v2 model β
β β’ 1024 dimensions β
β β’ OpenAI-compatible API β
ββββββββββββββββββββββββββββββββββ
π Quick Start
Prerequisites
- Docker & Docker Compose
- An MCP server gateway exposing your tools (e.g., Agent Gateway)
1. Clone and Start
git clone https://github.com/yourusername/dmcp.git
cd dmcp
# Start everything: Redis, Embedding Service, and DMCP Server
docker compose up -d
# Wait for services to be healthy (~2-3 minutes for embedding model to load)
docker compose ps
2. Index Your Tools
# Run the indexer to populate Redis with tools from your MCP gateway
docker compose run --rm indexer
# Verify tools are indexed
curl http://localhost:3001/health
# β {"status":"healthy","toolCount":420,...}
3. Configure VS Code
Add to your .vscode/mcp.json:
{
"servers": {
"dmcp": {
"type": "http",
"url": "http://localhost:3001/mcp"
}
}
}
That's it! The search_tools meta-tool is now available in VS Code / GitHub Copilot.
π Project Structure
dmcp/
βββ docker-compose.yml # Full stack configuration
βββ server/ # DMCP Server (TypeScript)
β βββ src/
β β βββ dmcp-server.ts # Main server with connection management
β β βββ redis-vss.ts # Redis vector similarity search
β β βββ custom-embedding-provider.ts
β β βββ dmcp-server.test.ts # Unit tests (28 tests)
β β βββ redis-vss.test.ts # Unit tests (28 tests)
β βββ vitest.config.ts
β βββ package.json
βββ indexer/ # Tool Indexer (TypeScript)
β βββ src/
β βββ index.ts # CLI indexer with parallel discovery
βββ README.md
π³ Docker Commands
# Start full stack
docker compose up -d
# View logs
docker compose logs -f dmcp-server
# Run one-shot indexing
docker compose run --rm indexer
# Start continuous sync worker
docker compose --profile worker up -d
# Rebuild after code changes
docker compose build dmcp-server && docker compose up -d dmcp-server
# Stop everything
docker compose down
# Stop and delete indexed data
docker compose down -v
βοΈ Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
PORT | 3000 | Server port (inside container) |
REDIS_HOST | localhost | Redis server host |
REDIS_PORT | 6379 | Redis server port |
EMBEDDING_URL | http://localhost:5000 | Embedding service URL |
DMCP_TOP_K | 15 | Max tools returned per search |
DMCP_MIN_SCORE | 0.3 | Minimum similarity threshold |
Connection Resilience
| Variable | Default | Description |
|---|---|---|
DMCP_RETRY_ATTEMPTS | 3 | Max connection retry attempts |
DMCP_RETRY_DELAY_MS | 1000 | Base delay between retries (exponential backoff) |
DMCP_HEALTH_INTERVAL_MS | 30000 | Health check interval for backend connections |
DMCP_CONNECTION_TIMEOUT_MS | 10000 | Connection timeout |
Docker Compose Services
| Service | Container | Host Port | Description |
|---|---|---|---|
redis-vss | mcp-redis-vss | 6380 | Redis Stack with vector search |
embedding-service | mcp-embedding-infinity | 5000 | Infinity embedding service |
dmcp-server | dmcp-server | 3001 | DMCP MCP server |
indexer | dmcp-indexer | - | One-shot indexer |
indexer-worker | dmcp-indexer-worker | - | Continuous sync (optional) |
π How Search Works
DMCP uses pure vector search with the ToolRet embedding model:
- Query is embedded using ToolRet-trained E5-large-v2
- Redis performs HNSW nearest neighbor search
- Top-K results are returned sorted by COSINE similarity
- Tools become available via
notifications/tools/list_changed
Example queries:
| Query | Finds |
|---|---|
"create GitHub issue" | GitHub tools |
"ticket management" | Jira tools |
"check pod logs" | Kubernetes tools |
"search emails" | Google Workspace |
"query Notion database" | Notion tools |
π₯ Health & Monitoring
Health Endpoint
curl http://localhost:3001/health
Response:
{
"status": "healthy",
"toolCount": 440,
"activeSessions": 2,
"backendConnections": {
"total": 5,
"healthy": 5,
"details": [
{"serverId": "github", "healthy": true, "lastCheck": 1704700000000},
{"serverId": "serena", "healthy": true, "lastCheck": 1704700000000}
]
},
"config": {
"retryAttempts": 3,
"retryDelayMs": 1000,
"healthIntervalMs": 30000,
"connectionTimeoutMs": 10000
},
"uptime": 3600
}
Server Logs
docker compose logs -f dmcp-server
# Example output:
# 16:38:36 [DMCP] π Server listening on http://0.0.0.0:3000
# 16:38:36 [DMCP] β Found 440 indexed tools
# 16:38:52 [DMCP] POST /mcp [initialize]
# 16:38:52 [DMCP] π‘ New connection request (session #1)
# 16:39:01 [DMCP] π Search: "kubernetes pods" (limit: 15)
# 16:39:01 [DMCP] β Found 12 tools in 45ms
π§ͺ Testing
cd server
# Run tests
npm test
# Run with watch mode
npm run test:watch
# Run with coverage
npm run test:coverage
Test Coverage: 56 tests covering:
- Tool name sanitization and parsing
- Connection retry and health check logic
- Redis vector search operations
- Embedding operations
π§ Local Development
# Start only infrastructure
docker compose up -d redis-vss embedding-service
# Run server locally
cd server
npm install
REDIS_PORT=6380 EMBEDDING_URL=http://localhost:5000 npm run start
# Run tests
npm test
β Adding MCP Servers
DMCP works with any MCP server. Example configurations are in gateway/config_parts/.
Notion MCP Server
Notion MCP provides tools for searching, reading, and creating Notion pages/databases.
- Create a Notion integration at notion.so/my-integrations
- Add to your gateway config (
gateway/config_parts/70-notion.yaml):
targets:
- name: notion
type: mcp
target_config:
command: npx
args:
- -y
- "@notionhq/notion-mcp-server"
env:
OPENAPI_MCP_HEADERS: '{"Authorization": "Bearer ${NOTION_API_KEY}", "Notion-Version": "2022-06-28"}'
- Set your API key:
export NOTION_API_KEY=ntn_... - Restart gateway and re-index:
docker compose run --rm indexer
Other Popular MCP Servers
| Server | Package | Documentation |
|---|---|---|
| GitHub | @modelcontextprotocol/server-github | GitHub MCP |
| Slack | @modelcontextprotocol/server-slack | Slack MCP |
| Google Drive | @modelcontextprotocol/server-gdrive | GDrive MCP |
| PostgreSQL | @modelcontextprotocol/server-postgres | Postgres MCP |
π Performance
| Metric | Value |
|---|---|
| Tools indexed | 440 |
| Index time | ~45 seconds |
| Search latency | ~50ms |
| Token reduction | 98% |
| Embedding model | ToolRet-e5-large-v2 (1024 dims) |
π MCP Spec Compliance
Implements MCP Specification with Streamable HTTP Transport:
- β
listChanged: truecapability - β
notifications/tools/list_changednotifications - β Dynamic tool availability based on search
- β Streamable HTTP transport (POST/GET/DELETE)
- β Session management with UUID session IDs
- β SSE for async notifications
π¬ Research Foundation
Implementation based on "Retrieval Models Aren't Tool-Savvy" (ACL 2025):
- π Paper
- π€ Model: mangopy/ToolRet-trained-e5-large-v2
- π GitHub
Key Insight: General IR models perform poorly on tool retrieval; tool-specific training is essential.
π¬ Inspiration
- πΊ MCP Tool Overload Problem - YouTube
- π Redis Blog: From Reasoning to Retrieval
π License
MIT