Skip to main content
Glama

multi-mcp

A production-ready MCP proxy server that aggregates multiple backend MCP servers into a single endpoint — with lazy loading, per-tool filtering, and a unified YAML config that doubles as a live control plane.

All your AI tools → multi-mcp → github, obsidian, exa, tavily, context7, ...

Why

Most MCP setups require configuring every server individually in every tool (Claude Code, Codex, Cursor, etc.). Each server starts eagerly at boot. You have no easy way to disable specific tools from a server you otherwise want.

multi-mcp solves all three:

  • One endpoint — configure it once, every tool connects to multi-mcp

  • Lazy loading — servers only connect when a tool is actually called

  • Tool control — flip enabled: false on any individual tool in a YAML file


Related MCP server: MCP Manager

Features

  • Unified YAML config — single file serves as cache, config, and control plane

  • Startup discovery — connects to every server briefly at first run, caches tool lists, disconnects lazy servers

  • Lazy loading — lazy servers reconnect on first tool call, auto-disconnect after idle timeout

  • Always-on servers — stays connected permanently, auto-reconnects if dropped

  • Per-tool enable/disable — expose exactly the tools you want from each server

  • Smart refresh — re-discovers tools without overwriting your settings

  • Stale tool cleanup — tools that disappear from a server and were disabled get pruned automatically

  • Supports all transports — stdio, SSE, and Streamable HTTP (2025 spec)

  • Tool namespacingserver::tool_name prevents conflicts across servers

  • Runtime HTTP API — add/remove servers without restarting (SSE mode)

  • Audit logging — JSONL log of every tool call

  • API key auth — optional Bearer token for SSE mode


Quick Start

Requirements: Python 3.10+, uv

git clone https://github.com/itstanner5216/multi-mcp
cd multi-mcp
uv sync

First run — auto-discovers all your servers and writes ~/.config/multi-mcp/servers.yaml:

uv run python main.py start

Or refresh manually to re-discover tools and update the YAML:

uv run python main.py refresh

Config

On first run, multi-mcp creates ~/.config/multi-mcp/servers.yaml by connecting to every server you've configured, fetching its tool list, then disconnecting. The resulting file looks like:

servers:
  github:
    command: /path/to/run-github.sh
    always_on: true          # stays connected at all times
    idle_timeout_minutes: 5
    tools:
      search_repositories:
        enabled: true
      delete_repository:
        enabled: false        # hidden from all AI tools
      create_gist:
        enabled: false

  exa:
    url: https://mcp.exa.ai/mcp?tools=web_search_exa,get_code_context_exa
    always_on: false          # lazy: connects only when called
    idle_timeout_minutes: 5
    tools:
      web_search_exa:
        enabled: true
      linkedin_search_exa:
        enabled: false        # don't need this

  obsidian:
    command: /path/to/run-obsidian.sh
    always_on: true
    tools: {}                 # auto-populated on first run

Tool control rules:

State

Behavior

enabled: true

Exposed to AI

enabled: false

Hidden — setting is never overwritten by refresh

Tool disappears from server

Marked stale: true, your setting preserved

stale: true + enabled: false

Cleaned up on next refresh

No tools key

All tools pass through (default)

To disable a tool, just set enabled: false and save. Takes effect on next multi-mcp start.


CLI

# Start the proxy (stdio mode — used by Claude Code, Codex, etc.)
uv run python main.py start

# Start in SSE mode (network accessible)
uv run python main.py start --transport sse --port 8085

# Re-discover tools from all servers, smart-merge into YAML
uv run python main.py refresh

# Re-discover tools from one server only
uv run python main.py refresh github

# Show server status and tool counts
uv run python main.py status

# List all tools with enabled/disabled status
uv run python main.py list

# Filter to one server
uv run python main.py list --server github

# Show only disabled tools
uv run python main.py list --disabled

Connecting Your AI Tools

Once multi-mcp is running, replace all individual server entries in your tool configs with a single entry:

Claude Code / Cursor / any JSON-based config:

{
  "mcpServers": {
    "multi-mcp": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "--project", "/path/to/multi-mcp", "python", "main.py", "start"]
    }
  }
}

SSE mode (if running as a background service):

