MCP audit log
Record who called which tool, when and with what outcome - one event per agent request.
When an AI agent calls an MCP gateway, the audit log records what happened - who called which tool, when, with what outcome and how much data flowed. Payloads are never recorded, only their sizes are.
MCP is one source of the platform-wide audit log - storage, external databases and the dashboard views are shared with REST, IMAP and publish/subscribe, and are described on that page.
Event types
Each HTTP request an agent makes produces exactly one event, after the request is handled - both POST requests delivering JSON-RPC messages and the DELETE that terminates a session.
| Event type | When |
|---|---|
mcp-initialize | An initialize request started a conversation |
mcp-tools-list | A tools/list request listed the tools |
mcp-tools-call | A tools/call request invoked a tool |
mcp-prompts-list | A prompts/list request listed the gateway's prompts |
mcp-prompts-get | A prompts/get request read one prompt's instructions |
mcp-discover | A server/discover probe of the stateless protocol revision |
mcp-session-delete | An HTTP DELETE terminated a session |
auth-failed | A request was refused because its credentials did not authenticate |
rate-limited | A request was refused with a 429 because the rate limit of its security definition was reached |
A method outside this set, e.g. ping, is recorded under its literal name, and a request whose body could not be parsed is recorded as unknown.
The columns
The events live in the same event table as every other source. This is how MCP fills it:
| Column | Content |
|---|---|
source | Always mcp |
event_type | One of the types above |
object_name | The gateway's name |
cid | The correlation ID of the request, the same one that appears in server logs |
endpoint | The tool or prompt name - only mcp-tools-call and mcp-prompts-get events have one, it is empty otherwise |
ext_client_id | The caller - the name of the security definition the agent authenticated with, or, for a bearer definition with an identity claim, that name, a slash and the person's claim value, e.g. mcp.billing.agents/maria.johnson@example.com |
sub_key | The session ID the request included or created, empty when there was none |
size | The size of the response, in bytes |
outcome | ok, or error when the HTTP status was not 2xx, the JSON-RPC response contained an error object, or a tool result reported isError |
data | A JSON document with the fields below - never the payload itself |
The data document holds remote_address, method (the literal JSON-RPC method), duration_ms (how long handling took) and request_size in bytes. Events with an error outcome additionally record the JSON-RPC error_code and error_message the agent received. When response controls shaped a tools/call response, the document also lists the trace of what shaping did - PII counts, compaction counts, token cuts and the agent filter - one key per finding, with nothing written for stages that did nothing.
In the dashboard, the MCP audit page shows these as Time, CID, Event, Tool, Caller, Outcome, Size and a data preview, with the Identity, Client and Reason columns described below.
The caller and the auth block
When the caller presented a bearer token, the data document also includes an auth block with what the token said, the same fixed keys in every event and never the token itself:
| Key | Content |
|---|---|
type | bearer_jwt for a JWT, bearer_static for a static token, none when no bearer token was presented |
definition | The name of the bearer token definition that matched, or was expected to |
identity | The value of the definition's identity claim, e.g. maria.johnson@example.com, empty without one |
issuer, audience | The token's iss and aud claims |
client | The OAuth client the person signed in through, from the token's azp or client_id claim - which AI product it was |
scopes | The scopes the token was granted |
token_id, expires_at | The token's jti and exp claims |
claims_matched | The name=value entries of the definition the token satisfied |
reason | On auth-failed events, why the token was refused - one of no_credentials, malformed, unsupported_algorithm, unknown_key, expired, wrong_issuer, wrong_audience, bad_signature, claim_missing, claim_mismatch and no_definition_matched |
claim | On auth-failed events with a claim_missing or claim_mismatch reason, the name of the claim |
identity, client and reason are also attributes of the event, so the MCP audit page shows them as the Identity, Client and Reason columns and the free-text search finds events by a person's name, by the client they used and by the reason they were refused. A refused token that could be read, an expired one or one from a person outside the group the definition lists, leaves the person and the client in the record, a token that could not be read leaves neither.
When the audit log is exported with OpenTelemetry, each MCP event is one log record and nothing of the above is lost. The columns become zato.audit.object_name, zato.audit.endpoint, zato.audit.ext_client_id, zato.audit.sub_key, zato.audit.size and zato.audit.outcome, the three attributes become zato.audit.attr.identity, zato.audit.attr.client and zato.audit.attr.reason, and the data document is flattened with a dot, so method is zato.audit.data.method, duration_ms is zato.audit.data.duration_ms and every key of the auth block is zato.audit.data.auth.<key>, e.g. zato.audit.data.auth.identity and zato.audit.data.auth.scopes. Keys that are empty in the event, such as identity for a token that could not be read, are left out of the record rather than sent as empty strings.
Enable and disable the log
Each gateway has its own Record each request in the audit log checkbox, in the Gateway options micro-form under More options on the wizard's step 02, What do they receive? - on by default for new gateways, and taking effect immediately when saved. The gateway list has an Audit log link in each row that opens that gateway's events.
In enmasse, the toggle is the is_audit_log_active attribute of an mcp_gateway entry.
Retention and storage
Events are kept for 30 days and deleted automatically past that window. Storage is the shared audit database - SQLite by default, or MySQL, PostgreSQL and Oracle DB - configured through the environment variables listed on the audit log page.
See also
| Feature | What it does |
|---|---|
| Platform audit log | Storage, external databases and the shared dashboard views |
| Security | The identities the caller column records |
| Response controls | The shaping whose trace appears in each event's data |
| Alerts | The alerts counted from these events - failing calls, invalid calls, looping agents, response volume |