Warning
Experimental. This extension is experimental and not yet ready for production use. It is built on top of WebMCP, which is itself an experimental, early-stage proposal. Both the underlying specification and this extension's API may change or break at any time without notice. Use at your own risk.
Analytics
The extension ships an optional, first-party usage log: one anonymous row per tool call, visualised in a backend module. It is enabled by default and can be switched off entirely (see Configuration).
What is recorded
Every tool call fires a small same-origin beacon
(navigator.sendBeacon, with a fetch fallback) to the ingest endpoint.
The
Event appends exactly two values per call:
- the tool name – validated against the registered providers
(
Tool); events for unknown names are not stored.Registry:: tool Names () - a client hint – a short, self-reported or coarsely detected label of the calling agent.
Nothing else is stored: no free text (search queries, e-mail contents, names), no cookies, no IP address, no user agent string.
The client hint
The hint is best-effort and resolved client-side in this order:
- the agent's optional
clientargument, if it sets one (the runtime adds aclientproperty to every tool's input schema automatically); - otherwise a coarse match against known agent markers in the User-Agent
(e.g.
Claude,ChatGPT,GeminiBot); - otherwise the literal
unbekannt("unknown").
Server-side the value is sanitised (letters, digits, space and ._-/() only)
and capped at 64 characters before it is stored.
Data model
Events live in a single append-only table, created by
extension::
uid int primary key
crdate int unix timestamp of the call
tool varchar(64) registered tool name
client varchar(64) sanitised client hint
There is no pid, no relation to a user or session, and no additional
payload column — the schema itself makes it impossible to store PII.
Retention and deletion
The table is append-only; the extension does not prune it automatically. Because a row is fully anonymous, there is no per-subject deletion to perform, but you remain free to trim or clear the log at any time, for example:
-- drop everything older than 90 days
DELETE FROM tx_neoblackwebmcp_event WHERE crdate < UNIX_TIMESTAMP() - 90*86400;
-- clear the log completely
TRUNCATE tx_neoblackwebmcp_event;
If you schedule this, a simple periodic DELETE on crdate is enough; the
crdate column is indexed.
The ingest endpoint
POST /webmcp-event is public by design (agents call it without a backend
session). It is protected by several deliberate constraints:
- Feature-gated: when
analyticsEnabledis off the endpoint is inert and the request is passed through untouched. - Same-origin guard: requests whose
Sec-Fetch-Siteheader is present and neithersame-originnorsame-siteare rejected with204. - Rate limited: at most
analyticsRateLimitcalls per client IP per minute (default 60;0disables). Excess calls receive429. The limiter stores only a hashed IP + time-window counter that expires after two windows — the plaintext IP is never persisted. - Whitelisted: only registered tool names are logged; anything else is handed down the middleware stack.
Backend module
When analytics is enabled, the System > WebMCP module shows calls per tool and per client, a per-day timeline and the most recent events. The timeframe (7 / 30 / 90 days) and tool/client filters are selectable; the accepted tool names are derived automatically from the registered providers.
The module is not page-related: it has no page tree and shows site-wide
figures, mirroring the event table which has no pid. It lives in the
System menu; there is nothing to pick in a tree.
The WebMCP dashboard: calls per tool/client, and a per-day timeline.
The WebMCP dashboard: The most recent events.