MCP工具目录代理服务

mcp-manager 是一个 MCP 代理服务器,通过可搜索的工具目录和轻量级接口让客户端按需发现、查询并调用多个 MCP 后端工具,适用于 LLM/MCP 客户端集成与开发效率提升场景。

  • by Ronnasayd
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 Ronnasayd/mcp-manager

使用说明

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)
  1. The model calls search_tools to find relevant tools by name/description
  2. The model calls get_tool_schema to retrieve the full input schema for a specific tool
  3. The model calls call_tool to execute the tool on the backend server
  4. The model calls get_tools_by_server to get all tools available on a specific backend
  5. 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)