Skip to main content
Glama

MCP Manager

MCP Manager exposes multiple MCP servers through one Streamable HTTP gateway. The gateway provides a single client endpoint, namespaces backend tools, and routes each call to either a registered local server host or a remote MCP server.

The default profile enables the Arxiv and calculator servers.

Architecture

                              +--> server-host --> stdio MCP server
MCP client --> MCP gateway ---+--> server-host --> stdio MCP server
                              +--> remote Streamable HTTP MCP server
  • Clients connect to the gateway at http://<gateway>:8080/mcp.

  • The gateway loads a profile, discovers tools, exposes them with each manifest's configured namespace and separator, and routes calls to healthy backends. The default separator is __; Atlas manifests use _.

  • A server-host process owns one stdio MCP child, exposes it over Streamable HTTP, and registers it with the gateway. The gateway never starts stdio processes itself.

  • Remote Streamable HTTP backends are contacted directly and do not need a server-host process.

  • Catalog manifests describe how servers run; profiles decide which servers and tools a deployment exposes.

See docs/ARCHITECTURE.md for the runtime and security boundaries.

Related MCP server: MCP Gateway

Repository components

Location

Purpose

catalog/servers/

One server manifest per MCP backend: transport, command or URL, environment, lifecycle, concurrency, credentials, and tool namespace.

profiles/

Deployment profiles that select servers and apply tool and credential policies.

src/mcp_manager/gateway/

The client-facing MCP gateway, tool registry, and registration API.

src/mcp_manager/host/

The HTTP host used to run and supervise one stdio MCP server.

src/mcp_manager/runtime/

Backend connections, routing, concurrency, and subprocess supervision.

src/mcp_manager/config/

Typed models and YAML configuration loading.

services/

Local adapters for MCP servers that need repository-specific behavior.

scripts/

Convenience launchers for the gateway and server hosts.

examples/

Curl and Python clients for discovery and tool calls.

Backend-specific profiles, credentials, and examples are documented in profiles/README.md.

Deploy the gateway and MCP servers

Install Python 3.11 or newer and uv, then install the project:

uv sync --extra dev

Node.js 20 or newer is also required for profiles that use Node-based servers. Package runners such as uvx and npx may download a pinned backend the first time it starts.

Launch with the convenience scripts

The launchers bind on all interfaces, derive the advertised address from the first value returned by hostname -i, and share gateway.json in the repository root. Override MCP_MANAGER_ADVERTISE_HOST when the first address is not reachable by peers.

Start the default Arxiv-and-calculator gateway on the current machine:

MCP_MANAGER_PROFILE=profiles/default.yaml scripts/run_gateway.sh

For a local deployment, start one host per selected stdio server in separate terminals. Hosts on the same IP require distinct ports:

MCP_MANAGER_ADVERTISE_HOST=127.0.0.1 \
  MCP_MANAGER_SERVER_PORT=9001 scripts/run_mcp_servers.sh arxiv

MCP_MANAGER_ADVERTISE_HOST=127.0.0.1 \
  MCP_MANAGER_SERVER_PORT=9002 scripts/run_mcp_servers.sh calculator

For the Brain cluster, allocate one CPU machine per server. Each allocated machine has its own IP, so every host may use the default port 9001:

scripts/allocate_cpu.sh arxiv
scripts/allocate_cpu.sh calculator

The allocator reads spec.resources.cpu and spec.resources.memoryMiB from the selected stdio server's catalog manifest. Override either value for a particular launch when needed:

MCP_MANAGER_CPU=16 MCP_MANAGER_MEMORY_MIB=32000 \
  scripts/allocate_cpu.sh arxiv

The lookup uses the validated mcp-manager server-resources command rather than parsing YAML in shell. Environment overrides take precedence over the manifest values.

The gateway and hosts automatically append the cluster route 100.96.0.0/12 to NO_PROXY and no_proxy. Internal registration and MCP connections also disable HTTPX environment proxies directly. Override the route with MCP_MANAGER_CLUSTER_NO_PROXY if the deployment network changes.

