Shared MCP Gateway
Aggregates multiple shared MCP servers into a single HTTP gateway, providing a unified, observable, and reusable MCP access layer for multiple AI clients like Codex, OpenCode, and OpenClaw. It centralizes configuration management, logging, health checks, and circuit breaking to simplify multi-client MCP deployments.
README
Shared MCP Gateway
统一把多个共享型 MCP Server 收口到一个 HTTP 网关里,对外提供一套稳定、可观测、可复用的 MCP 接入层,方便 Codex、OpenCode、Claude Code、OpenClaw 等客户端共同使用。
项目解决了什么问题
在多客户端、多 MCP Server 并行使用的场景下,通常会遇到这些问题:
- 每个客户端都要单独维护一套 MCP 配置,重复劳动多。
- 同一个工具链在不同客户端里配置不一致,容易出现“这个客户端能用、那个客户端不能用”。
- 下游 MCP Server 一旦异常,排查入口分散,不方便统一日志、自检和熔断处理。
- 新增或替换一个 MCP Server 时,需要分别改多份配置,变更成本高。
shared-mcp-gateway 的目标,就是把这些共享型能力统一纳管:
- 一处维护注册表:通过
registry.toml/registry.compose.toml统一维护下游 MCP。 - 一处对外暴露能力:通过一个 HTTP MCP 端点聚合多个下游服务。
- 一处做运维治理:统一健康检查、结构化日志、失败隔离、最小熔断。
- 一处生成客户端配置:自动产出 Codex / OpenCode / OpenClaw 的接入配置片段。
项目能干什么
当前项目已经支持:
- 聚合多个基于 stdio 的下游 MCP Server。
- 把下游工具按
namespace.tool_name方式统一暴露。 - 为不同客户端自动打上
caller标识,方便日志追踪。 - 提供
/healthz健康检查接口,查看已连接服务、失败服务、熔断状态。 - 提供结构化
logfmt日志,便于 grep、CLS、Loki 等系统检索。 - 在下游异常时做最小隔离,避免单个 MCP Server 挂掉影响整体体验。
- 生成客户端配置文件:
- Codex:
generated/codex-mcp.toml - OpenCode:
generated/opencode-mcp.jsonc - OpenClaw:
generated/openclaw-mcp.json
- Codex:
- 通过
scripts/self_check.py进行连通性、自检工具、关键能力探活。
适用场景
适合以下场景直接使用:
- 同一套 MCP 能力需要被多个 AI 客户端复用。
- 希望把“共享能力”与“宿主本地特例能力”分层治理。
- 希望统一日志、自检、健康检查与故障隔离。
- 希望新增一个共享 MCP 时,只改一份注册表配置。
项目结构
shared-mcp-gateway/
├── Dockerfile # 网关镜像构建文件
├── docker-compose.yml # 当前本地落地用 Compose 编排
├── registry.toml # 宿主机直跑配置
├── registry.compose.toml # 容器内运行配置
├── requirements.txt # Python 依赖
├── docs/
│ └── mcp-topology.md # 哪些 MCP 进入网关、哪些保留本地特例
├── generated/ # 自动生成的客户端配置文件
├── templates/ # 可复制的配置模板
│ ├── docker-compose.template.yml # Compose 配置模板
│ ├── registry.compose.template.toml # 容器内注册表模板
│ └── registry.template.toml # 宿主机注册表模板
├── scripts/
│ ├── render_client_configs.py # 生成客户端配置片段
│ └── self_check.py # 健康检查与关键工具自检
├── shared_mcp_gateway/
│ ├── config.py # 注册表解析
│ ├── gateway.py # HTTP MCP 聚合网关主程序
│ ├── logging_utils.py # 结构化日志输出
│ ├── render.py # 客户端配置渲染
│ └── stdio_bridge.py # stdio 客户端到 HTTP MCP 的桥接
核心工作方式
flowchart LR
A["Codex / OpenCode / OpenClaw"] --> B["stdio_bridge / HTTP Client"]
B --> C["Shared MCP Gateway"]
C --> D["mempalace"]
C --> E["mysql-db"]
C --> F["obsidian-kb"]
C --> G["tencent-cls"]
运行链路说明
一次 MCP 请求进入共享网关后,关键路径如下:
- 客户端通过
stdio_bridge.py或直接通过 HTTP 访问共享网关。 RequestLoggingMiddleware注入caller、request_id、访问日志上下文。SharedMcpGateway依据工具名 / 资源 URI / prompt 名定位目标下游。- 若对应下游已被熔断,请求会被快速拒绝,避免持续打到异常服务。
- 若允许转发,请求进入
DownstreamConnection,通过单 session 锁串行访问下游 MCP。 - 调用完成后更新 metrics、failure streak、circuit breaker,并同步到 heartbeat / healthz。
核心模块职责建议按下面理解:
shared_mcp_gateway/config.py:注册表解析与强类型配置对象。shared_mcp_gateway/gateway.py:统一索引、请求转发、熔断隔离、健康检查、心跳日志。shared_mcp_gateway/stdio_bridge.py:给只支持 stdio 的客户端提供 HTTP 网关桥接层。shared_mcp_gateway/render.py:把统一注册表渲染成不同客户端的接入配置。scripts/self_check.py:从健康接口和真实 MCP 调用两个维度做联通性自检。
请求时序图
下面这张图更适合对应代码阅读时建立整体心智模型:
sequenceDiagram
participant Client as "MCP Client"
participant Bridge as "stdio_bridge / HTTP Client"
participant Middleware as "RequestLoggingMiddleware"
participant Gateway as "SharedMcpGateway"
participant Breaker as "CircuitBreaker"
participant Downstream as "DownstreamConnection"
participant Server as "Downstream MCP Server"
Client->>Bridge: 发起 list_tools / call_tool / read_resource
Bridge->>Middleware: HTTP 请求进入网关
Middleware->>Gateway: 注入 caller / request_id 后转发
Gateway->>Breaker: 检查目标下游是否允许访问
alt breaker open
Breaker-->>Gateway: reject
Gateway-->>Client: 快速失败 / 返回熔断提示
else breaker closed
Gateway->>Downstream: 按 namespace 路由请求
Downstream->>Server: 串行发起 MCP 调用
Server-->>Downstream: 返回结果或异常
Downstream-->>Gateway: 返回标准 MCP 响应
Gateway->>Gateway: 更新 metrics / failure streak / breaker
Gateway-->>Client: 返回聚合后的 MCP 响应
end
阅读代码建议
如果要快速看懂主链路,建议按这个顺序读:
shared_mcp_gateway/config.py:先理解注册表结构。shared_mcp_gateway/render.py:理解客户端接入配置是怎么生成的。shared_mcp_gateway/stdio_bridge.py:理解 stdio 客户端如何接到 HTTP 网关。shared_mcp_gateway/gateway.py:重点看SharedMcpGateway、DownstreamConnection、RequestLoggingMiddleware。scripts/self_check.py:理解上线后如何验证“接口活着”和“真实能力可用”。
快速开始
1. 安装依赖
cd /path/to/shared-mcp-gateway
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
2. 准备配置
你可以直接参考模板文件:
templates/registry.template.tomltemplates/registry.compose.template.tomltemplates/docker-compose.template.yml
最常见的做法是:
cp templates/registry.template.toml registry.local.toml
cp templates/registry.compose.template.toml registry.compose.local.toml
cp templates/docker-compose.template.yml docker-compose.local.yml
然后把模板里的路径、端口、下游服务命令替换成你自己的实际环境。
3. 本地直接启动
python3 shared_mcp_gateway/gateway.py --registry registry.toml --log-level INFO
启动后默认访问:
- MCP 端点:
http://127.0.0.1:8787/mcp - 健康检查:
http://127.0.0.1:8787/healthz
4. Docker Compose 启动
docker compose up -d --build
docker compose ps
curl http://127.0.0.1:8787/healthz
停止:
docker compose down
如何配置:核心配置说明
项目的核心配置文件是 registry.toml,主要包含五部分:
1. 监听配置
[listen]
host = "127.0.0.1"
port = 8787
path = "/mcp"
含义:
host:网关监听地址port:网关监听端口path:MCP HTTP 路径
2. 网关元信息
[gateway]
name = "shared-gateway"
namespace_separator = "."
description = "Shared MCP gateway for Codex, OpenCode and OpenClaw."
含义:
name:对外暴露的网关名称namespace_separator:命名空间分隔符,默认通常使用.description:网关描述信息
3. 下游 MCP Server 配置
[[servers]]
key = "mysql-db"
enabled = true
namespace = "mysql_db"
command = "/bin/bash"
args = ["-lc", "cd /opt/mcps/mysql-connector && ./.venv/bin/python server.py"]
含义:
key:下游服务唯一标识enabled:是否启用namespace:工具名前缀命名空间command:启动命令args:启动参数env:可选,给该服务单独注入环境变量
4. 本地特例说明
[local_exceptions.openclaw]
keep_local = ["openspace"]
reason = "OpenSpace 强依赖宿主上下文,保留本地直连。"
endpoint = "http://127.0.0.1:8081/mcp"
用于记录哪些能力不走共享网关,而是继续保留本地直连。
5. 客户端配置路径元信息(可选)
[clients.codex]
config_path = "~/.codex/config.toml"
含义:
clients.*主要用于记录目标客户端配置文件所在位置。- 当前项目默认不会自动写回这些路径。
- 更推荐先运行
scripts/render_client_configs.py,再把生成结果复制到对应客户端配置里。
如何配置:案例
案例 1:宿主机直跑配置
下面是一个可直接参考的最小示例:
[listen]
host = "127.0.0.1"
port = 8787
path = "/mcp"
[gateway]
name = "shared-gateway"
namespace_separator = "."
description = "Shared MCP gateway for local development."
[[servers]]
key = "mempalace"
enabled = true
namespace = "mempalace"
command = "/opt/mempalace/.venv/bin/python"
args = ["-m", "mempalace.mcp_server"]
env = { PYTHONPATH = "/opt/mempalace" }
[[servers]]
key = "mysql-db"
enabled = true
namespace = "mysql_db"
command = "/bin/bash"
args = ["-lc", "cd /opt/mcps/mysql-connector && ./.venv/bin/python server.py"]
[local_exceptions.shared_gateway]
managed = ["mempalace", "mysql_db"]
reason = "共享能力统一由 shared-gateway 纳管。"
案例 2:Docker Compose 配置思路
如果你希望容器内统一运行网关,可参考下面的思路:
services:
shared-mcp-gateway:
build:
context: .
dockerfile: Dockerfile
container_name: shared-mcp-gateway
restart: unless-stopped
ports:
- "127.0.0.1:8787:8787"
environment:
OBSIDIAN_VAULT_PATH: /workspace/openclaw-workspace
PYTHONPATH: /workspace/mempalace
volumes:
- /opt/mcps:/workspace/mcps:ro
- /opt/mempalace:/workspace/mempalace:ro
- /opt/openclaw-workspace:/workspace/openclaw-workspace:rw
- /opt/mempalace-data:/root/.mempalace:rw
适合:
- 把多个 MCP 运行时依赖挂进同一个容器上下文。
- 通过只读挂载保证下游代码目录稳定。
- 统一使用容器里的
registry.compose.toml。
配置模板文件
为了便于直接落地,项目已经补充了可复制的模板文件:
1. 注册表模板
文件:templates/registry.template.toml
用途:
- 新环境初始化时,直接复制一份改路径即可。
- 适合作为宿主机直跑的起点配置。
- 保留了
listen、gateway、servers、clients、local_exceptions的完整结构。
建议使用方式:
cp templates/registry.template.toml registry.local.toml
2. 容器内注册表模板
文件:templates/registry.compose.template.toml
用途:
- 给 Docker / Compose 场景提供容器内路径版本的注册表模板。
- 避免把宿主机绝对路径误带入容器配置。
- 适合作为
registry.compose.toml的可复制起点。
建议使用方式:
cp templates/registry.compose.template.toml registry.compose.local.toml
3. Compose 模板
文件:templates/docker-compose.template.yml
用途:
- 新机器或新环境快速准备 Compose 编排。
- 避免直接修改现网或当前机器专用的
docker-compose.yml。 - 便于把挂载路径、环境变量改成团队自己的规范。
建议使用方式:
cp templates/docker-compose.template.yml docker-compose.local.yml
客户端接入示例
推荐接入流程:
- 先启动 shared-gateway,并确认
http://127.0.0.1:8787/healthz正常。 - 执行
python3 scripts/render_client_configs.py生成当前环境下的客户端配置片段。 - 优先复制
generated/目录里的实际产物,不要手写环境相关路径。
Codex 接入示例
更推荐直接使用 generated/codex-mcp.toml。其结构大致如下:
[mcp_servers.shared-gateway]
command = "/bin/bash"
args = ["-lc", "python3 /absolute/path/to/shared_mcp_gateway/stdio_bridge.py --url http://127.0.0.1:8787/mcp --caller codex"]
enabled = true
OpenCode 接入示例
更推荐直接使用 generated/opencode-mcp.jsonc。其结构大致如下:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"shared-gateway": {
"type": "local",
"enabled": true,
"command": [
"/bin/bash",
"-lc",
"python3 /absolute/path/to/shared_mcp_gateway/stdio_bridge.py --url http://127.0.0.1:8787/mcp --caller opencode"
]
}
}
}
OpenClaw 接入示例
OpenClaw 可以直接走 HTTP MCP,推荐直接使用 generated/openclaw-mcp.json:
{
"mcpServers": {
"shared-gateway": {
"url": "http://127.0.0.1:8787/mcp",
"transport": "streamable-http",
"connectionTimeoutMs": 10000,
"disabled": false
}
}
}
Claude Code 接入思路
当前项目已经支持通过 stdio_bridge.py 给 claude-code 注入调用方标识。核心思路是把 bridge 作为本地 stdio MCP 命令:
python3 /absolute/path/to/shared_mcp_gateway/stdio_bridge.py --url http://127.0.0.1:8787/mcp --caller claude-code
如果你的客户端配置体系允许自定义 stdio MCP command,直接复用这条 bridge 命令即可。
配置落地建议
为了减少环境问题,建议按下面顺序落地:
- 先复制模板文件,不要直接修改项目内现成样例。
- 先确保每个下游 MCP Server 单独可启动。
- 再把下游服务逐个写入
registry.toml或registry.compose.toml。 - 启动网关后,先检查
/healthz,再执行scripts/self_check.py。 - 最后执行
scripts/render_client_configs.py,同步客户端接入配置。
推荐区分三类文件:
registry.toml:宿主机直跑配置registry.compose.toml:容器内运行配置templates/*.template.*:新环境初始化模板
常用命令
生成客户端配置
python3 scripts/render_client_configs.py
这个脚本会:
- 读取
registry.toml - 统一生成 Codex / OpenCode / OpenClaw 的配置片段
- 避免手工复制 bridge 启动命令时产生配置漂移
生成结果位于:
generated/codex-mcp.tomlgenerated/opencode-mcp.jsoncgenerated/openclaw-mcp.json
执行健康检查
python3 scripts/self_check.py
python3 scripts/self_check.py --json
默认会执行两类检查:
healthz:检查网关是否正常暴露、下游是否缺失、熔断器是否打开。gateway_tools:直接以 MCP 客户端身份连到网关,检查关键工具是否存在,并执行无副作用探活。
查看日志
docker compose logs -f shared-mcp-gateway
当前接入的共享型 MCP
mempalacemysql-dbobsidian-kbtencent-cls
拓扑归位说明见:/path/to/shared-mcp-gateway/docs/mcp-topology.md
后续建议
如果你要继续扩展这个项目,推荐按下面顺序推进:
- 先在
registry.toml中新增一个[[servers]]。 - 本地验证该 MCP 是否能独立启动。
- 启动网关后检查
/healthz。 - 运行
scripts/self_check.py看关键能力是否正常。 - 重新执行
scripts/render_client_configs.py,同步客户端配置。
如果你当前就是要在这个项目里继续补充文档、模板或默认配置,优先维护:
README.mdtemplates/registry.template.tomltemplates/registry.compose.template.tomltemplates/docker-compose.template.ymldocs/mcp-topology.md
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.