
MetaMCP
STDIOAggregate multiple MCP servers into unified endpoints with customizable middlewares
Aggregate multiple MCP servers into unified endpoints with customizable middlewares
MetaMCP is a MCP proxy that lets you dynamically aggregate MCP servers into a unified MCP server, and apply middlewares. MetaMCP itself is a MCP server so it can be easily plugged into ANY MCP clients.
For more details, consider visiting our documentation site: https://docs.metamcp.com
English | 中文
Generally developers can use MetaMCP as infrastructure to host dynamically composed MCP servers through a unified endpoint, and build agents on top of it.
Quick demo video: https://youtu.be/Cf6jVd2saAs
A MCP server configuration that tells MetaMCP how to start a MCP server.
"HackerNews": { "type": "STDIO", "command": "uvx", "args": ["mcp-hn"] }
For STDIO MCP servers, MetaMCP supports three ways to handle environment variables and secrets:
1. Raw Values - Direct string values (not recommended for secrets):
API_KEY=your-actual-api-key-here
DEBUG=true
2. Environment Variable References - Use ${ENV_VAR_NAME}
syntax:
API_KEY=${OPENAI_API_KEY}
DATABASE_URL=${DB_CONNECTION_STRING}
3. Auto-matching - If the expected environment variable name in your tool matches the container's environment variable, you can omit it entirely. MetaMCP will automatically pass through matching environment variables.
🔒 Security Note: Environment variable references (
${VAR_NAME}
) are resolved from the MetaMCP container's environment at runtime. This keeps actual secret values out of your configuration and git repository.
⚙️ Development Note: For local development with
pnpm run dev:docker
, ensure your environment variables are listed inturbo.json
underglobalEnv
to be passed to the development processes. This is not required for production Docker deployments.
Similar to the official MCP inspector, but with saved server configs - MetaMCP automatically creates configurations so you can debug MetaMCP endpoints immediately.
Clone repo, prepare .env
, and start with docker compose:
git clone https://github.com/metatool-ai/metamcp.git cd metamcp cp example.env .env docker compose up -d
If you modify APP_URL env vars, make sure you only access from the APP_URL, because MetaMCP enforces CORS policy on the URL, so no other URL is accessible.
Note that the pg volume name may collide with your other pg dockers, which is global, consider rename it in docker-compose.yml
:
volumes:
metamcp_postgres_data:
driver: local
Still recommend running postgres through docker for easy setup:
pnpm install pnpm dev
If you have questions, feel free to leave GitHub issues or PRs.
Example mcp.json
{ "mcpServers": { "MetaMCP": { "url": "http://localhost:12008/metamcp/<YOUR_ENDPOINT_NAME>/sse" } } }
Since MetaMCP endpoints are remote only (SSE, Streamable HTTP, OpenAPI), clients that only support stdio servers (like Claude Desktop) need a local proxy to connect.
Note: While mcp-remote
is sometimes suggested for this purpose, it's designed for OAuth-based authentication and doesn't work with MetaMCP's API key authentication. Based on testing, mcp-proxy
is the recommended solution.
Here's a working configuration for Claude Desktop using mcp-proxy
:
Using Streamable HTTP
{ "mcpServers": { "MetaMCP": { "command": "uvx", "args": [ "mcp-proxy", "--transport", "streamablehttp", "http://localhost:12008/metamcp/<YOUR_ENDPOINT_NAME>/mcp" ], "env": { "API_ACCESS_TOKEN": "<YOUR_API_KEY_HERE>" } } } }
Using SSE
{ "mcpServers": { "ehn": { "command": "uvx", "args": [ "mcp-proxy", "http://localhost:12008/metamcp/<YOUR_ENDPOINT_NAME>/sse" ], "env": { "API_ACCESS_TOKEN": "<YOUR_API_KEY_HERE>" } } } }
Important notes:
<YOUR_ENDPOINT_NAME>
with your actual endpoint name<YOUR_API_KEY_HERE>
with your MetaMCP API key (format: sk_mt_...
)For more details and alternative approaches, see issue #76.
?api_key=
param api key auth doesn't work for SSE. It only works for Streamable HTTP and OpenAPI.Authorization: Bearer <API_KEY>
header.uvx
or npx
, you need to customize the Dockerfile to install dependencies on your own.🛠️ Solution: Customize the Dockerfile to add dependencies or pre-install packages to reduce cold start time.
Authorization: Bearer <api-key>
headerMetaMCP supports OpenID Connect authentication for enterprise SSO integration. This allows organizations to use their existing identity providers (Auth0, Keycloak, Azure AD, etc.) for authentication.
Add the following environment variables to your .env
file:
# Required OIDC_CLIENT_ID=your-oidc-client-id OIDC_CLIENT_SECRET=your-oidc-client-secret OIDC_DISCOVERY_URL=https://your-provider.com/.well-known/openid-configuration # Optional customization OIDC_PROVIDER_ID=oidc OIDC_SCOPES=openid email profile OIDC_PKCE=true
MetaMCP has been tested with popular OIDC providers:
https://your-domain.auth0.com/.well-known/openid-configuration
https://your-keycloak.com/realms/your-realm/.well-known/openid-configuration
https://login.microsoftonline.com/your-tenant-id/v2.0/.well-known/openid-configuration
https://accounts.google.com/.well-known/openid-configuration
https://your-domain.okta.com/.well-known/openid-configuration
Once configured, users will see a "Sign in with OIDC" button on the login page alongside the email/password form. The authentication flow automatically creates new users on first login.
For more detailed configuration examples and troubleshooting, see CONTRIBUTING.md.
MetaMCP provides separate controls for different registration methods, allowing administrators to fine-tune user access policies for enterprise deployments.
This separation enables common enterprise scenarios:
Access the Settings page in the MetaMCP admin interface to configure these controls:
Both controls work independently, giving you full flexibility over your registration policy.
If you want to deploy it to a online service or a VPS, a instance of at least 2GB-4GB of memory is required. And the larger size, the better performance.
Since MCP leverages SSE for long connection, if you are using reverse proxy like nginx, please refer to an example setup nginx.conf.example
Note: Prompts and resources follow similar patterns to tools.
sequenceDiagram participant MCPClient as MCP Client (e.g., Claude Desktop) participant MetaMCP as MetaMCP Server participant MCPServers as Installed MCP Servers MCPClient ->> MetaMCP: Request list tools loop For each listed MCP Server MetaMCP ->> MCPServers: Request list_tools MCPServers ->> MetaMCP: Return list of tools end MetaMCP ->> MetaMCP: Aggregate tool lists & apply middleware MetaMCP ->> MCPClient: Return aggregated list of tools MCPClient ->> MetaMCP: Call tool MetaMCP ->> MCPServers: call_tool to target MCP Server MCPServers ->> MetaMCP: Return tool response MetaMCP ->> MCPClient: Return tool response
Potential next steps:
See README-i18n.md
Currently en and zh locale are supported, but welcome contributions.
We welcome contributions! See details at CONTRIBUTING.md
MIT
Would appreciate if you mentioned with back links if your projects use the code.
Some code inspired by:
Not directly used the code by took ideas from