LABSCO SUMMARY
Tool-level selection is the reason to put a proxy in front of your servers.
Five servers behind one endpoint is convenient; picking which of their tools reach the model is what stops the context window filling with tools nobody calls, and the shipped filter middleware exists for exactly that. Environment variable references are the other detail worth noting — secrets resolve from the container's environment at runtime, so they never land in a config file or a git repository.
What it is
An MCP proxy that composes several servers into a single one. You define servers, group them into namespaces, apply middleware, and publish each namespace as an endpoint. Because the result is itself an MCP server, any client can consume it — and MetaMCP is itself a Docker deployment you run.
What you get
- Namespaces that group servers, with servers enabled or disabled individually and at tool level, so you can remix a large surface into just the tools a client needs
- Endpoints assigned to a namespace and served over SSE, Streamable HTTP, or OpenAPI for clients like Open WebUI — one click to switch which namespace an endpoint points at
- Authentication per endpoint: API key in a header or query parameter, or standard OAuth in MCP Spec 2025-06-18
- Middleware that intercepts and transforms requests and responses at namespace level, shipping with a filter-inactive-tools example that trims tool context for the model
- Tool overrides per namespace: rename, retitle or re-describe a tool and attach custom MCP annotations such as
{ "annotations": { "readOnlyHint": false } }, merged with what the upstream server returns - A built-in inspector with your saved server configs, so you can debug your own endpoints without a separate tool
- Secret handling for STDIO servers: raw values,
${ENV_VAR_NAME}references resolved from the container's environment at runtime, or auto-matching by name so nothing goes in the config at all
Requirements
Docker. Clone the repository, copy example.env to .env, and docker compose up -d; CORS is enforced against APP_URL, so access it only from that address. Local development with pnpm and a Postgres container is supported, as are Dev Containers in VSCode or Cursor. Tools, resources and prompts are all supported, and OAuth-enabled upstream servers have been tested. MIT licensed.
Setup effort
Run a container — build the image from the repository, then point your client at it
USE CASES
01
Giving a client one server instead of eight
Group the servers into a namespace, publish it as an endpoint, and point the client at that URL — switching what is behind it later is a namespace change, not a client reconfiguration.
02
Cutting a bloated tool list down to what matters
Disable servers or individual tools inside the namespace, and apply the filter middleware so inactive tools never reach the model's context.
03
Making a confusing upstream tool readable
Override its name, title or description for that namespace and attach annotations — merged with the upstream metadata rather than replacing it.
04
Exposing MCP servers to a team safely
Put an endpoint behind API-key or OAuth authentication, and keep secrets out of the config by referencing container environment variables.
05
Debugging an endpoint you just built
Use the built-in inspector against your saved configuration rather than reconstructing the setup in a separate tool.
BEFORE YOU INSTALL
What to know first
Requires
- Docker with docker compose
- A MetaMCP API key (sk_mt_…) created in your own MetaMCP instance, for endpoints set to API-key auth — the mcp-proxy client entries pass it as API_ACCESS_TOKEN
Where it runs
All 4 documented clients run the server on your machine.
INSTALLATION
Connect your client
Server setup
TERMINAL
git clone https://github.com/metatool-ai/metamcp.git && cd metamcp && cp example.env .env && docker compose up -dMCP Clients
Cursor
CURSOR · JSON
{
"mcpServers": {
"MetaMCP": {
"url": "http://localhost:12008/metamcp/<YOUR_ENDPOINT_NAME>/sse"
}
}
}Claude Desktop — mcp-proxy, Other MCP clients — mcp-proxy
JSON
{
"mcpServers": {
"MetaMCP": {
"command": "uvx",
"args": [
"mcp-proxy",
"--transport",
"streamablehttp",
"http://localhost:12008/metamcp/<YOUR_ENDPOINT_NAME>/mcp"
],
"env": {
"API_ACCESS_TOKEN": "<YOUR_API_ACCESS_TOKEN>"
}
}
}
}Open WebUI
Open WebUI reads MetaMCP's OpenAPI endpoint, not an mcpServers file. Open Settings → Integrations and click ➕ in the Tools section to add a tool server.
Enter this URL, then click Save (<YOUR_ENDPOINT_NAME> is your MetaMCP endpoint name):
OPEN WEBUI · URL
http://localhost:12008/metamcp/<YOUR_ENDPOINT_NAME>/api