MCP 服务器日志与监控:一句话结论
MCP 规范 2026-07-28 版(SEP-2577)已把协议内日志机制 notifications/message 列入弃用——新项目的正确姿势是:stdio 传输写 stderr,HTTP 传输上 OpenTelemetry,协议内日志只剩过渡期兼容价值。
规则变了:别再往协议里塞日志
很多教程还在教「实现 logging 能力 + setLevel 」,这在 2025 年没错,但官方调试文档现在明确标注:协议内日志按规范版本 2026-07-28 弃用,新实现应改走 stderr(stdio)或 OpenTelemetry(所有传输)。客户端侧则通过请求 _meta 里的 io.modelcontextprotocol/logLevel 选择性接收——服务端对没带这个字段的请求必须不发日志通知。
迁移成本不高:stdio 服务端把 Python logging 配到 stderr 即可,宿主应用会自动捕获:
import logging
from mcp.server import MCPServer
logger = logging.getLogger(__name__)
mcp = MCPServer("reports")
@mcp.tool()
async def fetch_report(report_id: str) -> str:
"""Fetch a report by id."""
logger.info("Fetching report %s", report_id)
return f"Report {report_id} is ready."
两种传输,两套监控方案
| 传输 | 日志去向 | 排查工具 |
|---|---|---|
| stdio | stderr(宿主自动捕获) | 客户端日志面板 + MCP Inspector |
| Streamable HTTP | stderr 无人捕获,需自建聚合或 OpenTelemetry | curl 、浏览器 DevTools Network 面板看 SSE 流 |
HTTP 传输下 stderr 不再被客户端捕获,这是很多人监控缺位的根源:要么自己上日志聚合,要么直接接 OpenTelemetry 输出结构化 trace 。传输选型的背景见 stdio 与 Streamable HTTP 对比。
该记什么:五类关键事件
无论走哪条通道,服务端至少记录这五类:
- 启动步骤:配置加载、依赖初始化、监听端口——启动失败占连接问题的大头。
- 资源访问:哪个 URI 被谁读了。
- 工具执行:工具名、参数摘要、耗时、结果状态。
- 错误条件:异常类型 + 上下文,别只记 message 丢堆栈。
- 性能指标:慢工具的延迟分布,P95 比 average 有用。
连接失败排查清单
监控之外,以下高频问题值得做成 checklist:
- 路径问题:宿主启动的 stdio 服务端工作目录可能是未定义的(如 macOS 的 /),配置和 .env 里一律用绝对路径。
- 环境变量:stdio 子进程只继承有限的环境变量子集,需要 override 就在配置的
env字段里显式给。 - 协议版本:每个请求的 _meta 必须带
io.modelcontextprotocol/protocolVersion和 clientCapabilities,缺了报 -32602;需要客户端声明而未声明的能力(如 elicitation)报 -32021 。 - 先隔离再排查:用 MCP Inspector 单独连服务端验证,Inspector 仍是排障第一站,配套三层测试法见 MCP 服务器怎么测试。
日常连接类问题的完整手册在 MCP 调试常见问题。
常见问题
协议内日志还能用吗?
OpenTelemetry 要接吗,还是 print 就够?
进度通知(progress)也弃用了吗?










评论 (0)