meta-mcp-manager
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@meta-mcp-managerlist all servers with their current status"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Meta MCP Manager
One MCP endpoint for every tool you own.
Self-hosted control plane that federates stdio and remote MCP servers, keeps them warm, indexes tools for retrieval, and exposes a single Streamable HTTP surface to Cursor, Claude, ChatGPT, and other agents.
Cursor / Claude / ChatGPT
│ one connection
▼
Meta MCP Manager ──► GitHub · Logfire · Context7 · your stdio servers · …
│
search → schema → call
manage_servers · manage_auth (admin)Scale past client tool caps — agents see a small fixed meta-tool set, not 500 schemas.
Cursor-compatible config — drop in an
mcp.jsonyou already use.Inbound OAuth — Claude/ChatGPT paste your URL; PKCE + DCR + consent page.
Outbound OAuth — connect protected upstreams (e.g. Logfire) via
manage_auth.Open source, single binary-ish Docker image — MIT, no phone-home.
Table of contents
Related MCP server: mcp-gw
Why
AI clients hard-cap tools and burn tokens on every schema. Loading dozens of MCPs directly:
Hits limits (e.g. ~40 tools in some IDEs).
Degrades tool selection accuracy.
Makes OAuth, restarts, and inventory unmanageable.
Meta sits in the middle: one public MCP, many upstreams, search-first discovery.
Features
Area | Capability |
Transports | Warm stdio pool; remote Streamable HTTP (+ SSE where configured) |
Discovery | BM25 |
Admin |
|
Outbound auth | OAuth 2.1 + PKCE to upstreams; encrypted token vault; refresh |
Inbound auth | OAuth AS + PRM for Claude/ChatGPT; API key for local clients |
Scopes |
|
Ops | Health JSON, audit log (arg keys only), Docker Compose |
Packaging | Logo SVG, docs/legal pages, CSP + security headers |
Quick start
Requirements
Python 3.11+
Optional: Node (
npx) if your upstream MCPs need itOptional: uv
Install & run
git clone https://github.com/arthurkatcher/meta-mcp-manager.git
cd meta-mcp-manager
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
# or: uv pip install -e ".[dev]"
cp config/mcp.example.json mcp.json
# Edit paths / servers as needed
export META_API_KEY="$(openssl rand -hex 16)"
meta serve --config mcp.json --host 127.0.0.1 --port 8080 --data-dir ./dataURL | Description |
| MCP endpoint |
| Health + stats |
| Human docs |
| Logo |
curl -s http://127.0.0.1:8080/health | jq .Docker
export META_API_KEY="$(openssl rand -hex 16)"
docker compose up --buildCompose mounts config/mcp.docker.json and persists /data. For public clients (Claude/ChatGPT) set:
export META_PUBLIC_URL=https://your.domain.example
export META_OAUTH_PASSWORD="$META_API_KEY" # or a separate consent password
docker compose up --buildConnect clients
Cursor / VS Code (API key)
{
"mcpServers": {
"meta": {
"url": "http://127.0.0.1:8080/mcp",
"headers": {
"Authorization": "Bearer YOUR_META_API_KEY"
}
}
}
}Grok (~/.grok/config.toml)
[mcp_servers.meta]
url = "http://127.0.0.1:8080/mcp"
enabled = true
[mcp_servers.meta.headers]
Authorization = "Bearer YOUR_META_API_KEY"Or: grok mcp add --transport http meta http://127.0.0.1:8080/mcp --header "Authorization: Bearer YOUR_META_API_KEY"
Claude Desktop (stdio bridge + API key)
{
"mcpServers": {
"meta": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://127.0.0.1:8080/mcp",
"--header",
"Authorization: Bearer YOUR_META_API_KEY"
]
}
}
}Claude / ChatGPT (remote + inbound OAuth)
Expose Meta with HTTPS (tunnel or reverse proxy):
ngrok http 8080 export META_PUBLIC_URL=https://YOUR_SUBDOMAIN.ngrok-free.dev meta serve --config mcp.json --host 0.0.0.0 --port 8080 \ --public-url "$META_PUBLIC_URL" --api-key "$META_API_KEY"In the client, add remote MCP URL:
https://YOUR_SUBDOMAIN.ngrok-free.dev/mcpComplete browser consent with
META_OAUTH_PASSWORDorMETA_API_KEY.
No static Bearer header required for that path.
Meta tools
Tool | Purpose |
| BM25 search over the catalog |
| Full JSON schema for |
| Invoke upstream tool |
| Paginated server inventory |
| Paginated tool catalog ( |
| Counts / health |
| create · update · delete · get · list · enable · disable · reload |
| login · status · logout · refresh (no raw tokens to the model) |
Agent path: search_tools → get_tool_schema → call_tool.
Add an upstream MCP (+ OAuth)
manage_servers(action="create", server_id="logfire",
url="https://logfire-us.pydantic.dev/mcp")
# if runtime_status == "auth_required":
manage_auth(action="login", server_id="logfire")
# open authorization_url → Meta /oauth/callback completes
manage_auth(action="status", server_id="logfire")
search_tools(query="list projects")
call_tool(tool_id="logfire/project_list", arguments={})Admin tools require scope meta:admin. API keys grant full admin.
Configuration
mcp.json (Cursor-compatible)
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
},
"context7": {
"url": "https://mcp.context7.com/mcp"
},
"protected": {
"url": "https://example.com/mcp",
"headers": {
"Authorization": "Bearer ${env:SERVICE_TOKEN}"
},
"auth": {
"CLIENT_ID": "${env:OAUTH_CLIENT_ID}",
"CLIENT_SECRET": "${env:OAUTH_CLIENT_SECRET}",
"scopes": ["read", "write"]
}
}
}
}${env:NAME} is interpolated at load time.
Environment variables
Variable | Description |
| Bearer key for local clients; default consent password if unset |
| Consent password for inbound OAuth (optional) |
| Public base URL (required for OAuth redirects / PRM) |
| Path to |
| SQLite, vaults, logs |
| Bind address |
| Inbound OAuth AS (default |
| Accept API key on |
| Require auth on |
| Require absolute stdio commands (default |
|
|
CLI:
meta serve --config mcp.json --host 127.0.0.1 --port 8080 \
--api-key "$META_API_KEY" --public-url "$META_PUBLIC_URL"OAuth
Two directions
Direction | Meaning |
Outbound | Meta → upstream MCP (Logfire, Linear, …) via |
Inbound | Claude/ChatGPT → Meta via PRM/AS + |
Inbound discovery endpoints
Endpoint | Spec role |
| RFC 9728 PRM |
| RFC 8414 AS metadata |
| Dynamic client registration |
| Authorization code + consent |
| Code exchange / refresh |
Scopes
Scope | Access |
| search, list, schema, stats (catalog) |
|
|
|
|
Default OAuth consent grants meta:read + meta:invoke (catalog + call tools).meta:admin is never default — must be requested explicitly. API keys get all scopes.
Set META_REQUIRE_INVOKE_SCOPE=true to enforce that call_tool needs meta:invoke (recommended when you also issue read-only tokens).
Rate limits (defaults, per principal / min)
Surface | Default | Env |
| 60 |
|
| 30 |
|
catalog ( | 180 |
|
OAuth register / token / authorize | separate | (built-in) |
Window: META_RATE_WINDOW_SEC (default 60). Set a limit to 0 to disable that bucket. Exceeded tools return error: rate_limited.
Product database (one SQLite file)
Everything durable lives in {META_DATA_DIR}/meta.db (WAL). Multiple tables, one file for backup/UI:
Table(s) | Purpose |
| Catalog of upstream MCPs + tool schemas |
| Meta-tool call log (Activity UI) |
| Outbound OAuth (token blobs Fernet-encrypted) |
| Inbound OAuth AS |
| Schema version |
Still separate on disk: mcp.json (config templates), token.key (Fernet key, mode 0600), optional JSONL mirror logs/audit.jsonl.
Legacy split files (activity.db, oauth.db, inbound_oauth.db) are merged into meta.db once on startup and renamed *.migrated.
Activity columns: event_id, ts, duration_ms, meta_tool, actor_label (oauth · Claude, …), ok, error_code, args_keys (names only), target_tool_id, …
OAuth actors use registered client_name from DCR when available.
Inbound bearer secrets (access/refresh/auth codes/client_secret) are stored as SHA-256 digests in SQLite (plaintext only at issuance).
Production checklist
Control | Env / action |
Strong API key |
|
Consent password |
|
Public bind | Auto |
DCR lock |
|
Disable DCR |
|
Catalog-only OAuth |
|
SSRF |
|
Activity retention |
|
Single worker | Do not set |
Backup |
|
TLS | Terminate at reverse proxy / tunnel |
Brand & connector packaging
Asset | Path |
Logo |
|
Favicon |
|
Docs |
|
Terms |
|
Privacy |
|
Brand pack |
|
PRM includes logo_uri, resource_documentation, resource_tos_uri, resource_policy_uri.
HTML/OAuth responses send CSP and standard security headers.
See docs/CONNECTOR.md for the full surface and production checklist.
Architecture
src/meta_manager/
app.py # HTTP routes, lifespan
main.py # CLI: meta serve
config/ # mcp.json load/save, settings
runtime/ # stdio + HTTP session pool
catalog/ # SQLite catalog + BM25
edge/ # meta tools, auth middleware, CSP
oauth/ # outbound vault + inbound AS
admin/ # manage_servers / manage_auth
brand/ # docs/legal HTML
static/ # logo, faviconDesign notes: ARCHITECTURE.md.
Development
source .venv/bin/activate
pip install -e ".[dev]"
pytest -q --timeout=90
# optional real-MCP stress (Meta must be running):
# META_URL=http://127.0.0.1:8080/mcp META_API_KEY=... python scripts/hardcore_eval_real.pyFixtures under fixtures/ provide stdio math/echo/many-tools and an HTTP time server for CI without flaky public remotes.
Security notes
Self-hosted: you operate the instance; protect
META_API_KEY/META_OAUTH_PASSWORDand network exposure.Prefer HTTPS and a stable domain for inbound OAuth (not long-term free tunnels).
Upstream tokens are stored under
META_DATA_DIR(Fernet-encrypted vault); back up and restrict that directory.Admin tools can add arbitrary commands (stdio) and URLs — treat
meta:adminlike root.Audit log records tool ids and argument keys, not secret values.
Legal pages under
/legal/*are OSS self-host templates, not formal counsel.
Status & roadmap
v0.1 — production-capable for single-operator self-host: federation, BM25 search, warm stdio, remote HTTP, outbound OAuth, inbound OAuth (PRM/AS/DCR/PKCE), admin tools with scope gates, Docker, connector branding, unified SQLite, activity log, rate limits, resource-bound tokens.
Still out of scope for multi-tenant SaaS: external IdP, distributed rate limits (Redis), multi-replica HA, marketplace listings.
See CHANGELOG.md for release notes.
Contributing
See CONTRIBUTING.md and CODE_OF_CONDUCT.md. PRs and issues welcome.
Security
Please report vulnerabilities privately — SECURITY.md.
License
MIT — Copyright (c) 2026 Meta MCP Manager contributors
This server cannot be deployed
Maintenance
Related MCP Connectors
- OneOAuthai.withone
Search, document and execute authenticated API calls across 700+ apps via one MCP server
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
Self-hosted federated MCP gateway: one OAuth 2.1 MCP server in front of N apps, user-level scopes.
Agent-to-agent messaging: directory, public lobby, DMs, channels, search. Stateless MCP + REST.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceAggregates multiple MCP servers behind a single, secure endpoint with unified tool/resource discovery, OAuth authentication, and resilient request routing. Enables users to manage and interact with multiple MCP backends through one centralized interface with load balancing and circuit breakers.2-
- AlicenseNot gradedqualityAmaintenanceAggregates multiple MCP servers into a single HTTP endpoint with tool namespacing, dashboard, and REST API for management.11 npmMIT
- FlicenseNot gradedqualityCmaintenanceAggregates multiple MCP servers into a single unified endpoint with hot-plugging, multi-protocol support, and management via web and CLI.26 npm-
- AlicenseNot gradedqualityAmaintenanceEnterprise MCP gateway that unifies multiple MCP servers behind one governed endpoint, providing federation, authentication, policy enforcement, caching, rate limiting, and audit.1Apache 2.0