# MCP analytics

The Zuplo Portal includes a built-in analytics dashboard for the MCP Gateway.
Every authenticated MCP request produces structured analytics events, which roll
up into KPI cards, time-series charts, and ranked breakdowns of capabilities,
users, upstream servers, clients, and failure origins.

This page covers where the dashboard lives, what each section shows, the event
taxonomy that backs it, and how to forward the underlying data to your own
logging or metrics provider.

## Where to find it

The MCP dashboard is a tab on the regular **Analytics** page in the Zuplo
Portal:

- **Account scope.** Open
  [Analytics → MCP](https://portal.zuplo.com/+/account/analytics) for an
  aggregate view across every project on the account that has MCP routes.
- **Project scope.** Open the project, then
  [Analytics → MCP](https://portal.zuplo.com/+/account/project/analytics) for
  that project's events only.

The MCP tab appears automatically once any MCP request has been recorded for the
project. New projects show the empty state until the first MCP request lands.

## Dashboard layout

The dashboard renders in a fixed order so the layout doesn't reshape when
filters or time ranges change. Empty sections still render with their
empty-state copy.

### KPI cards

Four headline metrics across the top:

| Card                | What it shows                                                                                     |
| ------------------- | ------------------------------------------------------------------------------------------------- |
| **Events**          | Total MCP analytics events in the selected window.                                                |
| **Success Rate**    | Share of events with `outcome = success`, plus the underlying success and error counts.           |
| **p95 Latency**     | 95th percentile total latency for the window, with the gateway and upstream slices shown beneath. |
| **Failure Origins** | Total failures decomposed into gateway, upstream, and client buckets.                             |

### Events over time

A stacked area or bar chart of event volume, broken down by event type and
colored by outcome class. Use the toggle in the top-right to switch between area
(default for longer ranges) and bar.

Failure outcomes always render in red so error spikes are easy to spot. Hover
any series for the human-readable label and per-bucket count.

### Event families donut

Aggregate breakdown across the three event families:

- **Requests** (`mcp_request`) — MCP request acceptance and rejection events at
  the route boundary.
- **Capabilities** (`capability_invocation`) — per-tool, per-prompt, and
  per-resource invocations.
- **Auth** (`auth_event`) — OAuth flow events: token issued, token validated,
  consent approved, upstream connection completed, and so on.

### Latency split

Three series on one line chart — total p95, gateway-only p95, and upstream-only
p95 — with the latest p50 total and per-scope p95 KPIs tiled above. Use this to
separate "the gateway is slow" from "the upstream is slow" without leaving the
dashboard.

### Top capabilities

A ranked table of the most-used capabilities, with two toggles:

- **View toggle**: Most calls / Most errors / Slowest.
- **Type filter**: All / Tool / Resource / Prompt.

Columns: Server, Capability, Type, Calls, Errors, Error rate, p95.

Rows for events recorded before capability instrumentation shipped appear as
`(unknown)` in the Server column. Those rows don't drill on `virtualServerName`,
but the rest of the table does.

### Top users

Ranked by event volume per `subjectId`. The user column displays a formatted
email when the subject id contains one (e.g.,
`auth0|google-apps|alex@example.com` renders as `alex@example.com`), otherwise
the raw subject id.

### Top MCP routes and top upstream servers

Two ranked tables side-by-side:

- **Top MCP Routes** breaks down by the route's `operationId` — the gateway's
  identity for the inbound MCP route.
- **Top Upstream Servers** breaks down by the upstream's `id` from the token
  exchange policy — the identity for the proxied upstream MCP server.

Each MCP route proxies one upstream, so the two columns track together for most
projects. When you front a single upstream through multiple routes (for example,
a public route and a read-only internal route), the split shows up here.

### MCP methods, top clients, transport

Three small panels in a row:

- **MCP Methods** — top JSON-RPC methods invoked (`tools/call`, `tools/list`,
  `initialize`, etc.).
- **Top Clients** — clients identified during MCP `initialize` (name, title,
  version). MCP clients that don't send the `clientInfo` block show as a generic
  identifier.
- **Transport** — a donut chart for the connection transport. Gateway flows are
  always `http` (stateless Streamable HTTP); other transports only appear for
  projects mixing the gateway with the
  [MCP Server handler](../../handlers/mcp-server.mdx).

### JSON-RPC error codes and failure origins

Two breakdowns side-by-side:

- **JSON-RPC Error Codes** ranks the top error codes the gateway returned to
  clients. Most gateway flows leave this empty because failures are surfaced
  through MCP-level error responses rather than bespoke codes.
- **Failure Origins** decomposes failures by where they originated — gateway,
  upstream, or client — so an operator can answer "is this problem ours, theirs,
  or the client's?" without leaving the dashboard.

### Top reason codes

A final ranked table of `reasonCode` values across all events. Reason codes are
stable, programmer-friendly strings like `missing_token`, `invalid_audience`,
`connect_required`, `upstream_timeout`. They surface in both analytics and
structured logs so a single string lets you cross-reference both data sources.

## Drilling into a dimension

Clicking a value in any breakdown table scopes the entire dashboard to that
value. Clicking again toggles the filter off. Multiple drill-ins compose with
AND semantics — for example, clicking a user, then an upstream server, then a
capability type narrows the view to that combination.

Capability rows produce a multi-field drill (name + type + virtual server)
because capability names alone aren't unique across types and servers.

The available drill dimensions match the analytics event schema:

- `subjectId` (typed events only)
- `virtualServerName`
- `upstreamServerName`
- `capabilityName`
- `capabilityType` (tool, resource, prompt)
- `mcpMethod`
- `clientName`
- `upstreamAuthMode`
- `failureOrigin`

## Event taxonomy

The dashboard is built from a fixed set of event types organized into three
families. The family, the outcome class, and the metadata fields each event
carries drive the views.

### Families

- **`mcp_request`** — boundary events at the route. Examples:
  `mcp_request_accepted`, `mcp_request_rejected`.
- **`capability_invocation`** — per-capability events emitted by
  [`McpProxyHandler`](../code-config/mcp-proxy-handler.mdx). Examples:
  `mcp_capability_invoked`, `mcp_capability_completed`.
- **`auth_event`** — OAuth and upstream-auth lifecycle events. Examples:
  `mcp_auth_downstream_token_issued`, `mcp_auth_downstream_token_validated`,
  `mcp_auth_upstream_connection_established`, `mcp_auth_consent_approved`.

### Outcomes

Every event carries an `outcome` in one of seven classes:

- `success`
- `failure`
- `denied`
- `application_error`
- `connect_required`
- `partial`
- `cancelled`

Outcome class drives chart colors and the success-rate KPI. Failures break down
further by `failureOrigin` (gateway, upstream, client) for the failure-origin
chart and KPI.

### Common fields

Every event includes the route and identity fields the dashboards filter on:

- `operationId` (surfaced in analytics as `virtualServerName`)
- `upstreamServerId` (surfaced as `upstreamServerName`)
- `subjectId` (the authenticated user)
- `authProfileId` and `upstreamAuthMode`
- `httpMethod`, `transport`
- `latencyMs` (and the gateway/upstream split when both halves are measured)
- `reasonCode` and `errorType` on failure events

## Forwarding the data

The dashboard reads from the same analytics pipeline that backs the rest of
Zuplo. To forward the underlying data to your own provider, use the standard
Zuplo plugins:

- **Log plugins.** Every analytics event corresponds to a structured log entry.
  See [Logging](../../articles/logging.mdx) for the list of supported log
  destinations (Datadog, AWS CloudWatch, Google Cloud Logging, Splunk, Sumo
  Logic, New Relic, Loki, Dynatrace, VMware Log Insight). The accompanying
  [Logging](./logging.mdx) page in this section covers the MCP-specific log
  fields.
- **Metrics plugins.** See [Metrics plugins](../../articles/metrics-plugins.mdx)
  for the built-in metric exporters (Datadog, Dynatrace, New Relic,
  OpenTelemetry).
- **OpenTelemetry.** Configure the
  [OpenTelemetry](../../articles/opentelemetry.mdx) plugin to export traces and
  logs. The MCP Gateway publishes spans for the request, inbound policies, and
  the upstream fetch, plus structured log events for the analytics taxonomy
  above.

## Related

- [Logging](./logging.mdx) — the structured-log counterpart and OTel
  configuration.
- [`McpProxyHandler`](../code-config/mcp-proxy-handler.mdx) — the handler whose
  capability instrumentation drives the dashboard's top-capability views.
- [Logging](../../articles/logging.mdx) — list of supported log destinations and
  how to enable them.
- [Metrics plugins](../../articles/metrics-plugins.mdx) — supported metrics
  destinations.
