📘 mcpgw 图解教程 · 目录 第一部分 · 宏观全景 02 / 15
第一部分 · 宏观全景

整体架构全景

mcpgw 是一个 Cargo 虚拟工作区(virtual workspace),按「职责单一」拆成多个 crate。 每个 crate 只做一件事,彼此依赖方向无环,于是检索逻辑、上游 I/O、对外服务都能独立演进。

分层全景:各 crate 与它的一句话职责

从对外的可执行程序,到最底层的纯数据结构,自上而下大致是这样几层:

binmcpgw
唯一的集成者:clap CLI + serve 装配者,把上游、网关、检索、配置拼起来。
下游downstream
把 3 个元工具暴露为真正的 MCP 服务(stdio + Streamable HTTP)。
网关gateway + metatools
ArcSwap 快照状态 + 三个元工具逻辑(在不可变快照上检索/路由)。
上游upstream
活的上游 MCP I/O:连接、工具摄取、call_tool 路由转发。
检索retrieval + embedder
检索策略(BM25 / Vector)+ 云端嵌入的 HTTP 后端(检索栈里只有 embedder 直连 HTTP)。
内核catalog + config
工具目录与 {server}__{name} 命名空间 + 配置解析/校验。
🔬 细节 / 代码对应:依赖纪律

分层之所以稳,靠的是几条刻意定下的依赖规则(对照 docs/L1-overview.md 依赖关系段):

crates/retrieval/Cargo.toml · crates/embedder/Cargo.toml
# crates/retrieval/Cargo.toml —— 没有 reqwest / http
[dependencies]
catalog = { path = "../catalog" }
async-trait = { workspace = true }

# crates/embedder/Cargo.toml —— HTTP 被隔离在这里
[dependencies]
retrieval = { path = "../retrieval" }
reqwest = { version = "0.13", features = ["json", "rustls"] }

传输能力一览

网关在「上游」和「下游」两个方向上都支持 stdio 与 HTTP(与 docs/L1-overview.md 同名表一致):

方向stdioHTTP(Streamable HTTP)
上游(连接被聚合的 MCP server) ✅ 子进程(command/args + env allow-list) ✅ 远程 url + 静态鉴权(bearer_env 原始 token、headers 头名→env)
下游(向客户端暴露 3 个元工具) serve over stdio ✅ 默认 127.0.0.1:8970 /mcp + 多 key Bearer 鉴权

下游 stdio 与 HTTP 可并发同时启用(共享一份 Arc<GatewayState>),但至少须启用一种。

✅ 关键要点
💡 设计亮点
这套分层把「会爆炸的工具列表」收敛成对外恒定的 3 个元工具, 而真正复杂的检索逻辑全部留在网关内部。因为检索内核(retrieval)不被 HTTP、配置或 CLI 绑死, 它可以独立演进:从 BM25 到向量检索、再到混合检索,都不动对外契约。

👉 检索策略正是网关的核心可插拔件。下一部分我们就钻进去,看向量检索是怎么建在 retrieval 抽象之上、又如何在嵌入失败时透明降级回 BM25 的。