See which MCP tools fail for which clients

Attach the last tool calls of the account to every support ticket, as metadata.mcp.recentCalls with the client user agent. Then group the failed calls of your tickets by tool and by client. The top row is the tool that fails most and the client that hits it. This shows the failures your users reported, with no extra logging on their side.

What the ticket carries

When a user opens a ticket through support_open_ticket, your server adds the context. Nobody types it.

"metadata": {
  "mcp": {
    "client": { "userAgent": "claude-user/1.0" },
    "catalogueVersion": "1.8.0",
    "recentCalls": [
      { "tool": "approve_drafts", "at": "2026-10-05T09:14:02Z", "ms": 212, "ok": false, "error": "FORBIDDEN" },
      { "tool": "list_campaigns", "at": "2026-10-05T09:13:40Z", "ms": 95, "ok": true }
    ]
  }
}

Step by step

  1. 1. Attach the recent calls to every ticket

    Your server records the last calls of each account: tool, time, duration, ok or failed, error code. When a ticket is opened, it adds them as metadata.mcp.recentCalls, with the client user agent and the catalogue version.

  2. 2. Read the tickets with their metadata

    In service mode, list the workspace tickets and read each one's metadata. The REST API and the team's MCP connector (list_tickets, get_ticket) both return it.

  3. 3. Count failed calls by tool and by client

    Skip the calls that worked. Group the failed ones by tool name and by client user agent. The top row is the tool that fails most, for the client that hits it.

  4. 4. Split by error code

    One tool can fail for two reasons. Group by the error code too: a FORBIDDEN on one client is a permission rule, a TIMEOUT on all clients is your server.

  5. 5. Check the catalogue version

    If one client fails on a tool that works for the others, compare the catalogue version in the ticket. An old tool list is the usual cause, and the fix is to re-add the connector.

Count them

// tickets: the list your workspace returns (service mode), each with metadata.mcp
type Call = { tool: string; ok: boolean; error?: string };
type Ticket = { id: string; metadata?: { mcp?: { client?: { userAgent?: string }; recentCalls?: Call[] } } };

function failuresByToolAndClient(tickets: Ticket[]) {
  const rows = new Map<string, { tool: string; client: string; failed: number; tickets: Set<string> }>();
  for (const t of tickets) {
    const mcp = t.metadata?.mcp;
    const client = mcp?.client?.userAgent ?? "unknown";
    for (const c of mcp?.recentCalls ?? []) {
      if (c.ok) continue;
      const key = c.tool + "|" + client;
      const row = rows.get(key) ?? { tool: c.tool, client, failed: 0, tickets: new Set() };
      row.failed += 1;
      row.tickets.add(t.id);
      rows.set(key, row);
    }
  }
  return [...rows.values()].sort((a, b) => b.failed - a.failed);
}

Questions

Does this show every failed call?
No. It shows the calls around a ticket: the last calls of an account at the moment a user asked for help. It is a view of the failures people cared about enough to report, not a full log of your traffic.
Do I need a separate analytics tool?
For a full log of all calls, yes, use one. For knowing which failures reach your users and who they are, the tickets already carry it.
Is anything secret sent in the calls?
It should not be. Attach the tool name, the time, the duration and the error code. Leave out tokens, passwords and message bodies.

First make your errors useful: handle MCP tool errors so the user gets help. The calls to list tickets and read their metadata are in the docs for agents. Plans, including ticket analytics per tool and per client, are on the pricing page.