跳到正文
DEV Community· Marianne·· 2 小時前AI 評分64

MCP 監控:智能體為何會靜默失敗,以及如何捕捉問題

MCP Monitoring: Why Your Agents Fail Silently and How to Catch It

AI 導讀

MCP 監控需要涵蓋工具層錯誤、工具誤用、延遲及 schema 漂移,因為伺服器回傳成功的 HTTP 狀態碼不代表智能體任務成功。指南比較 OpenTelemetry MCP 慣例、Datadog、託管平台日誌及 MCP Inspector,並以 Elva MCP Monitor 示範定時執行 initialize 握手、工具清單比對和可選的唯讀工具呼叫。

正文

Your MCP server is returning 200s. Your uptime dashboard is green. And an agent somewhere just told a user "I couldn't complete that request" for the fortieth time today.

That gap is what MCP monitoring is about. When an MCP server breaks, a person rarely sees an error page. An agent reads a failure, retries, picks a different tool, or gives up and summarizes the problem in natural language. None of that shows up in a classic HTTP monitor.

This guide covers why MCP needs its own monitoring, which signals are worth capturing, the main tools you can use today, and a walkthrough of one hosted option.

Why MCP monitoring is different from API monitoring

Classic API monitoring assumes a request, a status code, and a human or a service that notices when things go wrong. MCP breaks most of those assumptions.

Failures can be invisible at the transport layer. In MCP, a tool that fails can return a normal JSON-RPC result with isError: true in the body. The HTTP response is still a success. If you only count 5xx responses, you will miss every tool-level error.

Agents don't file tickets. A human who hits a broken endpoint tries once and complains. An agent may retry in a loop, burn tokens, and move on. The only witness is the traffic itself.

Tool misuse looks like success. An agent can call the wrong tool, or the right tool with poorly chosen arguments, and get a valid response. Usually the cause is a vague description or two tools that look alike. Your server did its job. The user still got a bad answer.

Latency compounds. One agent task can chain several tool calls. A tool with a slow p95 doesn't just slow one request. It stretches the whole task, and clients may time out partway through.

Schemas drift. Agents read your tools/list output and take input schemas literally. Rename a parameter or remove a tool, and clients that cached the old shape start failing. Nothing on the server side registers it as an error.

The handshake can break while the host is up. A server can answer a ping and still fail initialize, return an HTML error page where JSON-RPC should be, or reject credentials after an OAuth change.

What signals to capture