The discovery file contains the gateway URL and a new generation ID on each gateway startup. Hosts reread it before every registration attempt, retain the last valid record during filesystem errors, and reconnect after a gateway URL change. A host keeps its stdio child alive while the gateway is unavailable.

Useful overrides are:

Variable

Default

Purpose

MCP_MANAGER_PROFILE

profiles/all.yaml

Gateway profile to expose.

MCP_MANAGER_GATEWAY_PORT

8080

Gateway listen and advertised port.

MCP_MANAGER_SERVER_PORT

9001

One server-host listen and advertised port.

MCP_MANAGER_CPU

catalog spec.resources.cpu

Per-launch CPU allocation override.

MCP_MANAGER_MEMORY_MIB

catalog spec.resources.memoryMiB

Per-launch memory allocation override.

MCP_MANAGER_GATEWAY_DISCOVERY_FILE

<repo>/gateway.json

Shared discovery record.

MCP_MANAGER_ADVERTISE_HOST

first hostname -i address

Peer-reachable hostname or IP.

MCP_MANAGER_CLUSTER_NO_PROXY

100.96.0.0/12

Private cluster route.

The gateway can start before its hosts. /health reports process liveness; /ready remains HTTP 503 until every backend selected by the profile has a ready instance. A standalone host's /health checks its local MCP child, while its /ready additionally requires successful gateway registration.

Verify and call the deployment

Set the addresses reported by hostname -i or brainctl get process:

GATEWAY_IP=100.104.35.33
ARXIV_IP=100.100.90.20

Check the gateway and direct Arxiv host:

curl --noproxy '*' "http://$GATEWAY_IP:8080/health"
curl --noproxy '*' "http://$GATEWAY_IP:8080/ready"
curl --noproxy '*' "http://$ARXIV_IP:9001/health"
curl --noproxy '*' "http://$ARXIV_IP:9001/ready"

uv run python examples/list_mcp_tools.py \
  --url "http://$ARXIV_IP:9001/mcp"

List only the gateway's namespaced Arxiv tools:

curl --noproxy '*' --fail --silent --show-error \
  -X POST "http://$GATEWAY_IP:8080/mcp" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list",
    "params": {"_meta": {"servers": ["arxiv"]}}
  }' | python -m json.tool

Search Arxiv through the gateway:

curl --noproxy '*' --fail --silent --show-error \
  -X POST "http://$GATEWAY_IP:8080/mcp" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "arxiv_search_papers",
      "arguments": {
        "query": "\"attention mechanism\"",
        "max_results": 5,
        "sort_by": "relevance"
      }
    }
  }' | python -m json.tool

Call the calculator or run the 1000-request concurrency test:

curl --noproxy '*' --fail --silent --show-error \
  -X POST "http://$GATEWAY_IP:8080/mcp" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "calculator_calculate",
      "arguments": {"expression": "88 * 2345"}
    }
  }' | python -m json.tool

uv run python examples/load_test_calculator.py \
  --url "http://$GATEWAY_IP:8080/mcp" \
  --requests 1000 --concurrency 32 --expression '88 * 2345'

The calculator expression returns 206360. The load tester reports success and failure counts, throughput, end-to-end p50/p95/p99 latency, and a sample MCP response. It exits nonzero if any request fails.

Use request-scoped credentials

Credentialed backends receive API keys from the MCP client on each request. The real key is never stored in a catalog manifest or profile. It belongs at:

params._meta.credentials.<server_name>.<credential_field>

For example, start a gateway that exposes the hosted GitHub MCP server:

MCP_MANAGER_PROFILE=profiles/github.yaml scripts/run_gateway.sh

Keep the token in the client process environment and list the GitHub tools:

export GITHUB_TOKEN='<your-github-token>'

uv run python examples/list_mcp_tools.py \
  --url "http://$GATEWAY_IP:8080/mcp" \
  --server github \
  --credential-env github=GITHUB_TOKEN

