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 EventMiddleware appends exactly two values per call:

  • the tool name – validated against the registered providers ( ToolRegistry::toolNames()); events for unknown names are not stored.
  • 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:

  1. the agent's optional client argument, if it sets one (the runtime adds a client property to every tool's input schema automatically);
  2. otherwise a coarse match against known agent markers in the User-Agent (e.g. Claude, ChatGPT, GeminiBot);
  3. 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:setup:

tx_neoblackwebmcp_event
uid     int          primary key
crdate  int          unix timestamp of the call
tool    varchar(64)  registered tool name
client  varchar(64)  sanitised client hint
Copied!

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;
Copied!

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 analyticsEnabled is off the endpoint is inert and the request is passed through untouched.
  • Same-origin guard: requests whose Sec-Fetch-Site header is present and neither same-origin nor same-site are rejected with 204.
  • Rate limited: at most analyticsRateLimit calls per client IP per minute (default 60; 0 disables). Excess calls receive 429. 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 backend module showing calls per tool and a timeline

The WebMCP dashboard: calls per tool/client, and a per-day timeline.

The WebMCP backend module showing also the recent calls in a table

The WebMCP dashboard: The most recent events.