Whatever tool you pick, aim to capture these:

  • Handshake health: whether initialize succeeds, how long it takes, and which protocol version and transport were negotiated.
  • Tool inventory: the current tools/list output, compared against the previous one, so added, removed, or changed tools are visible.
  • Per-tool error rate: including results with isError: true, not just protocol or HTTP errors.
  • Latency percentiles per tool: p50 and p95 at minimum, since averages hide the slow tail agents time out on.
  • Caller identity: which client or agent made the call (Claude, Cursor, a partner's bot), and which key or user it used.
  • Token or payload size: large, unpaginated responses are expensive for the agent even when they succeed.
  • Retries and loops: repeated calls to the same tool with similar arguments in a short window.
  • Trace context: a trace ID that links the agent's LLM call to the tool call to your backend, so you can follow one task end to end.

Approaches and tools

There is no single right layer. Some teams instrument the server code, some trace the client, some put a gateway in front, and some run synthetic checks from outside. Most production setups combine at least two of these.

OpenTelemetry with the MCP semantic conventions

OpenTelemetry now has semantic conventions for MCP, currently marked as in development. They define client and server spans named {mcp.method.name} {target}, for example tools/call get-weather, with attributes such as mcp.method.name, mcp.protocol.version, and gen_ai.tool.name. They also define duration metrics like mcp.server.operation.duration.

Trace context travels inside the MCP request's params._meta rather than only in HTTP headers, which SEP-414 documents in the MCP spec. That matters because one MCP request can span several HTTP requests, and one HTTP stream can carry several MCP messages.

The official Python and TypeScript MCP SDKs emit these spans once you register an OpenTelemetry SDK. Per the Python SDK docs, a tool result with is_error=True sets the span status to error, which covers the silent-failure case above. The TypeScript docs note that spans don't record tool arguments or results by default.

From there you can send traces to any OpenTelemetry-compatible backend, such as Grafana Tempo, Jaeger, or a vendor platform. This is the most portable approach and works for self-hosted servers. You build the dashboards and alerts yourself.

Datadog Agent Observability

Datadog's MCP client guide covers automatic instrumentation for the official Python and JavaScript MCP SDKs, and manual instrumentation for other clients, including Java. For Python, the setup from their docs is:

pip install ddtrace
export DD_LLMOBS_ENABLED=true
export DD_LLMOBS_ML_APP=<YOUR_ML_APP_NAME>
export DD_LLMOBS_AGENTLESS_ENABLED=true
export DD_API_KEY=<YOUR_API_KEY>
ddtrace-run <YOUR_APP_STARTUP_COMMAND>

According to Datadog's auto-instrumentation docs, the Python integration also instruments the server side (initialize and tools/call), tagging spans with the client name and version. The manual instrumentation example explicitly marks a span as an error when result.isError is true. Their announcement post describes linking MCP spans to the LLM span that chose the tool, with aggregated p95 latency and error rates per tool and server.

This fits best if you already run Datadog and want MCP traces next to the rest of your APM data.

Speakeasy Gram tool logs

If your servers are hosted on Speakeasy's platform, the Tool Logs page is a raw log of every tool call. Its docs list filters for server, client (as reported at the MCP handshake), status, agent, and user, plus a summary strip with failure rate and blocked rate. MCP Insights rolls this up into call volumes and the tools with the most errors. Logs can also be exported to a collector, and there's an API for searching them.

MCP Inspector

The MCP Inspector is the official interactive tool for connecting to a server, listing its tools, and calling them by hand. It isn't a monitoring system, since nothing runs on a schedule and nothing alerts you. It's still the quickest way to reproduce a failure once your monitoring has flagged one.

Elva MCP Monitor and MCP logs

Elva, which builds hosted MCP servers from APIs, takes two angles. Elva-hosted servers come with call logs and insights. A newer feature, MCP Monitor, runs scheduled synthetic checks against any remote MCP server, including ones not hosted on Elva. The walkthrough below follows Elva's documentation.

Walkthrough: setting up an MCP monitor in Elva

Everything in this section comes from the MCP Monitor docs.

What each check does

Every check runs up to three steps:

  1. Handshake: runs the MCP initialize handshake and records latency, transport, and protocol version.
  2. Tool inventory: lists the tools and compares names and input schemas with the previous check. This is the schema drift signal from earlier.
  3. Read-only tool call (optional): calls one read-only tool with arguments you choose, as a synthetic test.

The result is one of four statuses:

  • Up: the handshake succeeded and every enabled check passed.
  • Degraded: the server answered, but tools/list failed, the tool call failed, or latency went over your threshold.
  • Down: no valid MCP response, for example DNS or TLS failure, timeout, 5xx, an HTML page instead of JSON-RPC, or rejected credentials.
  • Auth required: the server needs a credential or an OAuth reconnect before it can be checked.

A 429 is reported as rate limited, not as down.

Step 1: Add the server

Open MCP Monitor and enter the server URL, or pick one of your Elva-hosted servers.

Step 2: Authenticate

Choose None, Bearer token, API key header, Custom header, or OAuth. Per the docs, saved headers are encrypted at rest and not shown again.

Step 3: Choose what to check

Set the interval (every 1, 5, 15, 30, or 60 minutes), an optional latency threshold in milliseconds, and optionally one read-only tool to call. Free workspaces can check every 5 minutes or slower.

Step 4: Set alerts

Choose how many consecutive failed checks open an incident (2 by default), whether degraded checks count, and whether to notify when the tool inventory changes. Alerts can go to a Slack incoming webhook, up to five email recipients, or a signed webhook. Each monitor has Checks, Incidents, Tools, Alerts, and Settings tabs, and Send test on the Alerts tab tries every configured channel.

An incident opens when the failure threshold is reached and resolves on the next healthy check.

Handling webhook alerts

Webhook events are mcp_monitor.incident.opened, mcp_monitor.incident.resolved, mcp_monitor.tools.changed, and mcp_monitor.test. Here's the example incident payload from the docs:

{
  "event": "mcp_monitor.incident.opened",
  "occurredAt": "2026-11-02T10:00:00.000Z",
  "monitor": {
    "name": "Orders MCP",
    "url": "https://mcp.example.com/mcp",
    "status": "down",
    "slug": "orders-mcp",
    "statusPageUrl": "https://app.getelva.ai/status/orders-mcp"
  },
  "incident": {
    "startedAt": "2026-11-02T09:58:00.000Z",
    "cause": {
      "status": "down",
      "failureCode": "timeout",
      "message": "Handshake timed out"
    }
  }
}

Tool-change events include a toolsDiff with added, removed, and changed tools. Deliveries are signed with the same scheme as Elva's MCP webhooks, using the X-Elva-Signature and X-Elva-Timestamp headers, so verify them before acting on an event.

Status pages and one-off checks

You can publish a public status page at app.getelva.ai/status/<slug> and embed an SVG badge in a README. There's also a one-off check you can run without signing in, which produces a shareable report on the handshake, protocol version, transport, tools, and OAuth discovery.

On plan limits, the docs say Free workspaces can save 10 monitors with a 5-minute minimum interval.

Looking at real traffic

Synthetic checks tell you whether a server works. They don't tell you what agents actually do with it. For Elva-hosted servers, the MCP insights and logs page covers the traffic side: total requests, response-time percentiles, error rate, and token estimates over a date range, plus per-agent cards. Calling clients such as Claude, Cursor, Windsurf, and MCP Inspector are detected automatically from their requests. You can also follow logs from the terminal with elva-cli 1.2.0 or later:

elva mcp logs orders-mcp --follow

I covered Elva briefly in an earlier post, Postman Alternatives in 2026, from the API testing side. This post looks at the monitoring side.

How to choose

  • You run your own server and want portability: use the OpenTelemetry MCP conventions through the official SDKs, then send the data to the backend you already use.
  • You're already on Datadog: its MCP integration puts tool calls inside the same traces as the LLM calls that triggered them.
  • Your servers live on a hosted platform: start with that platform's logs (Gram's Tool Logs, Elva's MCP logs), then add external checks.
  • You need to know when a server breaks for agents, wherever it's hosted: add a synthetic monitor that runs the handshake and checks the tool list on a schedule. Elva's MCP Monitor is one option. A scheduled script using an official MCP SDK client is another.
  • You're debugging one failure right now: open MCP Inspector.

MCP monitoring checklist

  • [ ] Count tool results with isError: true as errors, not just HTTP and JSON-RPC errors.
  • [ ] Track p50 and p95 latency per tool, not per server.
  • [ ] Record which client or agent made each call.
  • [ ] Snapshot tools/list and alert when names or input schemas change.
  • [ ] Run a scheduled initialize handshake from outside your network.
  • [ ] Include at least one read-only synthetic tool call.
  • [ ] Propagate trace context through params._meta so agent, tool, and backend spans connect.
  • [ ] Watch response size and token usage for unpaginated tools.
  • [ ] Alert on repeated retries of the same tool from the same caller.
  • [ ] Treat auth and OAuth failures as their own status, separate from downtime.
  • [ ] Keep MCP Inspector handy for reproducing what your monitors find.

來源:DEV Community · dev.to