可观测性
MCP 请求会与模型流量一起出现在访问日志、用量事件管道和 Prometheus 指标中。MCP 专用字段会标识 JSON-RPC 操作、调用的工具和发现结果。工具调用失败时由 error_class 和 error_message 说明,因为其状态通常仍是 200。
使用访问日志调查单个请求,再使用用量事件和指标监控工具调用流量。限流和安全护栏阻断都会出现在这些信号中。在 AISIX Enterprise 和 AISIX Cloud 中,预算拒绝也会出现在这里。
访问日志
AISIX 处理完发往 /mcp 或 /mcp/{server} 的请求后,会写入访问日志。被身份认证拒绝的请求同样会写入一条,带有其 401 或 403 状 态码,但不含调用方 API Key ID。标准字段提供请求状态、延迟、调用方 API Key ID 和请求 ID;MCP 专用字段说明具体操作:
| 字段 | 出现条件 | 值 |
|---|---|---|
mcp_method | 请求体是包含方法的单个 JSON-RPC 对象。 | 方法,例如 initialize、tools/list 或 tools/call;在 UTF-8 字符边界截断为 256 字节。即使不受支持的协议版本导致请求提前返回 400,AISIX 也会记录该字段。 |
mcp_tool | 方法为 tools/call 且存在 params.name。 | 客户端发送的工具名称;在 UTF-8 字符边界截断为 256 字节。 |
tools_total | AISIX 处理 tools/list 请求。 | 访问策略过滤前,从查询成功的上游服务器返回的工具数量。请求被更早的检查拒绝时,该字段不存在。 |
tools_returned | AISIX 处理 tools/list 请求。 | 访问策略过滤后返回给调用方的工具数量。请求被更早的检查拒绝时,该字段不存在。 |
AISIX 无法推导的字段会被省略。例如,批量请求或 AISIX 无法解析的请求体没有 mcp_method。访问日志绝不会包含工具参数或结果。
诊断空工具列表
当 tools/list 没有返回工具时,请比较两个工具计数和附近的告警:
| 观察结果 | 可能原因 | 检查项 |
|---|---|---|
tools_total 大于零、tools_returned 为零,并 出现 no MCP access policy or key-level grant applies 告警。 | 调用方没有访问授权。 | 为调用方添加访问授权。 |
tools_total 大于零、tools_returned 为零,并出现 exclude every upstream tool 告警。 | 授权存在,但过滤掉了所有发现的工具。 | 修正适用的允许列表、拒绝列表或匿名允许列表。 |
出现 skipping upstream in tools/list: list_tools failed 告警。 | 指定上游失败,但 AISIX 继续查询其它上游。该上游的工具不会计入任何一个计数。 | 检查该服务器的可达性、身份认证和协议配置。 |
| 两个计数都为零,且没有上游失败告警。 | 查询成功的上游均未返回工具。 | 检查是否至少有一个已启用并公开工具的上游。 |
日志收集、标准字段和请求 ID 关联方式请参见访问日志与请求关联。
用量事件
tools/call 请求是否产生用量事件取决于 AISIX 已处理到哪个阶段:
| 结果 | 用量事件 |
|---|---|
AISIX 在工具调用核算前拒绝请求,例如身份认证失败、指定了未知服务器、请求体无法读取或过大、JSON 无效、AISIX 无法解析 params 的结构,或协议版本不受支持。 | 不发出。 |
| 请求进入工具调用核算。 | 即使缺少 params 或工具名称,或之后被访问控制、限流、安全护栏、控制面预算或 MCP 协议处理器拒绝,也会发出。 |
当安全护栏或内容采集需要 AISIX 回读工具结果,而回读失败(结果超过请求体上限,或响应体损坏)时,调用方收到 502,用量事件也记录状态 502。握手和发现方法不产生用量事件。
事件会标识调用方、服务器、工具和耗时,并在调用失败时说明失败原因:
| 字段 | 值 |
|---|---|
inbound_protocol | mcp |
mcp_server_name | 工具所属的已注册服务器。 |
mcp_tool_name | 被调用的上游工具。 |
api_key_id | 发起调用的调用方 API Key。 |
status_code | 调用方收到的 HTTP 状态。工具调用失败时通常仍为 200。参见工具调用失败。 |
error_class、error_message | 网关记录下的失败。参见工具调用失败和读取错误类别。 |
upstream_latency_ms | 上游工具调用所花费的时间。 |
downstream_latency_ms | 调用方等待工具调用完成的总时间。 |
guardrail_blocked | 当输入或输出被安全护栏阻断时为 true。 |
request_id、occurred_at | 关联 ID 和时间戳。 |
MCP 工具调用没有模型 Token,因此 Token 和成本字段为零。需要按工具归因调用量时,请使用 mcp_server_name 和 mcp_tool_name,而不是依赖 Token 或花费分析。
MCP 目前只执行一次贯穿整个请求的上游尝试,因此 upstream_latency_ms 和 downstream_latency_ms 会报告相同的时长。保留两个独立字段可使 MCP 记录与其它网关流量保持一致;在其它流量中,重试和网关处理可能使两者不同。
基础用量事件不包含工具参数或结果。启用完整内容采集后,通过流量控制和输入安全护栏检查的 tools/call 可以在完成数据脱敏后导出 params.arguments。如果响应包含 JSON-RPC result,导出器也可以采集该结果。输出安全护栏阻断会抑制这两个字段,其它 MCP 方法不会被采集。请参见配置内容采集。
MCP 用量事件会通过与模型用量事件相同的路径投递。所有已配置的可观测性导出器都会收到这些事件,因此 MCP 流量会与其它网关流量一起出现在导出链路中。在 AISIX Enterprise 和 AISIX Cloud 中,这些事件也会流入控制面的用量接收端。
工具调用失败
失败的 tools/call 仍以 HTTP 200 应答,内容是 JSON-RPC error 或带 isError 标记的结果。调用方收到的响应不变,事件的状态也保持 200,但事件会说明失败原因:
| 失败情况 | error_class | error_message | error_source 指标标签 |
|---|---|---|---|
工具返回 isError: true。 | tool_error | MCP tool returned isError | upstream |
| 上游返回 HTTP 错误。OpenAPI 类型服务器背后的 API 返回 HTTP 错误时同样归入此类。 | upstream_status | upstream MCP server returned HTTP <status> | upstream |
| 上游超时。 | timeout | upstream MCP server timed out | upstream |
| 到上游的连接失败。 | transport | upstream MCP server connection failed | upstream |
| 上游返回 JSON-RPC 错误。 | upstream_in_band | upstream MCP server returned JSON-RPC error <code> | upstream |
| AISIX 无法读取上游响应。 | upstream_decode | upstream MCP server returned an undecodable response | upstream |
| AISIX 无法获取上游凭证,包括 Token 交换或用户 OAuth 登录失败。 | credential_error | MCP upstream credential unavailable | aisix |
| 调用方的访问规则不允许使用该工具。 | permission_denied | MCP tool access denied | aisix |
| OpenAPI 类型的服务器没有该工具。 | tool_not_found | MCP tool not found | aisix |
导出器会把这些事件视为失败行,访问日志行报告相同的 error_class,控制台的 日志 视图也会把它们标为 工具错误,展开该行可看到 HTTP 状态码 200。由于状态仍是 200,只按状态查询找不到这些记录,统计失败时还要按 error_class 统计。
以下调用与上表不同:
- 在单服务器端点
/mcp/{server}上,Token 交换或用户 OAuth 登录失败会以各自的 HTTP 状态(例如401或503)应答,事件也记录该状态。 - 安全护栏拦截同样以
200和isError应答,但事件带有guardrail_blocked=true和error_classcontent_filter。 - 工具要求进一步的交互输入或转为异步任务时不做标记。调用方收到 JSON-RPC 错误,
error_class和error_message保持为空。
error_message 是固定文本,工具或上游返回的原文不会进入其中。使用 content_mode: full 时,经过数据脱敏的工具结果会进入链路的 gen_ai.tool.call.result 和失败行的响应。使用 metadata_only 时,不导出任何工具内容。请参见配置内容采集。
1.9.0 及更早版本的网关会把 HTTP 200 下失败的工具记录为成功,error_class 和 error_message 为空,安全护栏拦截除外。
指标
MCP 请求会出现在网关的 Prometheus 指标中,并携带可用于区分模型流量的标签。使用下列标签筛选相关指标序列:
| 目标 | 指标 | 过滤条件 |
|---|---|---|
| 跟踪活跃 MCP 请求。 | aisix_proxy_in_flight_requests | inbound_protocol="mcp" |
| 检查 MCP 用量事件投递。 | aisix_usage_events_emitted_total | handler="mcp" 和 inbound_protocol="mcp" |
指标通过 专用指标监听器的 GET /metrics 暴露。完整指标目录和标签语义请参见指标参考。
验证指标
要验证 MCP 指标是否发出,请先通过网关发送一次 MCP 工具调用,然后抓取专用指标监听器。下面的示例使用默认监听地址和路径。如果你的启动配置设置了其它 observability.metrics.prometheus.addr,请使用对应地址。
指标族会在首次观测后注册,因此只有记录过工具调用后才会出现 MCP 序列:
curl -sS "http://127.0.0.1:9090/metrics" | grep 'inbound_protocol="mcp"'
输出中应包含带有以下标签的指标样本:
| 指标 | 标签 |
|---|---|
aisix_proxy_in_flight_requests | inbound_protocol="mcp" |
aisix_usage_events_emitted_total | handler="mcp" 和 inbound_protocol="mcp" |
下一步
你现在已经了解如何通过访问日志诊断 MCP 请求,以及工具调用会出现在用量事件和指标中的哪些位置。使用下面的指南查看完整指标目录,或调整产生这些信号的流量: