mcpgw 是一个 Cargo 虚拟工作区(virtual workspace),按「职责单一」拆成多个 crate。 每个 crate 只做一件事,彼此依赖方向无环,于是检索逻辑、上游 I/O、对外服务都能独立演进。
从对外的可执行程序,到最底层的纯数据结构,自上而下大致是这样几层:
分层之所以稳,靠的是几条刻意定下的依赖规则(对照 docs/L1-overview.md 依赖关系段):
# 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 同名表一致):
| 方向 | stdio | HTTP(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>),但至少须启用一种。
👉 检索策略正是网关的核心可插拔件。下一部分我们就钻进去,看向量检索是怎么建在 retrieval 抽象之上、又如何在嵌入失败时透明降级回 BM25 的。