/ Directory / Playground / mcp-proxy
● Community tbxark ⚡ Instant

mcp-proxy

by tbxark · tbxark/mcp-proxy

Aggregate many MCP servers behind one HTTP endpoint — cut client config from 20 entries to 1, share MCPs across your team.

mcp-proxy by tbxark fronts any number of upstream MCP servers (stdio, SSE, or streamable HTTP) and exposes them through a single HTTP endpoint. Useful when you want one URL your whole team (or multiple AI clients) can point at, instead of re-configuring every server on every machine.

Why use it

Key features

Live Demo

What it looks like in practice

proxy-2.replay ▶ ready
0/0

Install

Pick your client

~/Library/Application Support/Claude/claude_desktop_config.json  · Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "proxy-2": {
      "command": "TODO",
      "args": [
        "See README: https://github.com/tbxark/mcp-proxy"
      ],
      "_inferred": true
    }
  }
}

Open Claude Desktop → Settings → Developer → Edit Config. Restart after saving.

~/.cursor/mcp.json · .cursor/mcp.json
{
  "mcpServers": {
    "proxy-2": {
      "command": "TODO",
      "args": [
        "See README: https://github.com/tbxark/mcp-proxy"
      ],
      "_inferred": true
    }
  }
}

Cursor uses the same mcpServers schema as Claude Desktop. Project config wins over global.

VS Code → Cline → MCP Servers → Edit
{
  "mcpServers": {
    "proxy-2": {
      "command": "TODO",
      "args": [
        "See README: https://github.com/tbxark/mcp-proxy"
      ],
      "_inferred": true
    }
  }
}

Click the MCP Servers icon in the Cline sidebar, then "Edit Configuration".

~/.codeium/windsurf/mcp_config.json
{
  "mcpServers": {
    "proxy-2": {
      "command": "TODO",
      "args": [
        "See README: https://github.com/tbxark/mcp-proxy"
      ],
      "_inferred": true
    }
  }
}

Same shape as Claude Desktop. Restart Windsurf to pick up changes.

~/.continue/config.json
{
  "mcpServers": [
    {
      "name": "proxy-2",
      "command": "TODO",
      "args": [
        "See README: https://github.com/tbxark/mcp-proxy"
      ]
    }
  ]
}

Continue uses an array of server objects rather than a map.

~/.config/zed/settings.json
{
  "context_servers": {
    "proxy-2": {
      "command": {
        "path": "TODO",
        "args": [
          "See README: https://github.com/tbxark/mcp-proxy"
        ]
      }
    }
  }
}

Add to context_servers. Zed hot-reloads on save.

claude mcp add proxy-2 -- TODO 'See README: https://github.com/tbxark/mcp-proxy'

One-liner. Verify with claude mcp list. Remove with claude mcp remove.

Use Cases

Real-world ways to use mcp-proxy

How to run a shared MCP gateway for your team

👤 Platform/DevEx engineers tired of onboarding each teammate to 10 MCPs ⏱ ~30 min intermediate

When to use: You've found 5+ MCPs that everyone on the team should use, and re-explaining the stdio config to each hire is eating your week.

Prerequisites
  • A VM or container host reachable by every team member — Any small EC2/Fly/Hetzner box; 512MB RAM is plenty
  • Docker installed on that host — curl -fsSL https://get.docker.com | sh
Flow
  1. Write a config.json listing every upstream MCP the team needs
    Draft a mcp-proxy config.json that aggregates github, sentry, postgres (read-only replica), and filesystem (scoped to /data). Give each a unique namespace.✓ Copied
    → Valid config with namespaced server entries
  2. Run mcp-proxy in Docker on the shared host
    Write the docker run command to launch ghcr.io/tbxark/mcp-proxy on port 9090 mounting config.json, with restart=always and a healthcheck.✓ Copied
    → Container stays up; /health returns 200
  3. Give teammates one URL to paste into every client
    Write a 5-line onboarding snippet teammates paste into Claude Desktop's config to point at our shared proxy URL.✓ Copied
    → Any teammate gets all upstream tools in one step

Outcome: New hires reach full MCP parity in 2 minutes by pasting one URL; upgrades happen in one place.

Pitfalls
  • Putting the proxy on the public internet without auth — Terminate TLS and auth at a reverse proxy (Caddy/nginx/Cloudflare) in front — mcp-proxy has no auth layer
  • Upstream tool names collide (two servers both expose get_issue) — Use namespacing so clients see github.get_issue vs gitlab.get_issue
Combine with: github · sentry · postgres

