最近在跟着教程用 MCP 协议给 Claude Desktop 接了一个自己写的本地工具 Server,功能很简单,就是查一下本地 SQLite 里的数据。单独用 Python 脚本跑没问题,但在 Claude 里调用时经常卡住,最后报 timeout。看日志发现 Server 收到了请求,也返回了结果,但客户端好像没收到。我怀疑是 stdio 传输那块哪里没处理好,但文档翻了几遍也没找到明确说明。有没有人遇到过类似情况?是不是我返回的 JSON 格式不对,还是需要额外加什么字段?求指点。
MCP 工具调用总是超时,是我 Server 写的有问题吗?
全部回复
共 8 条这个情况我之前也踩过,大概率不是 JSON 格式的问题,而是 stdio 传输里的缓冲和刷出没处理干净。MCP 走 stdio 的时候,服务端返回的每条消息通常要以换行分隔,并且写完必须立刻 flush,不然消息会卡在缓冲区里,客户端一直等不到完整帧,最后就 timeout 了。日志显示你返回了结果,其实只是写进了 Python 的缓冲,并没有真正推到管道里。你可以先确认一下是不是用的 sys.stdout.write 之后忘了 flush,或者用了 print 但没加 flush=True。另外 Claude Desktop 拉起本地 Server 时,stderr 和 stdout 千万别混用,调试日志全部走 stderr,否则会污染协议消息。还有一点,如果你用的是某个 MCP SDK,检查一下版本,早期版本在 Windows 上管道读取确实有 bug。建议先用 MCP Inspector 单独连一下你的 Server,能稳定跑通再挂到 Claude 里,这样能快速定位是传输层还是客户端的问题。
我也踩过这个坑,日志显示返回成功但客户端收不到,大概率是 stdout 里混进了别的东西。Python 里 print 的调试信息、库的 warning 都会跑到 stdout,把 JSON-RPC 消息污染了,Claude 那边解析就卡住直到超时。建议把日志全打到 stderr,或者用 logging 配置一下,stdout 只留给协议消息。另外确认下返回的 JSON 是不是单行、有没有多余换行,这个也挺关键的。
我也踩过这个坑,日志里Server明明返回了,但Claude那边就是收不到,最后发现是stdout里混进了别的东西。你检查一下代码里有没有print调试语句没删干净,或者某些库往stdout打日志,MCP对stdio通道的纯净度要求挺高的。建议所有调试输出都改到stderr,stdout只留给协议本身的JSON-RPC消息。另外返回结果记得包在jsonrpc 2.0的标准结构里,id和result字段别漏。
我也踩过这个坑,大概率不是 JSON 格式的问题。stdio 模式下最容易出事的是 stdout 混进了别的东西,比如你代码里某个 print 或者库的日志输出,会把 JSON-RPC 的消息流污染掉,客户端解析就卡住了。建议把所有调试输出都改到 stderr,stdout 只留协议消息。另外确认下返回内容有没有按行 flush,缓冲没冲出去也会一直等。
检查下返回内容有没有混入日志输出,stdout被污染会导致客户端解析失败。
我之前也这样,八成是 stdout 里混了 print 调试信息,MCP 只认纯 JSON。
这个坑我之前也踩过,大概率不是 JSON 格式的问题,MCP 对返回结构其实挺宽容的,只要符合协议基本都能解析。你描述的现象——Server 收到请求、也返回了结果,但客户端超时——听起来更像是 stdout 被污染了。stdio 传输模式下,标准输出是专门用来传 JSON-RPC 消息的,如果你在代码里有任何 print 调试语句、日志输出到 stdout,或者引用的某个库偷偷往 stdout 写东西,客户端就会收到一堆非 JSON 内容,解析直接失败,表现出来就是一直在等合法响应然后超时。建议你先把所有 print 改成写 stderr,或者用 logging 配置到 stderr,再试一次。另外确认一下返回的消息是不是按行分隔的完整 JSON,MCP 的 stdio 是 newline-delimited 的,如果你手动拼了多条消息没换行也会卡住。还有个容易忽略的点,Claude Desktop 那边对启动命令的工作目录和路径挺敏感的,如果 Server 启动时加载 SQLite 路径失败但没报错,也可能造成响应异常。你可以先用 MCP Inspector 单独连一下你的 Server,绕开 Claude 看看能不能正常拿到结果,这样能快速定位是 Server 侧还是客户端配置的问题。
我之前也遇到过类似问题,后来换了方案。