记录一下那天晚上的排查过程。自建 MCP server 用 Python 写,调试时加了一行 print,客户端立刻报 Unexpected token d is not valid JSON 并断开连接,删掉 print 后恢复。
刚开始盯着「日志库默认 handler 指向 stdout」,折腾了半个多小时,排掉了。
这类报错背后常见的原因有几处,逐个排除就行。stdio 传输把 stdout 当作 JSON-RPC 通道。还有一种是print 的输出直接混进了消息流。
另外,未捕获异常的栈也打到了 stdout。
搜一遍代码里的 print 调用
python -c "import re;[print(i+1,l) for i,l in enumerate(open('server.py',encoding='utf-8')) if 'print(' in l]"
再往下把日志 handler 统一指向 stderr
python -c "import logging,sys;logging.basicConfig(stream=sys.stderr,level=logging.INFO)"
随后加一层保护,禁止向 stdout 写非协议内容
python -c "import sys;print('guard stdout',file=sys.stderr)"
剩下的就是用官方 inspector 连一次确认消息可解析
python -c "print('npx @modelcontextprotocol/inspector')"
命令输出我都留了记录,免得改完记不清原来的值。
改之前先确认了最近有没有人动过配置,避免白查一遍。
别只看报错消失,验证要多做一步。客户端能持续收到 tools/list 与调用结果,日志出现在 stderr 一侧,连接不再断开。
这里还有个坑。stdio 模式下 stdout 只有协议能用,所有调试输出走 stderr,这条规则要写进项目的开发约定。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。
