八年前Meta就有万亿参数模型了——这种"事后看来理所当然"的技术演进,在MCP(模型上下文协议)领域正在重演。一位开发者为了内部演示写的几十行代码,最终演变成了一个支持多API聚合、真实OAuth2授权、三种传输协议并存的开源网关。这个故事的起点,简单到可笑:让非技术同事能用Claude Desktop试试公司API。
最初的版本确实很快。OpenAPI规范转MCP server,市面上有现成思路。但演示需求迅速膨胀:客服场景需要同时查产品API和内部工单系统,而且不能让所有人共用同一个服务token——得按用户身份走OAuth2。更麻烦的是,用户是非技术人员,streamable HTTP是底线体验;但开发者又不知道最终生产环境用什么客户端,stdio和SSE得打包在同一个二进制里。规范还在频繁变动,MCP层不能手写,得自动跟着spec走。
等这一切跑稳,openapi-mcp-gateway诞生了。它的核心能力用一句话概括:扔给它一个YAML,它就把OpenAPI spec变成能跑的MCP server。单进程可挂载任意数量API,支持真实的per-user OAuth2 with token relay。
启动方式极简:uvx openapi-mcp-gateway --spec https://petstore3.swagger.io/api/v3/openapi.json --name petstore,MCP server就在本地8000端口就绪。也可以加为项目依赖用uv add管理。Claude Desktop、Cursor、Cline等客户端都能连,三种传输协议全支持,要求Python 3.11+。
真正体现设计取舍的是多API配置。实际agent任务很少只调一个接口——查GitHub仓库、调内部产品API、写外部CRM,三件事要串在一起。网关的YAML配置允许单文件定义多个server:
petstore走公开spec;GitHub需要bearer token,同时用policy.allow/policy.deny细粒度控制暴露哪些端点(比如只给读仓库和用户信息,隐藏actions/secrets);Asana走完整OAuth2流程,指定client_id/client_secret和scopes。一条命令启动,三个MCP server分别挂在不同路径,各自独立鉴权、独立过滤。
这个设计的微妙之处在于"不把所有端点暴露给模型"。OpenAPI spec往往包含大量内部接口,直接全量转换既浪费token又增加风险。网关的策略过滤层让运维能精确控制AI可见的API表面,而不是要么全给、要么重写spec。
OAuth2的实现细节更值得拆解。很多MCP工具所谓的"OAuth支持"其实是共享服务账户,或者把token硬编码在配置里。这里的"real per-user OAuth2"意味着:终端用户走标准授权码流程,网关负责token生命周期管理,包括刷新,然后把携带用户身份的token中继给下游API。这对企业场景是刚需——审计日志要追溯到人,权限要按HR系统里的角色走。
传输协议的统一处理是另一个隐性成本。streamable HTTP是MCP 2024-11-05版本的新规范,适合浏览器直连;SSE是早期主流,兼容性好;stdio则是本地集成的兜底方案。三种协议状态机不同、错误处理不同,但网关选择打包在同一二进制里,由调用方按需选择。这种"不替用户做决定"的设计,反映了作者对生产环境不确定性的预判。
自动重生成机制解决了维护噩梦。spec变动时,传统做法是手动更新MCP server代码,或者写一堆模板生成脚本。网关的做法是:启动时或按配置周期重新拉取spec,动态重建路由。这对API迭代快的团队意味着,MCP层可以跟着后端CI/CD走,而不是成为独立的技术债。
技术选型上,Python 3.11+的硬性要求暗示了async/await和类型提示的重度使用。uv作为包管理工具的选择,则反映了作者对现代Python工具链的偏好——冷启动快、依赖解析可靠、支持全局工具和项目依赖两种模式。
这个项目的演进轨迹,某种程度上是MCP生态成熟度的缩影。早期demo验证"能不能跑通",中期被真实场景的复杂性倒逼(多API、真OAuth、协议兼容),最终沉淀为可复用的基础设施。作者没有一开始就设计网关,而是让需求自然生长——这种"从痛点出发"的路径,比自上而下的架构设计更经得起实际检验。
对于正在评估MCP落地的团队,这个开源项目的价值在于:它展示了一条从"让非技术同事试试API"到"企业级多API网关"的完整升级路径,每一步的取舍都留下了代码痕迹。不是所有人都需要从头造轮子,但理解轮子为什么长成这样,能少走很多弯路。
热门跟贴