Explorer la qualité des outils MCP
Tout serveur MCP instrumenté avec le SDK d'analytique MCP de PostHog émet un événement
$mcp_tool_call dans la table partagée events chaque fois qu'un agent invoque un
outil. Il n'y a pas de table ClickHouse dédiée — chaque champ existe en tant que
propriété $mcp_* dans events, et chaque métrique de qualité d'outil (taux d'erreur,
percentiles de latence, portée) est une agrégation sur cet unique événement. Ce sont les
données derrière le tableau de bord d'analytique MCP et les écrans de qualité d'outils.
Pour un seul outil, préférez les outils typés — posthog:query-mcp-tool-stats
(appels, erreurs, p50/p95, utilisateurs, sessions, intentions),
posthog:query-mcp-tool-failures (messages d'erreur les plus fréquents par harness), et
posthog:query-mcp-tool-daily-stats (tendance jour par jour). Chacun prend un toolName
dateRange, lance le même moteur de requête que l'UI de détail d'outil, et est protégé par le flagmcp-analytics— aucun SQL écrit à la main nécessaire.
HogQL via posthog:execute-sql est la voie pour les questions cross-outil — le
classement « quel outil en erreur le plus » ci-dessous n'a pas d'outil typé, donc classez
avec SQL, puis explorez l'outil le plus défaillant avec posthog:query-mcp-tool-stats et
posthog:query-mcp-tool-failures. Le schéma complet de propriétés et les recettes de
requête canoniques vivent dans la référence de données MCP partagée :
products/posthog_ai/skills/querying-posthog-data/references/models-mcp.md.
Cette référence est la source unique de vérité pour le schéma $mcp_* et l'idiome
effective-tool-name utilisé ci-dessous — cette skill n'insère que la requête phare
« quel outil en erreur le plus » pour la commodité ; tirez la matrice, la latence, et les
recettes de harness de la référence plutôt que de les re-dériver. Lisez-la avant
d'écrire des requêtes.
Les deux règles qui comptent le plus
-
Utilisez toujours le nom d'outil effectif. Les événements du nouveau SDK enveloppent l'outil réel dans un appel single-exec, donc grouper sur
$mcp_tool_namebrut les regroupe tous sous le wrapper. Utilisez :coalesce(nullIf(toString(properties.$mcp_exec_tool_call_name), ''), toString(properties.$mcp_tool_name)) -
Lisez toujours
$mcp_is_errorviatoBool(...)et castez$mcp_duration_msviatoFloat(...). Les propriétés sont des chaînes.
Fixez toujours une plage horaire — ces requêtes scannent events sinon.
Workflow : quel outil a le taux d'erreur le plus élevé
C'est la question canonique « quel outil en erreur le plus ». Classez les outils par taux
d'erreur, mais gardez-vous contre le bruit d'échantillon réduit avec un plancher HAVING
sur le volume d'appels :
posthog:execute-sql
SELECT
coalesce(nullIf(toString(properties.$mcp_exec_tool_call_name), ''), toString(properties.$mcp_tool_name)) AS tool,
count() AS total_calls,
countIf(toBool(properties.$mcp_is_error)) AS errors,
round(countIf(toBool(properties.$mcp_is_error)) * 100.0 / count(), 1) AS error_rate_pct
FROM events
WHERE event = '$mcp_tool_call'
AND coalesce(nullIf(toString(properties.$mcp_exec_tool_call_name), ''), toString(properties.$mcp_tool_name)) != ''
AND timestamp >= now() - INTERVAL 30 DAY
GROUP BY tool
HAVING total_calls >= 20
ORDER BY error_rate_pct DESC, total_calls DESC
LIMIT 20
Rapportez à la fois le taux et le volume — un taux d'erreur de 100 % sur 3 appels
raconte rarement l'histoire réelle ; un taux de 12 % sur 50 000 appels oui. Proposez de
récupérer les valeurs $mcp_error_message les plus fréquentes pour l'outil le plus
défaillant (voir ci-dessous).
Workflow : matrice de qualité d'outil
Une ligne par outil avec taux d'erreur, percentiles de latence, et portée — reflète l'écran de qualité d'outil. La requête prête à l'exécution est dans models-mcp.md sous « Tool-quality matrix ».
Workflow : pourquoi un outil échoue
Pour les buckets de défaillance les plus importants d'un outil (groupés par harness),
appelez posthog:query-mcp-tool-failures avec le toolName — c'est l'équivalent typé de la
requête ci-dessous. Les défaillances proviennent de la même source que le taux d'erreur :
les événements $mcp_tool_call en erreur ($mcp_is_error), limités au nom d'outil effectif.
Les défaillances sont groupées par $mcp_error_type (un bucket sémantique : internal,
validation, api_4xx, api_5xx, permission, timeout, rate_limited,
missing_context) et le statut HTTP $mcp_error_status s'il est présent. Pour voir les
appels en erreur individuels dans un bucket — avec le $mcp_error_message capturé, l'id
de session, le harness, et l'intention — passez le error_type/error_status brut du
bucket à posthog:query-mcp-tool-failure-occurrences (le $mcp_error_message est vide sur
les événements capturés avant l'envoi de la capture de messages) :
posthog:execute-sql
SELECT
concat(
coalesce(nullIf(toString(properties.$mcp_error_type), ''), 'unknown'),
if(empty(coalesce(toString(properties.$mcp_error_status), '')), '',
concat(' (HTTP ', coalesce(toString(properties.$mcp_error_status), ''), ')'))
) AS failure,
count() AS n
FROM events
WHERE event = '$mcp_tool_call'
AND toBool(properties.$mcp_is_error)
AND coalesce(nullIf(toString(properties.$mcp_exec_tool_call_name), ''), toString(properties.$mcp_tool_name)) = '<tool>'
AND timestamp >= now() - INTERVAL 30 DAY
GROUP BY failure ORDER BY n DESC LIMIT 10
$mcp_error_type n'est rempli que sur les chemins SDK/serveur plus récents — une partie
des appels en erreur ne portent ni type ni statut et tombent dans le bucket unknown.
Workflow : outils les plus lents
Échangez l'agrégat pour les percentiles de latence
(quantile(0.95)(toFloat(properties.$mcp_duration_ms))) et triez par p95_ms.
La requête matrice retourne déjà p50_ms / p95_ms.
Construction de liens UI
- Tableau de bord :
https://app.posthog.com/project/<project_id>/mcp-analytics/dashboard - Qualité d'outil :
https://app.posthog.com/project/<project_id>/mcp-analytics/tool-quality
Surfacez toujours un lien UI pour que l'utilisateur puisse vérifier visuellement.
Conseils
- Rapportez le taux d'erreur et le volume d'appels ensemble ; un plancher
HAVING total_calls >= Nempêche les outils avec très peu d'appels de figurer spurieusement en haut de la liste - Excluez les appels en erreur des percentiles de latence seulement si demandé — les appels défaillants sont souvent les lents, et les rejeter cache le problème
$mcp_client_namevous permet de découper la qualité par harness (Claude Code vs Cursor vs …) ; le bucketing canoniquemultiIfest dans models-mcp.md- Le bucketing de harness est résolu côté serveur par
products/mcp_analytics/backend/mcp_harness.py— c'est la source de vérité, etposthog:query-mcp-harness-breakdownl'exécute. Si votre SQL écrit à la main diverge de l'écran, votre bucketing a dérivé demcp_harness.py; préférez l'outil typé au re-dérivage
Skills connexes
exploring-mcp-sessions— explorez une unique exécution d'agent et sa séquence d'outilsexploring-mcp-intent-clusters— groupez les objectifs des agents et voyez quelles intentions pilotent les erreurs