Guide

How to Get Audit Logs of Every MCP Tool Call Into Your SIEM

Agents write logs on laptops. MCP servers see tokens, and not people. Only a gateway can make one record for each tool call with the person behind it. This guide shows what a record must contain. It also shows how to stream the records to Splunk, Falcon LogScale, Elastic or Sentinel, and what the delivery guarantees are.

· Erik Jonsson Thorén, Founder, Gatana

Short answer: Route the agents through a gateway that records every tool call with the person, the agent, the server, the tool and the outcome. Stream the records to the SIEM over HTTPS. In Gatana, set the audit level, then configure one destination under Settings, SIEM Streaming. Events arrive as HMAC-signed NDJSON batches within about one minute.

Why agents and servers cannot give you this

Agents write their logs on laptops, one person at a time, each in its own format. An upstream MCP server sees a token, or a shared API key. It does not see the person. Ten servers give ten log formats. None of them names the agent.

One point sees every call with the person, the agent, the server and the tool: the gateway. The audit trail must come from there.

What one record must contain

A record that a security team can use names these fields:

  • the event, for example a tool call, a sign-in or a configuration change
  • the time, in UTC
  • the person, and the agent or token that acted for the person
  • the server and the tool
  • the outcome, including calls that a rule blocked
  • the arguments, or a redacted form of them, when the policy requires it

Gatana sends each event as one JSON object on its own line:

{
  "id": "audit_logs:184223",
  "version": 1,
  "time": "2026-08-04T09:52:04.118Z",
  "tenant": "acme",
  "source": "audit_logs",
  "action": "mcp.tools/call",
  "actor": { "type": "user", "id": "usr_8Fq2..." },
  "entity": { "type": "mcp_server", "id": "srvr_pQ1..." },
  "details": {}
}
Field Content
id Stable and unique for the same event. Use it to deduplicate
time When the event happened, ISO 8601 UTC
source audit_logs or audit_logs_credentials
action A dotted name: mcp.tools/call, user.login_success, firewall.deny, credential.update
actor The user, or system for background work
entity What the event is about
details The event-specific payload

The event catalog lists every action. Most follow {entity type}.{event name}. Write rules against the prefix where you can.

How much a tool call records

The MCP audit log level in the organization settings decides the detail:

Level What a tool call records
off Nothing
terse (default) The server, the tool, the duration, and who called it
detailed Adds the call arguments
detailed-with-error Adds the response of failed calls
verbose Adds the response of every call

Sign-ins and configuration changes are always recorded. A details payload over 64 KB is truncated to a preview. Secret values are replaced with [REDACTED] at every level and at any depth.

The steps in Gatana

  1. Open the organization settings and set the MCP audit log level. Start with detailed if your policy needs arguments.
  2. Open Settings, then SIEM Streaming. One destination exists for each organization. The feature is part of the paid plans.
  3. Enter the HTTPS endpoint of your collector. In Gatana Cloud, the address must be public. A self-hosted installation can stream to a private address.
  4. Enter the optional authentication header that the collector expects.
  5. Select the sources: audit_logs, audit_logs_credentials, or both.
  6. Save the signing secret. It is shown one time and can be revealed again in the dashboard.
  7. Click Send test event. A gatana.test event is delivered. The dialog shows the HTTP status and the start of the response.

Receiver setup

Collector Endpoint Authentication header
Splunk HTTP Event Collector https://<host>:8088/services/collector/raw Authorization: Splunk <hec-token>
CrowdStrike Falcon LogScale https://<host>/api/v1/ingest/hec/raw Authorization: Bearer <ingest-token>
Elastic An HTTP input on your ingest pipeline; split lines, parse each as JSON Authorization: ApiKey <key>
Microsoft Sentinel A relay that accepts the POST and forwards to the Logs Ingestion API As the relay requires
Anything else Any endpoint that accepts an authenticated HTTPS POST of newline-delimited JSON As the collector requires

For Splunk, set sourcetype on the token or its input.

Verify the signature

Every request carries a signature over the exact body:

