Spanly 实战:为 MCP 服务器装上可观测性之眼
背景
当你把产品包装成 MCP(Model Context Protocol)服务器对外提供时,Sentry 和 New Relic 会看到什么?一堆看起来健康的 HTTP POST 请求——/mcp 路径下每秒几十次调用,状态码全部 200,毫无异常。然而 Agent 那边早已重试了三次然后放弃了,你的 MCP 工具在静默死亡,而你的 APM 面板上一片祥和。
这正是 Spanly(spanly.com)的创始人 Tim 在过去一年里亲自踩过的坑。他之前在搭建 MCP 网关时发现,传统 APM 根本理解不了 MCP 的消息模型:一个工具调用异常 + 两次重试失败,在 APM 看来就是三次健康请求。Sentry 也坦诚写过自己的 MCP 服务器长到每月 5000 万请求量级时,唯一的故障发现方式是用户发邮件说”你们的工具挂了”——因为 API 面板上一切正常。
Spanly 就是为这个盲区而生:一个零代码改动的 MCP 可观测性侧车代理(sidecar proxy),让你清楚地看到每个 Agent 在你的工具里到底在干什么。
安装与环境
Spanly 提供三种接入方式,覆盖不同技术栈。
方式一:CLI 侧车代理(推荐,零代码改动)
npx -y @spanly/spanly run -- <你的 MCP 服务器命令> brew install spanlyhq/tap/spanly
方式二:TypeScript SDK
npm install @spanly/sdk
方式三:Python SDK
pip install spanly
核心的 sidecar 代理使用 Go 编写(Apache-2.0 协议),源码开源于 github.com/spanlyhq/spanly。免费层每月包含 10 万次请求追踪,超出后降级为 10% 采样,不会超量扣费。
实战场景 1:用 CLI 侧车启动任意 MCP 服务器
假设你有一个自建的 MCP 服务器,可能是 Node.js 的,也可能是 Rust 或 Python 的。传统 APM 需要安装 SDK、改代码、部署——Spanly 只需要在前面加一个命令:
npx -y @spanly/spanly run -- python my_mcp_server.py
Spanly 会自动:
- 充当 MCP 协议代理(支持 stdio 和 HTTP 两种传输方式)
- 捕获每条消息(不仅仅是 tool-call span)
- 识别客户端类型:Claude Code、Cursor、Copilot、ChatGPT、Windsurf、Cline、Zed……
- 记录请求延迟和错误详情
- 将遥测数据异步发送,不阻塞你的 MCP 服务器
启动后打开 app.spanly.com 就能看到实时数据。右侧面板同时展示”工程视图”(延迟百分位、错误率、调用链)和”产品视图”(哪些工具增长最快、每个会话 Agent 做了多少事)。无需 live demo 注册:app.spanly.com/share/demo 可以直接体验。
实战场景 2:用 Python SDK 监控 FastMCP 服务器
如果你的 MCP 服务器基于 FastMCP 框架(Python mcp 库),SDK 集成只需两行代码:
import os
from spanly import SpanlyClient
server = FastMCP("my_mcp_server")
SpanlyClient(api_key=os.environ["SPANLY_API_KEY"]).monitor(server)
server.run()
SpanlyClient 会自动读取 SPANLY_API_KEY 环境变量,无需显式传参。它还支持钩子函数(on_collect、on_error),可以在数据送往后台之前过滤敏感请求、附加租户标签,或是在出错时进行本地告警:
from spanly import SpanlyClient, MonitorOptions
def on_collect(direction, context, packet):
# 为多租户场景附加环境 ID
context.environment_id = current_tenant_id()
# 丢弃敏感工具调用
if looks_sensitive(packet):
return None
return packet
SpanlyClient().monitor(server, MonitorOptions(
on_collect=on_collect,
on_error=lambda e: log.error("spanly: %s", e),
))
Sidecar 模式下所有 MCP JSON-RPC 消息都会被捕获;SDK 模式下则是在进程内嵌入,适合测试集成(pytest/Jest)或无法启动额外容器的部署场景。
实战场景 3:生产级部署 — 与现有 APM 共存
Spanly 特别设计了与已有监控体系的互操作能力。它不做替换你的 Datadog 或 Sentry,而是补充:
在生产环境中,推荐将 CLI sidecar 注册为 systemd 服务,确保 MCP 服务器异常退出时自动重启:
cat > /etc/systemd/system/spanly-sidecar.service << 'EOF' [Unit] Description=Spanly MCP sidecar proxy After=network.target [Service] Type=simple Environment=SPANLY_API_KEY=your_key ExecStart=npx -y @spanly/spanly run -- python /opt/mcp/server.py Restart=always RestartSec=5 User=mcp [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now spanly-sidecar
关键特性:W3C traceparent 头部原封不动透传。这意味着你的 MCP 调用链可以跨接 Spanly 和已有 APM——在 Datadog 中看到的 HTTP 请求,可以追溯到 Spanly 中的 MCP 消息级别。
侧车还内置了敏感信息保护:Authorization、Cookie、API-Key 等凭证头部会在离开侧车前被自动脱敏。美国的遥测留在美国区域,欧盟的在欧盟区域。
最佳实践
- 先用 CLI 侧车模式:零代码改动,先跑起来看看能观察到什么。如果满意就保留,不满意随时停掉。
- 关注产品视图而非仅工程视图:Spanly 的产品视图会显示哪些工具被调用最多、哪些 Agent 最活跃、每周趋势——这些数据比单纯的错误率更能帮你判断 MCP 服务器的健康度。
- 结合已有 APM 使用:Spanly 的 sidecar 将 W3C traceparent 原封不动传给后端,所以你可以在 Datadog/Sentry 中看到 HTTP 请求级别,在 Spanly 中看到 MCP 消息级别,两边互不冲突。
- 留意免费层阈值:免费层每月 10 万次请求,换算下来日均约 3300 次调用。对于个人项目或小团队绰绰有余;如果达到阈值会降级为 10% 采样而非直接停服。
- Credential 安全:侧车默认脱敏敏感头部,但生产环境建议搭配
.env或密钥管理服务管理SPANLY_API_KEY,不要硬编码在命令中。
总结
MCP 正在成为 AI Agent 与外部工具之间的标准协议,但传统的 HTTP 级 APM 对这个新协议几乎毫无洞察力。Spanly 用一个轻量的 sidecar 代理填补了这个空白——不要求你改代码、不绑定语言、不替换已有监控体系,只是多了一层对 MCP 消息级别的可见性。
如果你的产品正在或即将提供 MCP 服务,Spanly 值得一试。开源 sidecar 和 SDK 在 GitHub,免费层即可上手体验。
本文提及的工具与平台均为独立第三方产品,与其开发者或公司无关联关系。