meta-mcp-manager

meta-mcp-manager

Federates multiple MCP servers into a single endpoint with search, call, and admin tools, plus inbound/outbound OAuth.

Category
访问服务器

README

Meta MCP Manager

CI License: MIT Python 3.11+

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.json you 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


Why

AI clients hard-cap tools and burn tokens on every schema. Loading dozens of MCPs directly:

  1. Hits limits (e.g. ~40 tools in some IDEs).
  2. Degrades tool selection accuracy.
  3. 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 search_tools, paginated list_servers / list_tools
Admin manage_servers CRUD; enable/disable/reload
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 meta:read (catalog), meta:invoke (call), meta:admin (manage_*)
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 it
  • Optional: 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 ./data
URL Description
http://127.0.0.1:8080/mcp MCP endpoint
http://127.0.0.1:8080/health Health + stats
http://127.0.0.1:8080/docs Human docs
http://127.0.0.1:8080/static/logo.svg Logo
curl -s http://127.0.0.1:8080/health | jq .

Docker

export META_API_KEY="$(openssl rand -hex 16)"
docker compose up --build

Compose 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 --build

Connect 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)

  1. 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"
    
  2. In the client, add remote MCP URL:
    https://YOUR_SUBDOMAIN.ngrok-free.dev/mcp

  3. Complete browser consent with META_OAUTH_PASSWORD or META_API_KEY.

No static Bearer header required for that path.


Meta tools

Tool Purpose
search_tools BM25 search over the catalog
get_tool_schema Full JSON schema for server/tool
call_tool Invoke upstream tool
list_servers Paginated server inventory
list_tools Paginated tool catalog (server filter optional)
stats Counts / health
manage_servers create · update · delete · get · list · enable · disable · reload
manage_auth login · status · logout · refresh (no raw tokens to the model)

Agent path: search_toolsget_tool_schemacall_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
META_API_KEY Bearer key for local clients; default consent password if unset
META_OAUTH_PASSWORD Consent password for inbound OAuth (optional)
META_PUBLIC_URL Public base URL (required for OAuth redirects / PRM)
META_CONFIG Path to mcp.json
META_DATA_DIR SQLite, vaults, logs
META_HOST / META_PORT Bind address
META_OAUTH_ENABLED Inbound OAuth AS (default true)
META_ALLOW_API_KEY Accept API key on /mcp (default true)
META_REQUIRE_API_KEY Require auth on /mcp (default true)
META_STRICT_STDIO Require absolute stdio commands (default false)
META_STDIO_ALLOW_PREFIXES :-separated path prefixes allowed when strict

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 manage_auth + /oauth/callback
Inbound Claude/ChatGPT → Meta via PRM/AS + /oauth/authorize + /oauth/token

Inbound discovery endpoints

Endpoint Spec role
GET /.well-known/oauth-protected-resource RFC 9728 PRM
GET /.well-known/oauth-authorization-server RFC 8414 AS metadata
POST /oauth/register Dynamic client registration
GET/POST /oauth/authorize Authorization code + consent
POST /oauth/token Code exchange / refresh

Scopes

Scope Access
meta:read search, list, schema, stats (catalog)
meta:invoke call_tool when META_REQUIRE_INVOKE_SCOPE=true
meta:admin manage_servers, manage_auth

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
call_tool 60 META_RATE_CALL_TOOL
manage_* 30 META_RATE_MANAGE
catalog (search / list_* / stats) 180 META_RATE_CATALOG
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
servers, tools Catalog of upstream MCPs + tool schemas
activity Meta-tool call log (Activity UI)
oauth_tokens, oauth_pending Outbound OAuth (token blobs Fernet-encrypted)
oauth_clients, auth_codes, access_tokens, … Inbound OAuth AS
meta_schema 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 META_API_KEY ≥16 chars, unique
Consent password META_OAUTH_PASSWORD (separate from API key preferred)
Public bind Auto strict_stdio; refuse weak keys
DCR lock META_DCR_TOKEN=… and/or META_DCR_REDIRECT_ALLOWLIST=claude.ai,.openai.com
Disable DCR META_DCR_ENABLED=false
Catalog-only OAuth META_REQUIRE_INVOKE_SCOPE=true + grant meta:invoke when needed
SSRF META_ALLOW_PRIVATE_URLS=false when not needing localhost MCPs
Activity retention META_ACTIVITY_RETENTION_DAYS=30 (default)
Single worker Do not set WEB_CONCURRENCY>1 (refused at start)
Backup meta backup --out /safe/path (copies meta.db, token.key, mcp.json)
TLS Terminate at reverse proxy / tunnel

Brand & connector packaging

Asset Path
Logo /static/logo.svg
Favicon /static/favicon.svg
Docs /docs
Terms /legal/terms
Privacy /legal/privacy
Brand pack /brand

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, favicon

Design 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.py

Fixtures 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_PASSWORD and 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:admin like 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

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选