Analytics — Step-by-Step Setup
Add observability to every WebMCP tool in 4 steps. One webmcp.configure covers all tools — swap the provider SDK inside the hooks.
Prefer a provider recipe? Jump to PostHog, Sentry, or GA4. This page is the generic checklist.
For hook lifecycle (before → validate → fn → after → error/denied), see Guide — Hooks. For API types, see Reference — Hooks.
Step 1 — Pick your provider
| Provider | Best for | Hook events |
|---|---|---|
| PostHog | Product analytics, session replay | webmcp.invoked / succeeded / failed / denied |
| Sentry | Errors + performance spans | captureException + startInactiveSpan |
| GA4 | Marketing, gtag events | webmcp_invoked / succeeded / error / denied |
All use the same shape — choose one or combine.
External docs:
Step 2 — Configure hooks once (global)
Add one webmcp.configure in your app entry (e.g. main.tsx or app/layout.tsx):
import { webmcp } from 'simple-webmcp';
webmcp.configure({
hooks: {
before: [({tool, input, invocationId, metadata})=>{
metadata.start = performance.now();
// send "invoked" to your provider
console.log('[hook:before]', tool.tool.name, invocationId, input);
}],
after: [({tool, invocationId, output, metadata})=>{
const duration = Math.round(performance.now() - (metadata.start as number));
console.log('[hook:after]', tool.tool.name, invocationId, duration + 'ms', output);
}],
error: [({tool, error, invocationId})=>{
console.warn('[hook:error]', tool.tool.name, invocationId, error);
}],
denied: [({tool, reason, code, invocationId})=>{
console.warn('[hook:denied]', tool.tool.name, invocationId, reason, code);
}],
}
});Hooks wrap only the agent execute path — tool({input}) stays pure. metadata is a shared bag for one invocation (before sets start, after reads it). invocationId is crypto.randomUUID() or fallback.
To scope by tenant/route, use <WebMCPProvider> instead — see React guide.
Step 3 — Verify in the demo
Run docs locally:
bashnpm run docs:dev # open /demo/Open the Hooks & HITL card in the demo. Toggle Require approval for checkout on/off.
Use Inspect → Invoke checkout → watch the hook log turn green (success) or yellow (denied). Open DevTools Console →
[webmcp:hook]lines.Check your provider dashboard (PostHog Activity, Sentry Issues, GA4 DebugView) — events should appear with
tool,invocationId,duration.
If no events: ensure webmcp.configure runs before tool.register() / useWebMCP mount, and that the provider SDK is initialized.
Step 4 — Production checklist
- PII redaction: Redact
input/outputbefore sending. Use anafterhook to stripemail/token. See pattern in Hooks — After. - Sampling: For high volume, wrap hooks with
if (Math.random() > 0.1) returnor provider sampling. - Tenant / route: Use
WebMCPProviderto enrichinputwithtenantId— see React — WebMCPProvider. - Durations: Set
metadata.startinbefore, compute inafter(noterror/denied). - Deny vs error: Track
denied(human said no) separately fromerror(operational failure).deniedrate = HITL friction;errorrate = reliability. - Testing: In
vitest, callresetGlobalHooks()andregistry.clear()between tests — see Reference — Hooks for the singleton.
Next
Pick a provider recipe:
- PostHog — step-by-step —
posthog.capturewith durations - Sentry — step-by-step —
captureException+ spans - GA4 — step-by-step —
gtag('event', …)
Or return to Analytics Overview.
See also
- Guide — Hooks — ordering
global→scoped→tool/tool→scoped→global - Reference — Hooks —
BeforeContext,AfterContext, etc. - Demo — live hook log + Inspect invoke
- External: Chrome WebMCP API