MCP日志与可观测性
4951 字约 17 分钟
AIAgentMCP可观测性
2026-07-24
MCP 可观测性是对 Host-Client-Server 三层架构运行状态的度量、记录和分析能力。与传统微服务可观测性不同,MCP 的可观测性需要额外关注 Token 消耗、上下文膨胀以及敏感数据脱敏——因为日志和追踪数据本身可能成为 LLM 上下文的一部分。
一、基本定义
MCP 日志与可观测性是指在 Model Context Protocol 系统中,通过日志(Logs)、指标(Metrics)、追踪(Traces)三大支柱,对协议通信、Tool 调用、资源访问和 Agent 行为进行记录、度量和分析的机制与实践。
核心特征:
- 三层架构感知:需要覆盖 Host、Client、Server 三层的运行状态
- 面向模型与人类:可观测数据既服务于开发者的运维排查,也可能被模型消费用于决策
- Token 敏感:日志和追踪数据的体积直接影响上下文窗口使用量
- 脱敏优先:敏感数据(凭证、个人数据、API Key)不得出现在日志中
二、为什么可观测性在 MCP 中很重要
传统微服务的可观测性主要服务于人类运维。MCP 场景带来了新的复杂性:
- 调用链路长且间接:Host → Client → Server → 外部依赖,一个 Tool 调用可能经过 4-5 层传递,任何环节的异常都需要可追踪
- 模型依赖环境信息做决策:模型需要根据 Tool 返回结果、错误信息判断下一步行动,可观测数据的质量直接影响 Agent 行为
- 多 Server 并行:一个 Host 可能同时连接多个 MCP Server,需要统一视角观察各 Server 的健康状态
- 安全风险高:MCP Server 可能访问数据库、文件系统、外部 API,操作日志是安全审计的基础
- 成本可见性:每次 Tool 调用和 Resource 注入都消耗 Token,没有可观测性就无法控制成本
- 问题定位困难:当模型行为异常时,需要区分是模型推理问题、Tool 返回问题还是协议通信问题
三、三大支柱在 MCP 中的应用
3.1 日志(Logs)
日志是最基础的可观测手段,记录离散事件的结构化描述。
在 MCP 中,日志按层次分布:
| 层次 | 日志内容 | 示例 |
|---|---|---|
| Host 层 | 模型调用决策、Tool 选择、上下文组装 | "Model selected tool 'query_db' for task" |
| Client 层 | 连接管理、请求路由、重试行为 | "Server 'pg-server' connection established" |
| Server 层 | Tool 执行、Resource 读取、权限检查 | "Tool 'query_db' executed in 230ms, returned 15 rows" |
日志级别使用建议:
- ERROR:Tool 执行失败、连接中断、协议错误
- WARN:超时重试、降级触发、权限拒绝
- INFO:连接建立、初始化完成、Tool 调用成功
- DEBUG:请求/响应参数(脱敏后)、协议消息详情
3.2 指标(Metrics)
指标是可聚合的数值度量,用于监控和告警。
MCP 核心指标将在第五节详细展开。指标通常通过 Prometheus 格式或 OpenTelemetry Metrics 导出,配合 Grafana 等工具进行可视化。
3.3 追踪(Traces)
追踪记录一次完整请求在各层的执行路径和耗时。
MCP 中的追踪将在第六节详细展开。由于 Host-Client-Server 的三层架构,追踪需要跨进程传递上下文,通常基于 OpenTelemetry 的 W3C Trace Context 标准实现。
四、结构化日志
MCP 日志必须是结构化的(JSON 格式),而非纯文本。结构化日志可以被自动解析、搜索和聚合。
每条日志应包含以下核心字段:
{
"timestamp": "2026-07-23T10:30:00.123Z",
"level": "INFO",
"requestId": "req-042",
"sessionId": "sess-abc-123",
"serverId": "pg-server",
"toolName": "query_database",
"durationMs": 230,
"message": "Tool executed successfully",
"metadata": {
"rowCount": 15,
"responseSizeBytes": 2048
}
}4.1 核心字段说明
| 字段 | 说明 | 生成位置 | 示例 |
|---|---|---|---|
requestId | 唯一请求标识,贯穿整个调用链 | Host 层生成,逐层传递 | "req-042" |
sessionId | 会话标识,关联同一用户会话的多次请求 | Host 层生成 | "sess-abc-123" |
serverId | 目标 Server 标识 | Client 层分配 | "pg-server" |
toolName | 被调用的 Tool 名称 | Client/Server 层 | "query_database" |
durationMs | 调用耗时(毫秒) | Server 层记录 | 230 |
error | 错误信息(仅错误日志) | 各层 | {"code": -32030, "message": "..."} |
4.2 字段传递规则
requestId在 Host 层生成后,通过 JSON-RPC 的id字段或自定义 header 传递到 Client 和 ServersessionId用于聚合分析,同一会话内的所有请求共享- Server 在日志中同时记录自己生成的
traceId和上游传入的requestId,便于关联查询
五、关键指标
5.1 指标清单
| 指标名称 | 类型 | 说明 | 告警阈值参考 |
|---|---|---|---|
mcp.tool.success_rate | Gauge | Tool 调用成功率 | < 95% 告警 |
mcp.tool.error_rate | Gauge | Tool 调用错误率 | > 5% 告警 |
mcp.tool.timeout_rate | Gauge | 超时请求占比 | > 2% 告警 |
mcp.tool.retry_count | Counter | 重试次数(按 Tool 分组) | 持续增长告警 |
mcp.tool.response_size | Histogram | 返回结果大小分布 | P99 > 50KB 告警 |
mcp.server.init_latency | Histogram | Server 初始化延迟 | P99 > 5s 告警 |
mcp.tool.call_latency | Histogram | Tool 调用延迟 | P95 > 10s 告警 |
mcp.connection.active | Gauge | 活跃连接数 | 接近上限告警 |
mcp.token.usage | Counter | Token 消耗量 | 接近配额告警 |
mcp.permission.denial_count | Counter | 权限拒绝次数 | 频繁拒绝告警 |
5.2 指标聚合维度
指标应支持以下维度的聚合和查询:
- 按 Server:识别哪个 Server 有问题
- 按 Tool:识别哪个 Tool 不稳定
- 按错误类型:区分超时、权限、参数错误
- 按时间段:识别异常时间窗口
- 按 Session:识别特定用户的问题
六、追踪(Tracing)
6.1 跨 Client-Server 的请求追踪
MCP 的 Host-Client-Server 三层架构意味着一个用户操作可能跨越多个进程。追踪的目的是将分散在各层的日志关联为一条完整的调用链。
典型追踪场景:
用户提问 "查询最近的销售数据"
├── [Host] 模型选择 Tool "query_sales" (12ms)
├── [Host → Client] 发送 tools/call 请求
│ ├── [Client → Server] JSON-RPC 请求 (2ms 传输)
│ ├── [Server] 执行 SQL 查询 (180ms)
│ ├── [Server] 格式化结果 (15ms)
│ └── [Client] 接收响应,传递给 Host
└── [Host] 模型处理返回结果,生成回答 (350ms)6.2 关联 ID 传递
追踪依赖关联 ID 在各层之间传递。推荐基于 OpenTelemetry 的 W3C Trace Context 标准:
traceId:全局唯一,标识一次完整调用链spanId:标识当前层的一个执行单元parentSpanId:指向上游层的 span
在 MCP 协议中,关联 ID 的传递方式:
- stdio 传输:通过 JSON-RPC 消息的自定义字段传递
- HTTP/SSE 传输:通过
traceparentHTTP Header 传递
6.3 调用链中的 Span 结构
| Span 名称 | 所属层 | 记录内容 |
|---|---|---|
model.inference | Host | 模型推理耗时、Token 使用量 |
tool.selection | Host | Tool 选择决策过程 |
mcp.call | Client | 端到端调用耗时 |
mcp.transport | Client/Server | 传输层耗时 |
tool.execute | Server | Tool 实际执行耗时 |
resource.read | Server | Resource 读取耗时 |
external.api | Server | 外部依赖调用耗时 |
七、审计日志(Audit Log)
审计日志与普通操作日志不同——它记录的是安全相关事件,用于合规审查和安全分析。审计日志不可篡改,保留期限通常更长。
7.1 必须记录的事件
| 事件类型 | 记录内容 | 重要性 |
|---|---|---|
| 用户确认记录 | 哪个用户确认了哪个操作、确认时间、操作参数 | 高 |
| 权限拒绝记录 | 被拒绝的 Tool 调用、拒绝原因、请求参数 | 高 |
| 高风险操作记录 | 写入/删除操作、批量操作、外部 API 调用 | 高 |
| 外部依赖调用记录 | 调用了哪些外部服务、调用目的、响应状态 | 中 |
| 认证事件 | 连接建立、认证失败、Token 过期 | 高 |
| 配置变更 | Server 配置修改、权限规则变更 | 高 |
7.2 审计日志格式
{
"timestamp": "2026-07-23T10:30:00.123Z",
"eventType": "TOOL_CALL_CONFIRMED",
"actor": {
"type": "user",
"id": "user-001",
"session": "sess-abc-123"
},
"action": {
"type": "tool_call",
"toolName": "delete_record",
"serverId": "db-server",
"parameters": { "table": "orders", "id": "***" }
},
"result": "CONFIRMED",
"riskLevel": "HIGH"
}注意:审计日志中的参数也需要脱敏处理(参见第九节)。
八、Token 和上下文影响
MCP 可观测性的一个独特关注点是 Token 消耗——这是传统系统没有的维度。
8.1 Tool 描述占用的 Token
每个 Tool 的名称、描述和参数 Schema 都会被注入到模型的上下文中。当连接的 Server 多、Tool 数量大时,仅 Tool 描述就可能占用大量 Token。
监控指标:
mcp.tool.description_tokens:每个 Tool 描述占用的 Token 数mcp.context.tool_total_tokens:所有 Tool 描述总 Token 数mcp.context.tool_ratio:Tool 描述占上下文窗口的比例
建议:Tool 描述总 Token 数不应超过上下文窗口的 30%,为输入和输出留足空间。
8.2 Resource 内容注入的 Token
Resource 内容(如文件内容、数据库查询结果)被注入上下文时,需要监控其 Token 消耗:
mcp.resource.content_tokens:单次 Resource 内容占用的 Token 数mcp.context.resource_total_tokens:所有 Resource 内容总 Token 数mcp.context.bloat_ratio:上下文膨胀率(当前 Token 数 / 上下文窗口上限)
8.3 上下文膨胀监控
上下文膨胀是指随着对话进行,累积的 Tool 调用结果和 Resource 内容逐渐占满上下文窗口,导致模型性能下降或无法接收新输入。
监控策略:
- 设置上下文使用率的分级告警:60%(提醒)、80%(警告)、90%(严重)
- 追踪单次对话中上下文增长趋势
- 记录触发上下文截断或摘要的事件
九、敏感数据脱敏
核心原则:敏感数据(Token、凭证、个人数据)不得出现在日志中。
这是 MCP 可观测性的底线要求。日志系统一旦被攻破或泄露,敏感数据暴露的后果远大于服务本身故障。
9.1 必须脱敏的数据类型
| 类别 | 示例 | 脱敏方式 |
|---|---|---|
| API Key / Token | sk-ant-xxx..., ghp_xxx | 仅保留前 4 位 + *** |
| 密码 / Secret | 数据库密码、OAuth Secret | 完全不记录 |
| 个人数据(PII) | 姓名、邮箱、电话、身份证号 | 哈希或掩码处理 |
| 认证凭证 | Bearer Token、Session Cookie | 完全不记录 |
| 内部地址 | 内网 IP、端口、数据库连接串 | 使用服务名替代 |
| 请求/响应体中的敏感字段 | SQL 查询中的用户数据、文件内容中的个人信息 | 字段级过滤 |
9.2 脱敏实现策略
- 在日志写入前统一拦截:使用中间件或日志 Hook,在日志输出前执行脱敏
- 基于字段名匹配:对名为
password、token、secret、api_key的字段自动脱敏 - 基于正则匹配:对日志文本中的 API Key 模式、邮箱模式、手机号模式进行正则替换
- 白名单模式:只记录白名单内的字段,其余一律丢弃
// 脱敏前
{"sql": "SELECT * FROM users WHERE email = 'alice@example.com'", "apiKey": "sk-ant-abc123"}
// 脱敏后
{"sql": "SELECT * FROM users WHERE email = '***'", "apiKey": "sk-a***"}9.3 日志中不应出现的内容清单
- 任何形式的凭证(密码、Token、Key、Secret)
- 完整的个人身份信息
- 内部网络拓扑信息
- 数据库连接字符串
- 第三方服务的完整 URL(含凭证参数)
- 未脱敏的请求/响应 Body(如果包含敏感数据)
十、日志留存策略
| 日志类型 | 建议留存期 | 存储方式 | 说明 |
|---|---|---|---|
| 操作日志(INFO) | 7-30 天 | 结构化日志系统 | 用于问题排查 |
| 错误日志(ERROR) | 90 天 | 结构化日志系统 | 用于分析和复盘 |
| 审计日志 | 1-7 年 | 不可变存储 | 合规要求 |
| 追踪数据 | 7-14 天 | 追踪存储(如 Jaeger) | 用于调用链分析 |
| 指标数据 | 90 天-1 年 | 时序数据库 | 用于趋势分析 |
留存策略需考虑:
- 存储成本与排查需求之间的平衡
- 合规要求的最低留存期限
- 过期日志的自动清理机制
- 敏感数据的留存需要额外保护
十一、告警策略
11.1 告警规则
| 告警名称 | 触发条件 | 严重级别 | 建议响应 |
|---|---|---|---|
| 错误率突增 | 5 分钟内错误率 > 10% | P1 - 严重 | 立即排查,可能触发熔断 |
| 延迟异常 | P95 延迟 > 阈值 2 倍 | P2 - 高 | 检查 Server 负载和网络 |
| 权限拒绝频繁 | 10 分钟内拒绝 > 20 次 | P2 - 高 | 检查权限配置是否异常 |
| Server 不可用 | 健康检查连续 3 次失败 | P1 - 严重 | 触发降级,检查 Server 进程 |
| Token 消耗异常 | 1 小时内消耗 > 预期 3 倍 | P2 - 高 | 检查是否存在异常调用循环 |
| 上下文膨胀 | 上下文使用率 > 90% | P3 - 中 | 触发上下文压缩或截断 |
| 重试风暴 | 重试率 > 30% 持续 5 分钟 | P2 - 高 | 检查后端服务健康状态 |
11.2 告警降噪
- 相同告警合并:5 分钟内相同告警合并为一条
- 告警抑制:P1 告警触发时,抑制相关的 P2/P3 告警
- 维护窗口:计划内维护期间暂时屏蔽特定告警
十二、SLO 设计
MCP 系统的 SLO(Service Level Objective)应覆盖以下维度:
| SLO 指标 | 目标值 | 测量方式 |
|---|---|---|
| Tool 调用可用性 | ≥ 99.5% | 成功响应数 / 总请求数 |
| Tool 调用延迟 P95 | ≤ 5s | 从请求发出到响应返回 |
| Server 初始化延迟 P99 | ≤ 3s | 从连接建立到 capabilities 交换完成 |
| 错误率 | ≤ 1% | 错误响应数 / 总请求数 |
| 日志完整率 | ≥ 99.9% | 有结构化日志的请求数 / 总请求数 |
SLO 与告警的关联:当指标接近 SLO 边界时(如消耗了 50% 的 Error Budget),触发预警。
十三、MCP logging/notifications 协议支持
MCP 协议本身提供了 logging 能力,Server 可以在 capabilities 交换中声明支持日志:
- Server 声明
loggingcapability 后,Client 可以通过setLevel请求设置日志级别 - Server 通过
notifications/message通知向 Client 发送日志消息 - 日志消息包含
level、logger、data字段
支持的日志级别(从低到高):
debug、info、notice、warning、error、critical、alert、emergency
这一机制使得 Client 可以动态调整 Server 的日志输出粒度,在排查问题时临时提升到 debug 级别,正常运行时保持在 info 或 warning。
需要注意的是,协议层的日志通知是补充手段,不能替代 Server 自身的结构化日志系统。协议日志主要用于 Client-Server 之间的调试通信,而完整的可观测性需要在各层独立实现。
十四、可观测性数据流
十五、设计原则
- 脱敏是底线:敏感数据(Token、凭证、个人数据)在任何情况下都不得出现在日志中
- 结构化优先:日志使用 JSON 格式,便于自动解析和聚合
- 关联 ID 贯穿全链路:每个请求生成唯一
requestId,沿 Host → Client → Server 传递 - 分层记录,统一聚合:各层独立记录日志,通过关联 ID 在分析层聚合
- Token 消耗可见:将 Token 使用量作为一等公民进行监控
- 审计与操作分离:安全审计日志独立于操作日志,使用更严格的留存策略
- 告警基于 SLO:告警规则与 SLO 绑定,避免无意义的告警噪音
- 动态可调:支持运行时调整日志级别,不需要重启服务
十六、常见误区
| 误区 | 正确做法 |
|---|---|
| 日志中记录完整的请求/响应 Body | 对敏感字段脱敏后再记录 |
| 只记录错误日志,不记录成功日志 | 成功日志用于基线对比和 SLO 计算 |
| 用纯文本日志 | 使用 JSON 结构化日志 |
| 每层独立生成 requestId | 在 Host 层生成,逐层传递 |
| 忽略 Token 消耗的监控 | Token 是 MCP 系统的核心成本指标 |
| 审计日志和操作日志混在一起 | 审计日志独立存储,不可篡改 |
| 所有日志保留同样长的时间 | 按日志类型制定差异化留存策略 |
| 设置大量告警但不降噪 | 告警合并、抑制,避免告警疲劳 |
| 只关注 Server 层的可观测性 | Host、Client、Server 三层都需要可观测性 |
| 将协议日志等同于完整可观测性 | 协议日志是补充手段,各层需要独立实现 |
十七、实践检查清单
日志
指标
追踪
审计
告警与 SLO
十八、与其他概念的关系
- MCP基础:可观测性建立在 MCP 协议的基本通信机制之上
- MCP架构总览:Host-Client-Server 三层架构决定了可观测性的分层设计
- MCP Server设计:Server 需要内置结构化日志和指标导出能力
- MCP Client设计:Client 需要实现追踪上下文传递和连接级监控
- MCP安全边界:审计日志和脱敏策略是安全边界的重要组成部分
- MCP错误处理:错误日志是日志系统的核心内容之一,Correlation ID 与追踪直接关联
- MCP协议生命周期:协议层提供了 logging/notifications 机制作为可观测性的补充
十九、适用边界
本文档覆盖的范围:
- MCP 系统的日志、指标、追踪三大支柱的设计与实践
- 审计日志的记录要求和脱敏策略
- Token 消耗和上下文膨胀的监控
- 告警策略和 SLO 设计
- MCP 协议原生的 logging 能力
不涉及的范围:
- 具体日志平台(ELK、Loki、CloudWatch)的部署和配置
- 具体指标平台(Prometheus、Datadog)的安装和调优
- LLM 模型本身的可观测性(属于 AI 系统层面的问题)
- MCP Server 内部的业务级监控(如具体 SQL 查询的性能分析)
- 前端 UI 层的监控和埋点