← Blog

MCP Observability: Logs, Metrics, and Protocol-Level Checks

By admin · Jun 17, 2026 · 4 min read

Observability for a normal web service asks "is it up, and is it fast?" Observability for an MCP server has to ask a third question: "is the contract it's exposing to AI clients still the one they last saw?" Miss that third question and everything on your dashboard can look green while agents calling your tools quietly start failing.

The three things worth watching

MCP observability breaks down into logs, metrics, and protocol-level checks. Logs tell you what happened for a specific call. Metrics tell you the shape of behavior over time. Protocol-level checks tell you whether the server is honoring the contract it advertises — independent of whether any client happened to call it recently.

What to put in your logs

Structured logging is non-negotiable here, because you'll want to query these fields later, not grep them. A useful log line for a tool call captures:

{
  "ts": "2026-07-29T14:02:11Z",
  "server": "weather-mcp",
  "tool": "get_forecast",
  "caller": "agent-42",
  "protocol_version": "2026-07-28",
  "duration_ms": 184,
  "jsonrpc_error": null
}

A few things worth calling out. The caller field matters more than it used to: the 2026-07-28 spec removed protocol-level sessions (no more Mcp-Session-Id), so if you need to correlate calls from the same agent across requests, you now need an explicit application-level handle rather than relying on a session the transport hands you. And protocol_version earns its own field because, for a while yet, you'll have some clients still negotiating the older initialize-based handshake and others using the newer server/discover flow — you want to know which one you're actually seeing traffic from.

Metrics that actually predict trouble

Raw request counts are the least useful metric you can track. What matters more:

Protocol-level checks are not the same as uptime

A generic uptime monitor confirms a port is open or an HTTP endpoint returns 200. Neither confirms your server can actually complete an MCP exchange. A protocol-level check does the real thing: negotiates capabilities the way a client would, then calls tools/list and validates the shape of what comes back.

The check that catches the most real incidents isn't availability at all — it's a diff. Store the last known-good tools/list response, hash or structurally compare each new one against it, and alert specifically when a tool's name, required parameters, parameter types, or enum values change. MCP has no built-in versioning enforcement for tools, so a server can rename a parameter or quietly drop a tool and nothing in the protocol announces it. Watching for it is the only way to catch it before an agent does.

Alerting: separate "down" from "different"

Logs are not natively actionable for paging — you need metrics and thresholds behind an alert, not a promise to "check the logs later." Split your alerts into at least two categories: availability failures (handshake doesn't complete, requests time out, transport drops connections) and contract failures (the server answers fine, but the schema underneath it moved). The second category is the more dangerous one precisely because everything else on a standard dashboard looks fine.

This is the exact niche MCP Vitals runs in continuously: it performs the real handshake against your server, diffs tools/list against history, and separates availability alerts from schema-drift alerts so you're not stuck sifting through generic uptime noise for the change that actually matters.

Closing

Good MCP observability isn't a fancier dashboard — it's answering a question generic tooling was never built to ask: has the contract changed? If your current setup can't tell you that without you manually re-reading a schema, it's worth closing that gap before an agent finds it for you.

Monitor your MCP server — free

Real handshake checks, tool-schema drift detection, and a public health badge in 60 seconds.

Start free