Expose a local stdio MCP to a remote IDE via HTTP

👤 Developers using a cloud IDE that can't spawn stdio processes ⏱ ~15 min beginner

When to use: Your client only speaks HTTP/SSE but the MCP you need is stdio-only.

Flow
  1. Run mcp-proxy locally wrapping the stdio server
    Generate an mcp-proxy config that wraps npx -y @modelcontextprotocol/server-filesystem /tmp as an SSE endpoint on :9090.✓ Copied
    → curl http://localhost:9090 returns MCP metadata
  2. Tunnel the port to a public URL
    Give me a one-liner with cloudflared or ngrok to expose :9090.✓ Copied
    → Public HTTPS URL
  3. Point the remote IDE at the SSE URL
    Write the IDE config entry to consume this as an SSE MCP server.✓ Copied
    → Tools appear in the remote IDE

Outcome: A stdio-only MCP reachable from any HTTP-capable client.

Pitfalls
  • Public tunnels are open to the world while live — Use cloudflared with Access policies or add a shared-secret header
Combine with: filesystem

Upgrade an MCP for the whole team without touching client configs

👤 Team leads rolling out MCP version bumps ⏱ ~10 min beginner

When to use: A security-fix version of an upstream MCP drops and you need everyone on it today.

Flow
  1. Bump the version in the central mcp-proxy config
    Update my mcp-proxy config to pin github-mcp-server to v0.4.2 and reload.✓ Copied
    → New version live on the proxy
  2. Verify tools still respond
    Hit the proxy's list_tools and confirm github.* tools are present with the new server version.✓ Copied
    → Tool list unchanged from consumer perspective

Outcome: Silent upgrade — teammates pick up the new version on next tool call, no client restart needed.

Pitfalls
  • New version renamed a tool and broke downstream prompts — Read the upstream changelog before pinning; keep previous version configured briefly for overlap

Combinations

Pair with other MCPs for X10 leverage

proxy-2 + github + sentry

Put both behind one proxy so teammates don't juggle two tokens in two configs

Configure mcp-proxy to front both github and sentry MCP servers, loading credentials from a single .env file the host reads.✓ Copied
proxy-2 + agent

Compare vs 1mcp-app/agent — both aggregate, different tradeoffs (Go vs Node, OAuth vs none)

Set up mcp-proxy alongside 1mcp-app/agent on the same host and benchmark tool-call latency through each.✓ Copied

Tools

What this MCP exposes

ToolInputsWhen to callCost
list_tools (none) Client-side — proxy handles automatically on MCP handshake free
call_tool name: str (optionally namespaced), args: object Any tool invocation — proxy routes by name/namespace 1 upstream call

Cost & Limits

What this costs to run

API quota
No own quota; passes through upstream server limits
Tokens per call
Negligible overhead beyond the upstream response
Monetary
Free, MIT licensed
Tip
Run on a tiny box — 512MB RAM handles dozens of upstreams. Real cost is upstream API fees.

Security

Permissions, secrets, blast radius

Credential storage: Upstream credentials in host env vars or config.json; keep config.json out of git
Data egress: Proxy forwards to whichever upstream servers you configure; no telemetry back to tbxark
Never grant: Exposing the proxy to the public internet without an auth layer in front

Troubleshooting

Common errors and fixes

Upstream server failed to start

Check the command path in config.json is absolute or on the container PATH. docker exec in and run manually.

Verify: docker logs <proxy-container>
Tool call returns 'tool not found' but list_tools shows it

Namespace mismatch — with namespacing on, clients must call server.tool_name, not tool_name.

Verify: curl http://proxy:9090/tools | jq
SSE connection drops every 30s

Reverse proxy idle timeout too short. Raise to 5 min or disable buffering for /sse paths.

Verify: nginx/Caddy log shows client timeout
Docker container exits immediately

Config JSON invalid. Validate with jq before starting.

Verify: docker logs shows JSON parse error

Alternatives

mcp-proxy vs others

AlternativeWhen to use it insteadTradeoff
1mcp-app/agentYou want OAuth 2.1 and scope-based auth built inHeavier footprint, Node-based vs Go
Hyprmcp JetskiYou need analytics and prompt-level visibility on top of aggregationRequires Kubernetes/PostgreSQL — overkill for small teams
Direct client-side configsTeam is 1-3 people and you rarely change serversZero infra, but every change is N updates

More

Resources

📖 Read the official README on GitHub

🐙 Browse open issues

🔍 Browse all 400+ MCP servers and Skills