Skip to main content

MCP usage telemetry

repowise mcp-log controls RepoWise's pseudonymous MCP usage telemetry — a lightweight, per-hour "heartbeat" the listener sends so we can see whether the MCP server is being used, how much, and whether it is healthy.

The heartbeat is on by default and carries counts only — no source code, no file paths, no query content, no arguments. It is pseudonymous, not anonymous: it is tied to your authenticated session and is attributable to your account via a server-derived identifier (see What is never sent below). Because it is personal data, it is included in your GDPR data export and is erased when you delete your account. You can opt out of future heartbeats at any time with repowise mcp-log off.

Verbs

repowise mcp-log on              # opt back in to the usage heartbeat
repowise mcp-log off # opt out — disables the heartbeat
repowise mcp-log status # show current opt-in state + endpoint

What the heartbeat contains

Once per hour, for each active tenant, the listener POSTs a small JSON document of aggregate counters (no per-call detail):

{
"listenerVersion": "0.1.0",
"windowStartsAt": "2026-06-29T10:00:00.000Z",
"toolCounts": { "find_symbol": 42, "get_impact": 7 },
"statusCounts": { "ok": 46, "error": 2, "timeout": 1, "rejected": 0 },
"missCounts": { "find_symbol": 3 },
"healthCounters": { "graphNotLoaded": 0, "unknownRepo": 0,
"lspDisabled": 0, "lspUnavailable": 1,
"connectFail": 0, "preAuthFail": 0 }
}
  • toolCounts — how many times each MCP tool was invoked.
  • statusCounts — outcome tallies: ok / error / timeout / rejected.
  • missCounts — per-tool "coverage miss" tallies (a query that returned an empty result, e.g. a symbol we couldn't find). These drive graph + documentation coverage improvements.
  • healthCounters — "broken MCP" signals: graph not loaded, unknown repo, LSP disabled, LSP unavailable (language server not installed/unsupported), connect failures, pre-auth failures.
  • listenerVersion — the listener CLI version, for fleet version-spread telemetry.

What is never sent: file contents, file paths, symbol names, query strings, arguments, response bodies, or any AI-generated text. The payload is counts and version only. No identity fields ride the wire. Instead, both your tenantId and — when the per-user dimension is enabled — an opaque per-seat identifier (your Cognito sub) are derived server-side from your authenticated session and stamped onto the stored counts. That server-derived sub is a pseudonym: it maps back to your account (which is why these counts are treated as pseudonymous personal data, exportable and erasable), but your email and name are never stored on the heartbeat row itself.

The heartbeat rides RepoWise's Service Telemetry basis (Terms of Service §V.0(b) / Privacy Policy §I.3) — the same basis used by our other operational metrics. The pseudonymous, server-derived tenantId (and, when enabled, per-seat sub) is retained for approximately 24 months (Privacy Policy §XI), then aged out automatically.

Because the heartbeat is pseudonymous personal data rather than anonymous data, it is:

  • Included in your GDPR Art. 15 data export — the ops compliance export emits an mcpUsageHeartbeat section covering the full 24-month retention window for your tenant.
  • Erased on account deletion (GDPR Art. 17) — when you request deletion, every heartbeat row scoped to your tenant is deleted on a best-effort basis alongside the S3 context purge. The immortal consent audit row (MCP_LOG_CONSENT#) is deliberately not touched — it is the Art. 7(1) proof-of-consent trail and is retained regardless.

Opting out

repowise mcp-log off     # stop sending the heartbeat
repowise mcp-log on # start again

off writes enabled: false to a local flag at ~/.repowise/mcp-log.flag. The listener re-reads this flag on every tick, so opting out takes effect at the next heartbeat without restarting the listener — no further heartbeats are sent. Opting out is a local control; it does not delete previously collected aggregate counters, and the server-side consent audit row is preserved (GDPR Art. 7(1)).

Operators can additionally disable the heartbeat fleet-wide with the REPOWISE_MCP_HEARTBEAT_DISABLED (listener) and REPOWISE_MCP_HEARTBEAT_TELEMETRY_DISABLED (server) kill-switches.

Raw per-call logging is disabled

RepoWise previously shipped an experimental raw per-call query log (one encrypted JSONL line per MCP call, including the query arguments). That pipeline is currently disabled — the listener no longer collects it by default and it is never uploaded. It required redaction and consent work that has not landed, so it is inert pending that effort. The pseudonymous heartbeat above is the only active MCP telemetry.

The typed-resolution sidecar (separate upload)

Distinct from telemetry: to power typed code intelligence (accurate go-to-definition, call hierarchies, type-aware impact), the listener runs language servers locally and uploads a structural sidecar for the repositories you analyze. This sidecar contains structural code metadata — file paths, symbol and method names, and call-site coordinates (line/column) — so the server can resolve references precisely. It is not MCP usage telemetry and is not controlled by repowise mcp-log; it is part of analyzing your repository. It does not include file contents. See your plan's data-handling terms for details.