用AI Agent配合MCP工具干活那阵子,有件事让我越来越不踏实:我压根不知道这些代理在里面搞什么名堂。一个代理调用了工具,成功了没?花了多长时间?它有没有因为解析不了返回结果,用一模一样的指令重复调了同一个工具六遍?说实话,我完全搞不清楚。我能看到的输出,要么是个最终答案,要么就是个含糊不清的报错。中间发生的一切全是空白。
这种不可见性带来的不只是抓瞎。它让你像个瞎子一样在调试,出了问题只能靠猜。当你在生产环境中运行一套代理时,真正的噩梦才刚开始。它不是个理论上的风险,它就是个实实在在的问题。所以,我决定自己动手造个东西来堵上这个窟窿。这套方案基于OpenTelemetry和SigNoz。下面要说的,就是我到底造出了什么、前三次是怎么做砸的,以及最后什么方法才真正管用。
先说清楚到底哪里出了问题。MCP这套协议,本质就是跑在标准输入输出上的一套简易JSON-RPC 2.0通信。代理那边发过去一个请求,里面指定了要调用的工具名称和一堆参数,然后服务端就回应一下。完事了。整个过程里,日志里没有请求ID,没有耗时记录,没有报错率统计,甚至连“会话”这个概念都没有。
在我自己的测试中,有三种失败模式像幽灵一样反复出现。第一种是死循环。一个代理用同样的查询语句,连续调了五次搜索工具。我之所以注意到,纯粹是因为演示程序明显变慢了,而我恰好正盯着屏幕。没有告警,没有日志,什么记录都没有。那个代理困在了一个自我强化的循环里,而MCP层对此毫无感知。
第二种是挂起调用。我故意写了个需要跑大约20秒的慢速工具。代理就干等着。没有超时事件被触发。没有追踪记录。除非你盯着终端愣神到怀疑自己,否则你根本不会知道出了状况。第三种我称之为静默漂移。我为测试写了个假的MCP服务端,它会突然在运行时给自己添加一个新工具。一旦这个工具出现在工具列表里,代理就会开始尝试去调它。可是,没人记录下来服务端的工具列表是何时发生变化的——这种漂移就悄无声息地发生了。
这些都不是人为制造的极端个例。只要大语言模型的输出格式发生一丁点变化,死循环就可能冒出来。只要下游API性能降级,挂起调用就会出现。只要服务端做了一次不停机更新,漂移就随时可能发生。它们是真问题。
怎么在不给别人添麻烦的前提下解决这个问题?我的核心思路很直接:别要求任何人在自己的代理或服务端里加装一套SDK。就拦截标准输入输出的数据流就行了。运行机制很简单,你把MCP服务端通过这个代理来启动。代理会把它作为一个子进程来管理,把双向的标准输入输出接上线,然后监听每一条通过换行符分隔的JSON消息。它就相当于一个透明的中间人——每条消息原封不动地通过,但所有内容在这个观察者眼里都一览无余。
每处理一次工具调用请求,我就开启一段追踪记录。当响应返回时,这段追踪会自动闭合,耗时也就自动被抓取到了。整个过程里我差点犯了个大错,差点把原始参数给记进日志,最后用哈希值堵住了这个风险。运行起来也简单得要命,只需要从之前的直接启动服务端,改成用代理命令去启动它。其它一切照旧。
热门跟贴