Skip to content

One gateway for all your MCP servers

Register Streamable HTTP MCP servers, compose them into bundles, and expose each bundle through endpoints shaped for claude.ai, ChatGPT or your own scripts. Self-hosted, restart-safe, horizontally scalable.

bundlemcp: unified mcp server bundler

Upstream MCP servers

Streamable HTTP, probed and cached

weather
forecastcurrent
notes
searchcreate
crm
lookupupdate

One bundle

Prefixed, curated, renamed

assistant
  • weather__forecast
  • weather__current
  • notes__search
  • add_notewas notes__create
  • crm__lookup
  • crm__updatedisabled

Endpoints per client

Same tools, three contracts

/assistant/mcp
claude.ai · OAuth 2.1
profile: claude
/assistant-gpt/mcp
ChatGPT · OAuth 2.1
profile: chatgpt, tools re-annotated read-only
/assistant-ci/mcp
scripts & agents · API key
profile: default, 120 calls/min per key

Every tool call passes the endpoint's auth, the bundle's curation, the client profile, the optional metering hook, and lands in the audit log. Sessions live in Valkey, so any replica serves any client.

See it run ​

Ten minutes from clone to a working bundle, with Docker and ports 8000, 3000 and 8080 free. The compose stack ships a demo server, bundle and endpoint, so the first call needs nothing but a key.

bash
git clone https://github.com/mhoegger/bundlemcp.git && cd bundlemcp
cp deploy/.env.example deploy/.env
docker compose -f deploy/docker-compose.yml --env-file deploy/.env \
  up -d --build --wait --wait-timeout 300
bash
KEY=bmcp_sk_devservicekey000000000000000000000000
V=2026-07-28
curl -s -N http://localhost:8000/demo/mcp \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: $V" -H "Mcp-Method: tools/call" \
  -H "Mcp-Name: echo__reverse" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{
       "name":"echo__reverse","arguments":{"text":"bundlemcp"},
       "_meta":{"io.modelcontextprotocol/protocolVersion":"'"$V"'",
                "io.modelcontextprotocol/clientCapabilities":{}}}}'
json
// arrives as the last `data:` event of an SSE stream
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": { "content": [{ "type": "text", "text": "pcmeldnub" }] }
}

An MCP SDK builds that envelope for you — the headers and _meta above are what a hand-rolled client has to send. See Request envelope.

Then open the admin UI at localhost:3000, register your own servers, and connect claude.ai with an OAuth endpoint. The whole path is in the Quickstart.

Specs, architecture records and diagrams live in the repository.