
开发者回顾 mcp CLI 项目:实际运行的是代理而非命令行工具
来源标题:I shipped a CLI and what I run is a proxy
开发者发布的 mcp CLI 项目实际运行的是代理功能,与其 README 描述的命令行工具定位不符。该项目在 Buser 作为内部服务部署,单日经 Cloudflare 处理 196,270 次请求、6.79 GB 流量,平均每次约 35 KB。所有请求均来自 agent 调用工具,浏览器访问量和缓存命中率均为零。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
我自己的 README 第一行写的是:mcp 是一个把 MCP server 变成终端命令的 CLI。3 月 15 日我推第一个 commit 的时候,这话没错。第二天,第 17 个 commit,proxy 作为一个功能进来了。八个月、158 个 commit 之后,我实际在跑的是那个功能,而 README 开头讲的还是小的那一半。 在 Buser,它作为内部服务跑在 mcp.buser.io 后面。Cloudflare 统计到某一天有 196,270 个请求、6.79 GB 流量经过它。全天平均下来每秒两出头,大约每小时 8,200 个,每个平均 35 KB。比 ping 重多了。 那个面板上还有第二个数字,我看得更久。零访问。缓存命中率百分之零。没有人打开浏览器,返回的东西也没有任何值得存下来的。那每一个请求都是一个 agent 在调用工具,然后等一个只属于那次调用、别的调用不会有的答案。 为什么,我已经写过两遍了,不想再写第三遍。资源方面的论据在 MCP servers are draining your hardware:每个客户端启动时都会拉起所有配置的 server 并让它们一直活着,所以十个 server、三个会话就是三十个空闲进程。而 proxy 不管有多少客户端连进来,每个后端只跑一个进程。访问控制方面的论据在 MCP created without asking 和 An MCP gateway has to know a read from a write:server 上放 service token,每个人一个凭证,再加一个知道工具是读还是写的 ACL。 那两篇我都是作为一个在解决自己笔记本问题的人写的。今年变的地方是,别人的 agent 开始在我睡觉的时候依赖它。 仓库现在开着的十二个 issue 里,七个带 serve: 前缀。158 个 commit 里有 28 个动 src/serve/。这个比例不是我规划的。bug 就在那儿,因为流量就在那儿。 我这周关掉的那个,最能说明单个用户看不到什么。issue 144 里,一个被取消的请求还在后端继续跑。 客户端放弃一个很长的 tools/call,发来 notifications/cancelled。那条通知是一条独立的消息,没有 id。我的 stdio 循环把每一行进来的内容都当 JsonRpcRequest 解析,而 JsonRpcRequest 的 id 是必填的,所以通知永远解析不成它,也就没有任何代码去看它的 method。proxy 收到过的每一次取消,都被丢在了地上。客户端走了,proxy 还占着槽位和连接,后端继续干活,继续按次计费。 这个 bug 存在了八个月。在笔记本上你永远注意不到,因为你放弃一次工具调用时会把终端关掉,整个进程树跟着一起死。把同样的代码放到一个共享端点后面,一个被取消的请求就是别人在付的配额。 修复本身不是有意思的部分。有意思的是,修它的时候暴露出我一周前刚上线的第二个 bug,就在那个为取消功能添加 registry 的 commit 里。Tokio 的 watch::Sender::send 在没有接收者活着的时候拒绝写入值,而我的 token 自己不带接收者。所以 cancel() 什么都没设。两个测试挂起而不是失败,而我写的那个用来证明一个身份不能取消另一个身份请求的测试,因为最糟糕的原因通过了。根本就没有东西在取消。 我能抓到它只是因为测试套件挂了。如果 cancel() 悄悄什么都没做、测试还一直绿着,那条断言就会躺在仓库里,看起来像是访问控制。 那个面板上的 p95 首字节时间是 4.2 秒。那不是页面加载,也不该被当成页面加载来读。一次经过 proxy 的 tools/call 要等后端在等的东西,而其中一些后端在查数据仓库。proxy 只加了路由、认证和一次审计写入。那几秒属于工作本身。 同一天,这些请求里有 0.18% 返回 5xx。大约 350 次失败,我不会假装共享端点让它们比每个人自己拿 token 的时候更便宜。它只是把失败挪了位置。一个 proxy 有糟糕的一分钟,就是公司里每个 agent 都有糟糕的一分钟——这是我在知情下做的取舍,四月也写过了。一个我看得见的失败,胜过一片我看不见的攻击面。 CLI 也没死,我也不会删它。它是我调试 proxy 的方式。一个工具通过网关行为不对时,我第一件事就是用 mcp <server> <tool> 直接调它,弄清楚是哪一边在撒谎。 如果要我说有什么会做得不一样,那就是更早承认它的形态。我花了好几个月给那个没人用的前门写文档、做 Homebrew tap、搭发布流水线,而真正承载流量的东西,写在一份 37 KB、大多数人根本不会翻到的指南里。 如果你在维护一个东西,而 issue tracker 已经漂向某一个前缀,那就是这个项目在告诉你它变成了什么。我的项目说了七次 serve:(一共十二个 issue),在我愿意读它之前。
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。