The package sits beside your traffic, not in it
MCPulse is not a proxy. It is an npm package inside your own process. This matters twice over. Directory-listed MCP servers cannot change their URL, and OAuth breaks if traffic is redirected — so a proxy would be unusable for exactly the servers most worth measuring. And because the package sits beside the traffic rather than in it, if MCPulse is down, your server keeps working. A failed flush costs a data point. It must never cost a tool call.What never leaves your process
The rule is one sentence and it cannot be un-broken: sizes and hashes only, never arguments, never results.args_hash is twelve characters of a SHA-256 over the arguments with keys sorted. It exists for one purpose: telling whether two calls within 30 seconds used the same arguments, which is what separates a retry from ordinary pagination. It is deliberately too short to be brute-forced back into anything meaningful, and it is not reversible.
There is no option that turns any of this off, in either direction. You cannot configure the SDK to send more, because a guarantee you can switch off is not a guarantee.
The three rules the package holds to
- Never throw. Every entry point is wrapped in a
try/catchthat swallows. If instrumentation cannot be attached, your server is handed back untouched and runs without analytics. - Never block. Record, buffer, return. Nothing awaits the network on the path a model is waiting on. Ingest replies
202before the write happens for the same reason. - Never store customer data. The table above.
Account isolation
Every request is scoped to the account derived from the credential:- An ingest key resolves to exactly one MCP. Telemetry cannot be posted into another account’s MCP by any value in the body, because no value in the body is read for that purpose.
- A session token resolves to one account and one role. Requesting an MCP outside that account returns
404, not403, so ids outside your account are not even confirmed to exist.
account_id directly and it is derived by a database trigger from the row’s own mcp_id — never taken from the caller. A row inserted claiming someone else’s account is corrected before it lands.
API key handling
- Generated with 32 characters of cryptographic randomness, prefixed
mp_live_. - Only a SHA-256 hash and the first 12 characters are stored. The raw key is returned once, at creation, and is unrecoverable afterwards.
- Scoped to one MCP, named at creation, and revocable at any time from Installation or Keys.
- Revoking clears the in-memory resolution cache immediately, so a revoked key stops working now rather than within five minutes.
Roles
Three roles, account-wide. Reads are open to everyone in the account — an analytics product nobody on the team can read is not doing its job. Only writing needs rank.
Every one of these is enforced in the API, not in the interface. Hiding a button is a courtesy; the guards are the enforcement, and anything talking to the API directly — including the MCP server — gets no such courtesy. The last owner cannot be demoted or removed, because an account with no owner cannot be administered by anyone.
See Roles and permissions.
MCP access runs the same guards
The MCP endpoint registers 24 tools, and 10 of them write — 7 that change something and 3 that remove it. That is not a second permission surface: every one calls the same service function the REST route calls and hits the same guard, so a member is refused over MCP exactly as they are over HTTP. Two writes deliberately do not exist. There is nocreate_key, because the full key would land in a model’s context and from there in transcripts and provider logs. There is no delete_account, because a typed-name confirmation proves nothing when the model already read the name a moment earlier. See MCP tools.
Retention and deletion
Deletion is the database’s job. Every foreign key cascades:- Deleting one MCP removes its keys, its calls, its hourly counters, its sessions and its tool pairs. Its siblings are untouched.
- Deleting the account removes every MCP in it and everything underneath, plus every teammate’s access, in a single statement.
calls exist so the nightly pass can walk them and so the live feed has something to show; every other figure comes from tool_hours, which stays small and aggregates correctly across any range. A cleanup of calls by your plan’s retention — 7, 90 or 365 days — is built and deliberately not switched on yet.
Rate limiting
Ingest is limited to 10,000 payloads per minute per key, counted in payloads rather than requests — a batch of 500 costs 500. Over the limit returns429 with Retry-After. See Rate limits.