X-Gatana-Signature: t=1785825392,v1=6c3b...f19a

t is a Unix timestamp in seconds. v1 is HMAC-SHA256 of "{t}.{raw body}", keyed with the signing secret. Verify against the raw body before any JSON parsing. Reject a request whose timestamp is outside your tolerance.

import { createHmac, timingSafeEqual } from 'node:crypto';

function verify(rawBody, header, secret, toleranceSeconds = 300) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const age = Math.abs(Math.floor(Date.now() / 1000) - Number(parts.t));
  if (!Number.isFinite(age) || age > toleranceSeconds) return false;
  const expected = createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
  const a = Buffer.from(expected, 'hex');
  const b = Buffer.from(parts.v1 ?? '', 'hex');
  return a.length === b.length && timingSafeEqual(a, b);
}

A secret rotation takes effect immediately. Update the receiver first, or accept a short gap. If the receiver can examine two secrets, add the new one before you rotate.

Delivery guarantees

Property Value
Batch size Up to 500 events or about 1 MB, as application/x-ndjson
Frequency One time each minute. Expect an event within about one minute of the action
Timeout 10 seconds. Redirects are not followed
Semantics At least once. Deduplicate on id
Order Events from each source arrive in order
Retries After 1, 5, 15 and then 60 minutes
After 1 hour of failures The destination is marked failing in the dashboard
After 24 hours Administrators receive one email
After 7 days Delivery is disabled and a second email is sent
Recovery The read position is kept. Reactivation continues from where delivery stopped, as far back as audit retention permits

Rules worth writing first

  • firewall.deny: a tool call that a rule blocked. Alert on a burst from one actor.
  • siem_destination.*: a change to the streaming configuration itself. Alert on every one.
  • credential.auto_oauth_refresh_failed and credential.expired_no_refresh: a connection about to break.
  • user.created and user.disabled: compare with the identity provider.
  • mcp.tools/call volume per actor: a baseline, then a threshold.
  • tenant_configuration.update: a change to organization settings, including the audit level.

What is never sent

  • Secret values: tokens, passwords, client secrets, private keys and API keys are replaced with [REDACTED].
  • Encrypted secret columns: a change is reported as {"changed": true} and never decrypted.
  • Internal events visible only to Gatana staff, such as billing traffic.

The SIEM streaming page in the documentation has the full reference, including a Python verifier.

FAQ

Questions, answered.

What does each audit record contain?

Each record names the event, the time, the organization, the actor and the entity. For a tool call, it names the server, the tool, the duration and the credential that the call came through. At the detailed level, it adds the arguments. At the verbose level, it adds the response. Sign-ins and configuration changes are always recorded.

How fast do events arrive in the SIEM?

Within about one minute. The exporter runs one time each minute. It holds events back for a few seconds so that it skips none. Batches contain up to 500 events or about one megabyte. The destination must answer with a 2xx status within 10 seconds.

Can the same event arrive twice?

Yes. Delivery is at least once. A batch that was accepted but whose acknowledgement was lost is sent again. Thus the same event can arrive twice. Deduplicate on the id field. It is stable, unique and repeatable for the same event. Events from each source arrive in order.

How do I verify that a batch came from Gatana?

Every request carries an X-Gatana-Signature header with a timestamp and an HMAC-SHA256 value over the raw body, keyed with your signing secret. Verify against the raw body before you parse JSON. Reject a request whose timestamp is older than a tolerance that you select. Five minutes is a reasonable default.

Which SIEMs work with the stream?

Any collector that accepts an authenticated HTTPS POST of newline-delimited JSON. Splunk HTTP Event Collector and CrowdStrike Falcon LogScale accept the batches on their raw endpoints. Elastic takes them on an HTTP input. Microsoft Sentinel receives them through a relay. In-house pipelines operate in the same way.

Does the stream include tool arguments and responses?

Only if you increase the MCP audit log level. The default, terse, records the server, the tool, the duration and the caller. Detailed adds the arguments. Detailed with error adds the response of failed calls. Verbose adds every response. Secret values are replaced with a redaction marker at every level.

All guides