UncalledBook a demo

MCP analytics: what your logs can and can't show

Server-side MCP analytics show who called which tool. They can't show the calls that never happened. What each method sees, and how to fill the gap.

Updated 30 October 2026

MCP analytics usually means logging what reaches your server. That is worth doing, and it answers real questions: which tools get used, by which clients, how often they fail. It cannot tell you why the calls went down.

What your server can see

Your server receives requests, so it can record anything in them.

  • Which client connected. On older protocol versions, the initialize request carries clientInfo with a name and version. In the 2026-07-28 spec there is no handshake, and each request carries io.modelcontextprotocol/clientInfo in _meta. Either way the value is self-reported, and the schema says it is for display, logging and debugging.
  • Tool lists and tool calls. tools/list and tools/call are plain JSON-RPC requests. You get the tool name and the arguments, and you can measure duration and errors yourself.
  • The method, from HTTP headers. On 2026-07-28 Streamable HTTP, Mcp-Method and Mcp-Name mirror the method and tool name into headers, so a gateway can log them without parsing the body.

What your server can’t see

  • The prompt. The user’s message goes to the model, not to you.
  • The decision. In the spec’s flow, the model picks a tool on the client side. Your server hears about it only if the answer is yes. A skipped call produces no request, so it leaves no trace.
  • Whether the model saw your tool at all. A tools/list request doesn’t mean your tool is in the model’s context. Claude Code defers MCP tools by default: only names and server instructions load at session start, and definitions load on demand.
  • Every session. Clients may cache the tool list. The 2026-07-28 spec adds ttlMs and cacheScope for this, so list requests undercount sessions.

So when a graph goes quiet, your logs can’t separate three different situations:

  1. Fewer people are asking for what your tool does.
  2. People ask just as often, and agents now answer another way.
  3. Agents no longer load or see your tool.

The first is a market problem. The other two are problems you can fix, usually in the tool description, but only if you know which one you have.

What to log anyway

Keep this small. You want to be able to answer “which tool, which client, did it work”.

Field Why
Method and tool name The base count for everything else
Client name and version Shows when one agent changes while others don’t
Duration and error flag Separates “not called” from “called and failed”
Protocol version Shows which clients have moved to the newer spec

OpenTelemetry has draft semantic conventions for MCP, still marked as in development. They name spans {mcp.method.name} {target}, for example tools/call track_order, and use attributes such as mcp.method.name, gen_ai.tool.name and mcp.protocol.version. Following them now saves a migration later. Tool arguments and results are opt-in there, which is a sensible default for privacy.

What the existing tools measure

These products do what they say. All of them work from events your server sends.

Tool What it records Worth knowing
PostHog MCP Analytics Tool calls, tool lists, reported models, failures, and requests for missing capabilities In beta. Its docs include a query for advertised tools that are never called
AgentCat (docs.mcpcat.io redirects here) Tool, resource and prompt events, client info, sessions, and the agent’s goal Groups stateless traffic into sessions by user, client and a 30-minute window
OpenTelemetry Whatever you instrument, in your own backend Conventions are still in development

PostHog and AgentCat can both add a context argument to your tool schemas, so the agent explains why it is calling. That is useful intent data, but it only exists for calls that happen.

A “never called” query is the closest a log gets to the real gap. It finds tools nobody uses at all. It can’t tell you that a tool used to be called on 84% of order questions and is now called on 31%, because a log has no count of the questions.

How to see the calls that didn’t happen

You have to measure from the agent’s side: put a known number of prompts in, and count how many produce a call.

  1. Write the prompts your users would type. OpenAI’s golden prompt set is a good recipe: direct prompts that name your product, indirect prompts that only describe the outcome, and negative prompts where another tool should handle it.
  2. Run each one several times in each agent. The same prompt doesn’t always produce the same tool call, so one run proves little.
  3. Count calls in your own server log. That is your ground truth, and it works for any agent.
  4. Repeat on a schedule. Models and agent apps change without you releasing anything. A number you measured once won’t warn you about that.

How to test an MCP server has the commands for each agent.

Uncalled is step 4 as a service: the same prompts, every day, in each agent, with an alert when the rate drops. It isn’t live yet. If you want the number for your server before then, send the URL to hello@uncalled.app and I’ll run it by hand.

Find out whether agents still call your tool.

Twenty minutes on Google Meet, plus a free call-rate report if you share your MCP server.

Book a 20-min demo