--credential-env is a client-side convenience: it reads GITHUB_TOKEN and adds it to params._meta.credentials.github.apiKey. The gateway does not read that environment variable. The equivalent tools/call request is:

curl --noproxy '*' --fail --silent --show-error \
  -X POST "http://$GATEWAY_IP:8080/mcp" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data-binary @- <<JSON
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "_meta": {
      "credentials": {
        "github": {"apiKey": "${GITHUB_TOKEN}"}
      }
    },
    "name": "github__get_me",
    "arguments": {}
  }
}
JSON

A single-field server can receive up to 64 interchangeable keys in one call:

{
  "_meta": {
    "credentials": {
      "github": {"apiKey": ["<github-token-1>", "<github-token-2>"]}
    }
  }
}

For a rate-limited server, the first applicable policy atomically chooses the offered key with the earliest next admission time. Any later applicable policies admit that same key. This lets an immediately available key run instead of waiting behind a recently used key. When no rate-limit policy is configured, all keys are equally available and calls rotate across them. A retry performs selection again. Repeating --credential-env for the same server and field builds the equivalent pool in the example client.

Send the declared fields on both credential-dependent tools/list and tools/call requests. A tools/list request may include credentials for multiple servers so their tools can be discovered together. Each tools/call invokes one tool and may include credentials only for that tool's routed server. Discovery uses the first offered key and does not consume rate-limit admission. Multi-field backends use the same structure—for example, credentials.oxylabs.username and credentials.oxylabs.password. See profiles/README.md for every included server's field names and more examples.

If a shared filesystem is unavailable, use explicit --gateway-url and --advertise-url values instead of the discovery-file options. Remote HTTP entries such as GitHub and Hugging Face do not need a server-host process. The registration API is unauthenticated, so expose it only on a trusted private network or place an authenticating proxy in front of it.

Modify the configuration

Configuration is split into two layers:

  1. A file in catalog/servers/ defines a backend and how to connect to it.

  2. A file in profiles/ selects catalog entries and controls which tools and credential uses are allowed for one deployment.

For example, this profile exposes every Arxiv tool but only the calculator's calculate tool:

apiVersion: mcp.manager/v1alpha1
kind: MCPProfile

metadata:
  name: example

spec:
  servers:
    - serverRef: arxiv
      tools:
        allow: []       # empty means all discovered tools
        deny: []

    - serverRef: calculator
      tools:
        allow: [calculate]
        deny: []

To change a deployment:

  1. Copy or edit a profile under profiles/.

  2. Add or remove serverRef entries and adjust tools.allow/tools.deny.

  3. Start a server-host for every selected stdio entry. Add a manifest under catalog/servers/ first if the backend is new.

  4. Validate the result, then restart the gateway. Restart a host as well when its catalog manifest changed.

uv run mcp-manager --profile profiles/example.yaml list-servers
uv run mcp-manager --profile profiles/example.yaml doctor

Server manifests can define stdio commands, remote HTTP URLs, non-secret fixed environment values, request-scoped credential slots, lifecycle policy, and concurrency limits. See docs/ADDING_SERVERS.md for the complete schema patterns.

Maintenance

ActivityMaintained
ResponsivenessNo issues

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

  • F
    license
    C
    quality
    D
    maintenance
    A powerful gateway for the Model Context Protocol (MCP) that unifies AI toolchains by federating multiple MCP servers, wrapping REST APIs as MCP tools, and supporting multiple transport methods with an admin dashboard.
    1
  • A
    license
    Not graded
    quality
    C
    maintenance
    Aggregates multiple Model Context Protocol servers into a single gateway to provide unified search, description, and execution of tools. It reduces context limit issues by dynamically fetching specific tool schemas only when needed rather than loading all available tools at once.
    12
    23
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Self-hosted MCP gateway that exposes a single MCP URL to AI agents and routes tools/resources to many upstream MCP servers behind it.
    3,958
    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/Feanus/mcp-manager'

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