{
  "mcpServers": {
    "multi-mcp": {
      "type": "sse",
      "url": "http://localhost:8085/sse"
    }
  }
}

Transport Support

multi-mcp connects to backend servers over any transport:

Transport

Backend config

Notes

stdio

command: /path/to/server

Local subprocess

Streamable HTTP

url: https://...

Current MCP spec (POST)

SSE

url: https://...

Legacy SSE (GET), auto-fallback

For url-based servers, multi-mcp tries Streamable HTTP first and falls back to legacy SSE automatically.


Runtime API (SSE mode)

When running with --transport sse, a management API is available:

# List active servers
GET /mcp_servers

# Add a server at runtime
POST /mcp_servers
{"name": "new-server", "command": "/path/to/server"}

# Remove a server
DELETE /mcp_servers/{name}

# List all tools by server
GET /mcp_tools

# Health check
GET /health

Authenticate with Authorization: Bearer <key> (set MULTI_MCP_API_KEY env var to enable).


Architecture

┌──────────────────────────────────────────────────┐
│  Claude Code / Codex / Cursor / any MCP client   │
└─────────────────────┬────────────────────────────┘
                      │ stdio or SSE
              ┌───────▼────────┐
              │   multi-mcp    │
              │                │
              │ • YAML config  │
              │ • namespacing  │
              │ • tool filter  │
              │ • lazy loading │
              │ • audit log    │
              └──┬──────┬──────┘
                 │      │
    ┌────────────┘      └──────────────┐
    │                                  │
┌───▼──────────┐              ┌────────▼──────┐
│ always_on    │              │     lazy      │
│              │              │               │
│ github       │              │ exa (SSE)     │
│ obsidian     │              │ tavily        │
│              │              │ context7      │
│ (connected   │              │ seq-thinking  │
│  always)     │              │               │
└──────────────┘              │ (connects on  │
                              │  first call,  │
                              │  disconnects  │
                              │  after idle)  │
                              └───────────────┘

Development

# Run tests
uv run python -m pytest

# Run specific test file
uv run python -m pytest tests/test_cache_manager.py -v

# Check what's configured
uv run python main.py status
uv run python main.py list

Test coverage: 30 tests across YAML config, merge logic, startup discovery, idle timeout, startup flow, CLI, and reconnect behavior.


Environment Variables

Variable

Description

MULTI_MCP_API_KEY

Bearer token for SSE API auth

MULTI_MCP_HOST

SSE bind host (default: 127.0.0.1)

MULTI_MCP_PORT

SSE bind port (default: 8085)

MULTI_MCP_LOG_LEVEL

Log level: DEBUG, INFO, WARNING, ERROR


License

MIT

Available Tools

3 tools
calculator__addB

Add two numbers

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. 'Add two numbers' implies a simple computation, but it doesn't disclose any behavioral traits such as error handling, input validation, or performance characteristics. This leaves significant gaps in understanding how the tool behaves beyond its basic function.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise with just three words, front-loading the core action ('Add') without any wasted text. Every word earns its place by directly conveying the tool's purpose, making it efficient and easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (a simple addition function) and no output schema, the description is minimally complete. It states what the tool does but lacks details on usage, behavior, or return values. For such a straightforward tool, this might be adequate, but it doesn't provide full context for reliable agent invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0 parameters with 100% coverage, meaning no parameters are documented in the schema. The description 'Add two numbers' implies two numeric inputs, adding semantic meaning about what the tool expects, which compensates for the lack of schema parameters. However, it doesn't specify parameter names or formats, so it's not fully detailed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Add two numbers' clearly states the tool's purpose with a specific verb ('Add') and resource ('two numbers'), making it immediately understandable. However, it doesn't explicitly distinguish this from its sibling 'calculator__multiply', which performs a different arithmetic operation, so it doesn't fully achieve sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention the sibling 'calculator__multiply' for multiplication needs or 'weather__get_weather' for unrelated tasks, nor does it specify any context or prerequisites for addition operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

calculator__multiplyB

