使用说明
mcp-manager
An MCP proxy server that wraps multiple MCP backends and exposes a searchable tool catalog through 5 lightweight tools. Instead of loading full tool schemas (8,000–20,000+ tokens) from every backend on each request, models can discover and call tools on demand.
How It Works
LLM / MCP Client
│
▼
┌───────────────────────────────────────────────┐
│ mcp-manager (proxy) │
│ search_tools │ get_tool_schema │
│ call_tool │ list_servers │
│ get_tools_by_server │
└───────────────┬─────────────────────────────┘
│
┌──────────┼──────────┐
▼ ▼ ▼
context7 github filesystem
(HTTP) (stdio) (stdio)
- The model calls
search_toolsto find relevant tools by name/description - The model calls
get_tool_schemato retrieve the full input schema for a specific tool - The model calls
call_toolto execute the tool on the backend server - The model calls
get_tools_by_serverto get all tools available on a specific backend - Backend connections are spawned lazily and cached; idle connections are killed after 5 minutes
Requirements
- Python 3.11+
- uv
- Node.js (for stdio backends using
npx)
Installation
git clone <repo-url>
cd mcp-manager
# Create the venv and install all deps (incl. dev) from uv.lock
uv sync
Run any command with uv run <cmd> (no manual venv activation needed).
Configuration
Edit backends.json to define your MCP backends:
{
"servers": {
"my-http-server": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"timeout_seconds": 30
},
"my-stdio-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${env:GITHUB_TOKEN}"
},
"timeout_seconds": 30
}
}
}
Backend types
| Field | Type | Description |
|---|---|---|
type |
http | stdio |
Transport protocol |
url |
string | HTTP endpoint (http type only) |
command |
string | Executable to spawn (stdio type only) |
args |
string[] | Arguments for the command (stdio type only) |
env |
object | Environment variables; supports ${env:VAR} syntax |
timeout_seconds |
int | Per-request timeout (default: 30) |
Environment variable substitution
Values using ${env:VAR_NAME} are replaced with the corresponding environment variable at startup:
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${env:GITHUB_TOKEN}"
}
Building the Catalog
Before starting the server, build the tool catalog. This queries all backends and snapshots their tool schemas into catalog.json:
uv run catalog-builder --config backends.json --catalog catalog.json
Or pass --build-catalog when starting the server to build it automatically:
uv run mcp-manager --build-catalog
Running the Server
stdio mode (default — for MCP clients like Claude Desktop)
uv run mcp-manager \
--config backends.json \
--catalog catalog.json \
--transport stdio
SSE/HTTP mode
uv run mcp-manager \
--config backends.json \
--catalog catalog.json \
--transport sse \
--port 8000
CLI options
| Option | Default | Description |
|---|---|---|
--config |
backends.json |
Path to backend configuration file |
--catalog |
catalog.json |
Path to catalog file |
--transport |
stdio |
stdio or sse |
--port |
8000 |
Port for SSE mode |
--build-catalog |
false | Build catalog before starting |
Environment variable overrides: MCP_PROXY_TRANSPORT, MCP_PROXY_PORT.
The 5 Proxy Tools
search_tools
Semantic vector search over the catalog by tool name or description.
{
"query": "search for files",
"max_results": 5
}
Returns:
[
{
"server": "filesystem",
"name": "search_files",
"key": "filesystem/search_files",
"description": "Search for files matching a pattern",
"score": 91.4
}
]
get_tool_schema
Retrieve the full JSON Schema for a specific tool.
{
"server": "filesystem",
"tool_name": "search_files"
}
Returns:
{
"success": true,
"server": "filesystem",
"tool_name": "search_files",
"key": "filesystem/search_files",
"description": "Search for files matching a pattern",
"input_schema": { ... },
"updated_at": "2026-03-26T10:00:00"
}
call_tool
Execute a tool on a backend server.
{
"server": "filesystem",
"tool_name": "search_files",
"arguments": {
"path": "/tmp",
"pattern": "*.log"
}
}
Returns: the backend's MCP CallToolResult, passed through unchanged.
Text blocks are not re-encoded, images arrive as image blocks, and
isError, structuredContent and _meta are kept as the backend sent them.
{
"content": [{ "type": "text", "text": "/tmp/app.log\n/tmp/db.log" }],
"structuredContent": { "matches": ["/tmp/app.log", "/tmp/db.log"] },
"isError": false
}
Proxy-side failures (unknown tool or server, invalid arguments, timeout,
backend crash) use the same shape with isError: true and one text block:
{
"content": [
{
"type": "text",
"text": "Tool 'search_filez' not found on server 'filesystem'"
}
],
"isError": true
}
Invalid arguments append the tool's input schema to the error text so the caller can retry with corrected arguments.
list_servers
List all configured backends and their status.
Returns:
[
{
"id": "filesystem",
"name": "filesystem",
"type": "stdio",
"status": "ready",
"tool_count": 5,
"last_cataloged_at": "2026-03-26T10:00:00"
}
]
get_tools_by_server
Get all tools available for a specific backend server.
{
"server": "github"
}
Returns:
[
{
"name": "search_repositories",
"description": "Search for repositories on GitHub"
},
{
"name": "get_user_profile",
"description": "Get a user's GitHub profile information"
}
]
Claude Desktop Integration
Add mcp-manager to your Claude Desktop config (~/.config/claude/claude_desktop_config.json):
{
"mcpServers": {
"mcp-manager": {
"command": "uv",
"args": [
"run",
"mcp-manager",
"--config",
"/path/to/mcp-manager/backends.json",
"--catalog",
"/path/to/mcp-manager/catalog.json"
],
"cwd": "/path/to/mcp-manager"
}
}
}
Claude Code Hook
hooks/mcp_manager_context.py injects an additionalContext block explaining
how mcp-manager works, the current server/tool-count table (read live from
catalog.json), and the discover → schema → call flow. Wire it into both
SessionStart and UserPromptSubmit in .claude/settings.json:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "uvx --from git+https://github.com/Ronnasayd/mcp-manager.git mcp_manager_context /path/to/mcp-manager/catalog.json"
}
]
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "uvx --from git+https://github.com/Ronnasayd/mcp-manager.git mcp_manager_context /path/to/mcp-manager/catalog.json"
}
]
}
]
}
}
The script takes the path to catalog.json as its only argument, so the
server/tool table always reflects the latest catalog build
without editing the hook itself.
Development
Run tests
# Dev deps are already installed by `uv sync`
# Run all tests
uv run pytest
# Run with verbose output
uv run pytest -v
# Run a specific test file
uv run pytest tests/unit/test_search_tools.py -v
Project structure
src/
proxy/ # FastMCP server entrypoint
catalog/ # Catalog schema (Pydantic) and builder
backends/ # Connection manager (stdio & HTTP)
tools/ # The 4 proxy tool implementations
tests/
unit/ # Unit tests for each module
integration/ # End-to-end proxy tests
fixtures/ # Mock MCP server helpers
backends.json # Backend configuration
catalog.json # Generated tool catalog (auto-built)
