@npwork/mcp-proxy
v0.0.10
Published
Master MCP server that proxies multiple MCPs with semantic tool search
Maintainers
Readme
mcp-proxy
Master MCP server that proxies multiple MCPs with semantic tool search. Instead of configuring dozens of MCPs individually, configure one mcp-proxy that manages them all and provides intelligent tool discovery.
Features
- Single entry point - One MCP to rule them all
- Semantic search - Find tools using natural language queries (powered by e5-small-v2 embeddings)
- Dynamic tool discovery - No need to know exact tool names upfront
- Fail-fast startup - Ensures all child MCPs are healthy before accepting requests
Setup
1. Create mcps.json
Create a file that defines your child MCPs (e.g., ~/.claude/mcps.json):
{
"mcpServers": {
"mermaid": {
"description": "Tool that generates Mermaid diagrams",
"command": "npx",
"args": ["-y", "mcp-mermaid"]
}
}
}Config options per MCP:
description- (recommended) Helps semantic search find the right toolscommand- Executable to runargs- Command line argumentsenv- Environment variables (supports${VAR}placeholder syntax)
2. Add mcp-proxy to Claude Code
Add to your MCP settings (~/.claude.json or .mcp.json):
{
"mcpServers": {
"mcp-proxy": {
"command": "npx",
"args": ["-y", "@npwork/mcp-proxy"],
"env": {
"MCP_CONFIG_PATH": "<PATH TO mcps.json>"
}
}
}
}3. Claude Code Hook (Recommended)
To ensure Claude Code always checks mcp-proxy first, add a UserPromptSubmit hook.
3.1 Create the hook script (e.g., ~/.claude/hooks/always-use-mcp-proxy.sh):
#!/bin/bash
# UserPromptSubmit hook that enforces MCP proxy usage
CONFIG_PATH="/path/to/mcps.json" # <-- UPDATE THIS PATH
# Extract MCP names and descriptions using jq
MCP_LIST=$(jq -r '.mcpServers | to_entries | map("- \(.key): \(.value.description // "no description")") | join("\n")' "$CONFIG_PATH")
cat <<EOF
INSTRUCTION: MANDATORY MCP PROXY CHECK
Available MCPs via mcp-proxy:
$MCP_LIST
IF any MCP description matches your task:
1. Use mcp__mcp-proxy__search_tool(query: "...") to find the right tool
2. Use mcp__mcp-proxy__execute(mcp: "name", tool: "tool_name", args: {...}) to call it
NEVER use shell commands (psql, cqlsh, curl, etc) when an MCP can do it.
EOF3.2 Make it executable:
chmod +x ~/.claude/hooks/always-use-mcp-proxy.sh3.3 Add to your Claude Code settings (.claude/settings.json):
{
"hooks": {
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/always-use-mcp-proxy.sh"
}
]
}
]
}
}4. First Run
- Open Claude Code
- Type
/mcpand wait for MCP to connect - If mcp-proxy shows as "failed" - this is normal on first run (downloading takes time)
- Click on mcp-proxy entry and select "Reconnect"
- Wait for connection - should succeed on retry
- If still failing, run
claude --debugand check logs for errors
Tools
mcp-proxy exposes two tools:
search_tool
Search for tools across all configured MCPs using natural language.
search_tool(query: "database query", limit: 5)Returns matching tools with their schemas, MCP name, and relevance score.
execute
Execute a tool on a specific child MCP.
execute(mcp: "postgres", tool: "query", args: { sql: "SELECT * FROM users" })Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| MCP_CONFIG_PATH | Path to mcps.json config file | (required) |
| MCP_CONNECTION_TIMEOUT | Connection timeout in ms | 30000 |
| MCP_CACHE_DIR | Directory for embeddings cache | /tmp/mcp-proxy |
| MCP_LOG_FILE | Log file path (timestamped) | (stderr only) |
How it works
- On startup, mcp-proxy connects to all configured child MCPs
- It fetches tool lists from each MCP and builds a semantic search index using e5-small-v2 embeddings
- When you call
search_tool, it performs vector similarity search to find relevant tools - When you call
execute, it forwards the request to the appropriate child MCP
License
ISC