Multiply two numbers

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. 'Multiply two numbers' implies a computational operation but doesn't specify behavioral traits like error handling (e.g., overflow), input constraints (e.g., numeric types), or output format. For a tool with zero annotation coverage, this is a significant gap in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise with 'Multiply two numbers,' a single sentence that front-loads the core purpose without any wasted words. Every part of the sentence earns its place by clearly stating the action and resource.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (a simple multiplication operation) and no output schema, the description is minimally complete but lacks details on behavior and usage. Without annotations or output schema, it should provide more context on how the tool works and what it returns, but it's adequate for basic understanding.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0 parameters with 100% coverage, meaning no parameters are defined in the schema. The description mentions 'two numbers,' which implies two inputs, but since the schema explicitly defines no properties, this is a minor semantic addition. Baseline is 4 for 0 parameters, as there's nothing for the description to compensate for.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Multiply two numbers' clearly states the verb ('multiply') and resource ('two numbers'), making the purpose immediately understandable. It distinguishes from sibling tools like 'calculator__add' by specifying multiplication rather than addition. However, it doesn't explicitly differentiate from other potential mathematical operations beyond the named siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention when multiplication is appropriate compared to addition or other operations, nor does it reference the sibling tools or any contextual prerequisites. Usage is implied by the tool name but not explicitly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

weather__get_weatherC

Get weather for location via HTTP call.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It mentions an HTTP call, hinting at network behavior, but doesn't disclose critical traits like error handling, rate limits, authentication needs, or what happens if the location is invalid. This leaves significant gaps for a tool that likely interacts with an external API.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence with no wasted words. It's front-loaded with the core action ('Get weather for location') and adds a useful detail ('via HTTP call'). However, it could be slightly more informative without losing conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (an HTTP-based weather tool with no output schema and no annotations), the description is incomplete. It lacks details on what weather data is returned, how location is specified (implied but not stated), error cases, or behavioral constraints. This makes it inadequate for reliable agent use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0 parameters with 100% coverage, so no parameters need documentation. The description doesn't add param info, but that's acceptable here. Baseline is 4 for zero parameters, as the schema fully covers the absence of inputs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the tool's purpose ('Get weather for location') and the mechanism ('via HTTP call'), which is clear but vague. It doesn't specify what weather data is retrieved (e.g., temperature, conditions) or how the location is determined, and it doesn't distinguish from siblings (calculator tools), though they are unrelated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention any prerequisites, context for location input, or comparisons to other weather-related tools (none listed as siblings, but this is a generic gap). Usage is implied only by the purpose statement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

B3/5.0
Disambiguation5/5

The three tools have clearly distinct purposes: two are for mathematical operations (addition and multiplication) and one is for weather retrieval. There is no overlap or ambiguity between these functions, making it easy for an agent to select the correct tool.

Naming Consistency3/5

The naming is mixed: 'calculator__add' and 'calculator__multiply' follow a consistent 'domain__verb_noun' pattern, but 'weather__get_weather' uses a different structure with a redundant 'weather' term. This inconsistency reduces predictability, though the names remain readable.

Tool Count2/5

With only three tools, the server feels thin and under-scoped for a 'Multi MCP' name that suggests broader functionality. The tools cover two unrelated domains (calculator and weather), lacking depth in either area, which may limit agent effectiveness.

Completeness2/5

The tool surface is severely incomplete. For the calculator domain, basic operations like subtraction and division are missing, and for weather, there are no tools for forecasts or historical data. This creates significant gaps that will likely cause agent failures in handling related tasks.

Maintenance

ActivityInactive
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A dynamic proxy server that enables users to manage and access multiple MCP backend servers through a single, unified interface. It supports both static and runtime server configuration with persistent storage and works with HTTP and SSE transports.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Self-hosted MCP proxy and aggregation platform. Register multiple upstream MCP servers and expose them through a single unified endpoint with namespace routing, multi-transport support (HTTP/SSE, stdio, OpenAPI→MCP), per-tool overrides, and a web admin UI.
    16
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Proxy-style MCP tool multiplexer that aggregates multiple downstream stdio MCP servers into one, offering meta-tools for status, search, call, parallel, batch, and pipeline operations with concurrency control and caching.
  • A
    license
    Not graded
    quality
    C
    maintenance
    A flexible MCP proxy server that connects to and routes between multiple backend MCP servers over STDIO or SSE, enabling dynamic management and namespacing of tools.
    110
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/itstanner5216/multi-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server