Skip to main content

MCP Call Evidence

MCP Inventory answers what exists — which MCP servers your agents can reach and which credential is bound to each. MCP Call Evidence answers what happened: every tool call made through one, and every OAuth grant action behind it, written to the same tamper-evident audit chain as your moderation history.

Before this release, an MCP tool call left a line in a service log and nothing else. There was no record you could show anyone of which agent used which credential against which server, whether the call was allowed or refused, and what the far end said. A log line can be edited, rotated away, or simply lost; an audit row in the chain cannot be changed without the chain reporting it.

Note: This release ships MCP Call Evidence as data — it is recorded in the audit and drives the findings below, and there is no dedicated screen for it yet, which is why this page carries no screenshot. The console view arrives with the MCP Inventory console.


What gets recorded​

One row per tool call, for every connection — not only the ones bound to an agent's identity. A connection scoped to a tenant or to a person is precisely the case where an agent acts with a human's credential, which is the thing most worth having a record of.

A refusal is recorded as fully as a success. An audit holding only the calls that went through describes a system in which nothing is ever refused.

RecordedWhat it tells you
Server and toolWhich MCP server, and which tool by name.
Agent identity, user, connectionWho the call ran as, and which binding it used.
Authentication methodStatic credential, Hub-held OAuth token, or caller identity.
Credential fingerprintThe same one-way digest MCP Inventory shows, so a row can be lined up against the inventory without either holding the secret.
Decision and codeforwarded, deny, credential_unavailable, oauth_error, upstream_error — each with a stable code such as tool_authz or token_wrong_server.
Downstream statusWhat the MCP server actually answered, including a 401 or 403.
Latency and trace idHow long the call took, and the identifier that ties it to the agent run.

One row per OAuth grant action — issued, refreshed, stepped up, denied, disconnected, and a client registered against a new authorization server — each with the actor and the scopes involved. A grant that quietly gained scope, or one revoked upstream, is visible as an event rather than inferred from a credential that stopped working.

What is never recorded​

  • No credential, ever. Only the fingerprint. Nothing that could be replayed reaches Beak AI Security.
  • No tool arguments. They are the caller's unscanned input and can contain anything the user typed. Tool names are recorded; their arguments are not.
  • No caller token. Where a call runs as a person, the record names the person; the token itself never leaves Beak AI Hub.

Following one call end to end​

Beak AI Agent Runtime opens a span for each MCP tool call and sends its trace id with the request. Beak AI Hub records that id on the audit row, and the MCP server records it on its own per-call log line. One identifier therefore appears in three places:

  • the agent run in Beak AI Observability, where you can see what the agent was doing;
  • the audit row, which says which credential was used and whether the call was allowed;
  • the MCP server's log, which says whether the call arrived carrying a person's identity.

That last point is the one worth knowing about. A first-party MCP server can be configured to act as the calling person rather than as a shared service account. Its per-call line records whether a given call did so, which makes the rollout of that behaviour observable while it happens instead of reconstructable afterwards.

A call made by something other than an agent run — a direct client with its own API key — carries no trace id. That is not a gap in the record: it is how you tell the two apart.


Findings​

Two findings are raised from the evidence, alongside the inventory findings.

FindingSeverityWhat it means
A credential the server keeps refusingHighFive or more calls on one connection were refused with 401 or 403 in the last 24 hours, and at least half of that connection's calls failed. The credential has been revoked, has expired, or was never granted the access the agent is asking for. Until it is fixed, every agent depending on that connection is silently failing.
A server with no call evidenceLowThe server is registered and reachable, an agent can select it, but no call has ever been recorded through it. Access is granted and a secret is stored for something nothing uses. Suppressed while the finding above is open for the same server — a storm of refusals explains the silence.

Best Practices​

  • Treat a refusal storm as a credential incident, not a performance problem. A run of 401s is a credential that stopped being valid; retries will not fix it and will hide when it started.
  • Check the trace id before the timestamp. Two calls a second apart are hard to tell from each other; the trace id names one agent run exactly.
  • Verify the audit chain after any database maintenance. The chain is what makes these rows evidence rather than logs, and it can only tell you it is intact if you ask it.
  • Review OAuth grant events when an integration changes hands. A grant reissued to a different account looks identical to a routine refresh from the credential alone; the event carries the actor.
  • Investigate a server with no evidence rather than deleting it. It may be unused, or it may be reached by something that does not go through the gateway at all — which is the more interesting answer.