← All articles

MCP Audit Logging: Complete Security and Compliance Guide

July 20, 2026·30 min read·MCPForge

MCP Audit Logging: Complete Security and Compliance Guide

MCP allows AI applications to access data and perform actions through external servers.

A single request may involve:

  • a human user
  • an AI host application
  • an MCP client
  • an Authorization Server
  • an API gateway
  • an MCP server
  • a policy engine
  • a credential broker
  • a background task
  • a database
  • a third-party API
  • an administrative approval

When an important action occurs, an organization must be able to answer:

text
Who initiated the action?

Which MCP client acted?

Which server and tool were used?

What resource or tenant was affected?

Which authorization and approval allowed it?

What data moved?

Which downstream system changed?

Did the operation succeed?

Without a connected audit trail, each system may expose only a fragment.

text
Identity Provider:
User logged in

Authorization Server:
Token issued

MCP Server:
Tool called

Downstream API:
Resource changed

None of those records alone explains the complete event.

MCP audit logging creates that connection.

text
User
  │
  ▼
MCP Host and Client
  │
  ▼
Authorization Server
  │
  ▼
MCP Gateway
  │
  ▼
MCP Server and Tool
  │
  ▼
Downstream Service
  │
  ▼
Correlated Audit Trail

NIST describes log management as the process of generating, transmitting, storing, accessing, and disposing of log data, supporting use cases such as cybersecurity incident identification, investigation, operational troubleshooting, and required retention.

Quick Answer

MCP audit logging is the authoritative recording of security-relevant events across the complete MCP execution chain. A useful audit record should preserve the verified user, OAuth client, workload, MCP resource, tool, target, tenant, authorization decision, approval state, downstream effect, and outcome. It must exclude reusable credentials, minimize sensitive prompt and data content, support correlation across systems, resist tampering, and remain searchable during incident response.


MCP Protocol Logging vs Audit Logging

MCP includes a structured logging utility.

In protocol revision 2025-11-25, a server can advertise:

json
{
  "capabilities": {
    "logging": {}
  }
}

The client may request a minimum level using:

json
{
  "jsonrpc": "2.0",
  "id": 24,
  "method": "logging/setLevel",
  "params": {
    "level": "warning"
  }
}

The server can then send:

json
{
  "jsonrpc": "2.0",
  "method": "notifications/message",
  "params": {
    "level": "error",
    "logger": "database",
    "data": {
      "message": "Connection failed"
    }
  }
}

The stable MCP schema defines the following levels:

  • debug
  • info
  • notice
  • warning
  • error
  • critical
  • alert
  • emergency

These levels map to the severity model from RFC 5424.

This protocol feature is primarily useful for:

  • diagnostics
  • progress visibility
  • troubleshooting
  • development feedback
  • client-facing operational messages

It is not automatically a complete security audit system.


Why Protocol Logs Are Not an Audit Trail

MCP protocol logs may be:

  • filtered by severity
  • disabled
  • ignored by the client
  • displayed but not persisted
  • controlled by the server being investigated
  • disconnected from Authorization Server events
  • missing downstream effects
  • unavailable after a process exits
  • incomplete during a compromise
text
Server sends log notification
          │
          ▼
Client may display it
          │
          ▼
Client may discard it

An audit trail should not depend on whether a user selected the debug, info, or warning level.

Security-relevant events must be recorded according to server-side policy even when no MCP logging capability was negotiated.


Audit Logs Must Be Independent

A secure architecture separates:

Diagnostic Logs

Help developers and operators understand technical behavior.

Security Logs

Record suspicious events, policy failures, token misuse, and attacks.

Audit Logs

Record authoritative actions and decisions for accountability.

Business Transaction Records

Record domain events such as a payment, deployment, document deletion, or permission change.

text
One MCP action
      │
      ├── Diagnostic event
      ├── Security event
      ├── Audit event
      └── Business transaction

These records may be sent to the same platform, but they have different purposes, schemas, access rules, and retention requirements.


Audit Logging Goals

An MCP audit system should support:

  • accountability
  • incident detection
  • forensic investigation
  • authorization review
  • abuse detection
  • user support
  • compliance evidence
  • operational reconstruction
  • dispute resolution
  • data-access reporting

A well-designed record should answer:

text
Who?
What?
When?
Where?
Through which client?
Against which MCP resource?
With which authorization?
Why was it allowed or denied?
What was the result?

What Audit Logging Cannot Prove Automatically

Logs are evidence, not absolute truth.

A record may be incomplete or misleading when:

  • the application logs an unverified identity
  • the clock is incorrect
  • a compromised server fabricates records
  • the real action bypasses the logging path
  • logs are modified
  • correlation IDs are reused
  • downstream actions are asynchronous
  • the user account is compromised
  • the model summary does not match the actual arguments
text
Log says:
user-123 requested action

But:
user-123 session may have been stolen

Audit architecture should preserve verified facts and clearly distinguish them from untrusted assertions.


Authoritative vs Untrusted Audit Fields

Consider:

json
{
  "tenant_id": "tenant-a",
  "tool_arguments": {
    "tenant_id": "tenant-b"
  }
}

Which tenant should the audit record use?

The authoritative tenant should come from:

  • validated token claims
  • server-side session state
  • policy engine context
  • verified resource mapping

The tool argument should be recorded separately as requested input.

json
{
  "actor_tenant_id": "tenant-a",
  "requested_tenant_id": "tenant-b",
  "authorization_decision": "deny",
  "reason_code": "cross_tenant_request"
}

This distinction is critical during investigations.


The MCP Audit Event Model

A standardized event model makes searches and correlations easier.

A practical audit record may include:

json
{
  "event_id": "evt_01JZ...",
  "event_type": "mcp.tool.execution",
  "event_version": "1.0",
  "timestamp": "2026-07-20T15:42:18.613Z",
  "correlation_id": "corr_01JZ...",
  "request_id": "mcp-request-4821",
  "session_id": "session-fingerprint",
  "actor": {},
  "client": {},
  "authorization": {},
  "resource": {},
  "operation": {},
  "approval": {},
  "outcome": {},
  "network": {},
  "data": {},
  "service": {}
}

Do not add every possible field to every event.

Use a consistent core combined with event-specific fields.


Core Event Fields

Every audit event should generally contain:

  • unique event ID
  • event type
  • schema version
  • timestamp
  • producing service
  • environment
  • outcome
  • correlation identifier

Example:

json
{
  "event_id": "evt_c7d94c8b",
  "event_type": "mcp.authorization.denied",
  "event_version": "1.0",
  "timestamp": "2026-07-20T15:42:18.613Z",
  "service_name": "finance-mcp",
  "service_version": "4.8.1",
  "environment": "production",
  "correlation_id": "corr_e3445a91",
  "outcome": "denied"
}

Event Identifiers

Every event should have a unique identifier.

text
event_id = one log record

The identifier supports:

  • deduplication
  • references from alerts
  • forensic notes
  • evidence export
  • replay detection
  • ingestion troubleshooting

Do not use a user ID, request ID, or timestamp alone as the unique event identifier.


Event Types

Use stable, machine-readable event names.

Examples:

text
mcp.session.initialized
mcp.authorization.succeeded
mcp.authorization.denied
mcp.tool.requested
mcp.tool.approval.requested
mcp.tool.approval.granted
mcp.tool.execution.started
mcp.tool.execution.completed
mcp.tool.execution.failed
mcp.resource.read
mcp.prompt.retrieved
mcp.sampling.requested
mcp.elicitation.requested
mcp.server.configuration.changed
mcp.client.registration.created
mcp.security.token_rejected

Avoid using free-form English sentences as the only event classification.


Schema Version

Audit event schemas change over time.

Include:

json
{
  "event_version": "1.2"
}

Schema versioning supports:

  • parsers
  • migrations
  • dashboards
  • backward compatibility
  • evidence interpretation
  • long-term retention

A stored event should remain understandable after the producing service has been upgraded.


Timestamps

Use a precise, unambiguous timestamp.

Recommended representation:

text
2026-07-20T15:42:18.613Z

Record timestamps in UTC.

Additional fields may include:

json
{
  "timestamp": "2026-07-20T15:42:18.613Z",
  "observed_timestamp": "2026-07-20T15:42:18.702Z",
  "duration_ms": 89
}

Event Time

When the action occurred.

Observed Time

When the logging or collection system received it.

The difference can reveal:

  • delayed delivery
  • queue backlog
  • clock problems
  • offline processing
  • replayed records

Clock Synchronization

A multi-system MCP workflow depends on reliable time.

text
Authorization Server:
15:42:18.100

MCP Gateway:
15:42:17.450

MCP Server:
15:42:19.900

Incorrect clocks can make events appear in the wrong order.

Systems should use authenticated and monitored time synchronization where practical.

Audit monitoring should detect:

  • large clock drift
  • timestamps from the future
  • timestamps older than expected
  • repeated timestamps
  • sudden clock changes

Correlation IDs

A correlation ID connects events belonging to one logical workflow.

text
MCP Host
corr-123
   │
   ▼
Authorization Server
corr-123
   │
   ▼
Gateway
corr-123
   │
   ▼
MCP Server
corr-123
   │
   ▼
Downstream API
corr-123

Each system should also retain its own local identifiers.

Example:

json
{
  "correlation_id": "corr-123",
  "mcp_request_id": 42,
  "gateway_request_id": "gw-789",
  "downstream_request_id": "api-456"
}

Correlation IDs Are Not Authentication

A caller may supply:

http
X-Correlation-ID: administrator-approved

This value does not prove anything.

Correlation identifiers should be:

  • generated by a trusted entry point
  • validated for length and format
  • replaced when invalid
  • propagated in controlled fields
  • excluded from authorization decisions

They help connect events.

They do not establish user, client, or approval identity.


Trace IDs and Span IDs

Distributed tracing may already provide:

  • trace ID
  • span ID
  • parent span ID
json
{
  "trace_id": "78f563...",
  "span_id": "014ac9...",
  "parent_span_id": "01d532..."
}

These can support audit correlation.

However, general tracing may:

  • sample events
  • omit denied requests
  • retain data briefly
  • expose detailed payloads
  • allow developers broad access
  • be disabled under load

Security audit logging should not depend exclusively on sampled traces.


User Identity

An audit record should capture the authenticated actor.

Example:

json
{
  "actor": {
    "type": "human",
    "subject_id": "usr_8421",
    "tenant_id": "tenant-a",
    "authentication_context": "phishing_resistant_mfa"
  }
}

Prefer stable internal identifiers.

Email addresses and display names may change and may contain personal data.

Where useful, store:

  • stable user ID
  • tenant or organization
  • role at decision time
  • authentication strength
  • acting administrator
  • effective user

Actor vs Subject

Some actions involve delegation or impersonation.

text
Actor:
support-admin-42

Subject:
customer-user-123

A correct record should preserve both.

json
{
  "actor": {
    "subject_id": "support-admin-42",
    "type": "administrator"
  },
  "effective_subject": {
    "subject_id": "customer-user-123"
  },
  "delegation": {
    "type": "support_impersonation",
    "reason_code": "case-9182"
  }
}

Recording only the effective user would hide the administrator who actually acted.


MCP Client Identity

The same user may use several clients.

json
{
  "client": {
    "client_id": "enterprise-agent",
    "client_name": "Enterprise AI Agent",
    "registration_type": "preregistered",
    "verification_status": "approved"
  }
}

Useful fields include:

  • OAuth client_id
  • client registration type
  • publisher or software ID
  • software version
  • verification status
  • device or installation identifier where permitted

A client-provided display name should not replace the actual client_id.


Host and MCP Client Separation

MCP architecture distinguishes the host application from the individual client connection.

text
Host:
AI desktop application

Client:
Connection to Finance MCP

Client:
Connection to Documentation MCP

Audit records may preserve both:

json
{
  "host": {
    "application_id": "desktop-ai",
    "version": "8.2.0"
  },
  "client": {
    "connection_id": "conn-finance-739",
    "oauth_client_id": "desktop-ai-prod"
  }
}

This helps analyze multi-server workflows.


Workload Identity

For remote deployments, log the authenticated service identity.

json
{
  "workload": {
    "identity": "spiffe://example.com/ns/finance/sa/mcp",
    "environment": "production",
    "region": "eu-central",
    "instance_id": "pod-7c8499",
    "artifact_digest": "sha256:..."
  }
}

Possible fields include:

  • service account
  • certificate identity
  • cloud workload principal
  • namespace
  • cluster
  • instance
  • deployment version
  • container image digest

Do not rely only on a source IP address.


MCP Resource Identity

Record the exact MCP Resource Server targeted by the token and request.

json
{
  "resource": {
    "resource_server": "https://finance-mcp.example.com",
    "server_name": "finance-mcp",
    "environment": "production"
  }
}

This helps prove that authorization was bound to the intended resource.

A log entry containing only:

text
audience valid

is less useful than recording the validated resource identifier.


OAuth Authorization Context

An MCP audit record should preserve useful authorization facts without storing the token.

Example:

json
{
  "authorization": {
    "issuer": "https://auth.example.com",
    "audience": "https://finance-mcp.example.com",
    "scopes": [
      "invoices:read",
      "invoices:create"
    ],
    "token_type": "Bearer",
    "token_id": "jti-8c239",
    "token_fingerprint": "sha256:7c5d...",
    "expires_at": "2026-07-20T15:50:00Z"
  }
}

Where available, useful values include:

  • issuer
  • audience
  • scopes
  • token identifier
  • authentication context
  • grant or delegation ID
  • expiration
  • client ID
  • tenant

Never store the raw Access Token.


Token Fingerprints

A non-reversible token fingerprint can help correlate use of the same token.

Conceptually:

text
fingerprint =
HMAC(audit-specific secret, token)

Prefer a keyed construction rather than a plain hash when token entropy or implementation conditions might permit guessing.

The fingerprint should:

  • not allow token recovery
  • use an audit-specific key
  • support rotation
  • avoid becoming an authentication credential
  • be accessible only where required

Do Not Log Authorization Headers

Unsafe:

text
Authorization: Bearer eyJhbGciOi...

Also unsafe:

json
{
  "headers": {
    "authorization": "Bearer ..."
  }
}

HTTP middleware that logs every request header can silently expose:

  • Access Tokens
  • API keys
  • cookies
  • Basic credentials
  • signed client assertions

Use explicit allowlists for logged headers rather than attempting to blacklist every sensitive header.


Sensitive OAuth Events to Audit

Relevant Authorization Server events include:

  • authorization request received
  • client validation succeeded or failed
  • redirect URI rejected
  • user authentication succeeded or failed
  • consent granted or denied
  • incremental scope requested
  • authorization code issued
  • authorization code redeemed
  • token issued
  • Refresh Token rotated
  • Refresh Token replay detected
  • token revoked
  • client registration created
  • registration metadata changed
  • client suspended
  • signing key changed

These events should correlate with the later MCP request where possible.


Tool Discovery Events

Audit relevant changes and access to the tool catalog.

Possible events:

text
mcp.tools.list.requested
mcp.tools.list.completed
mcp.tools.catalog.changed
mcp.tool.added
mcp.tool.removed
mcp.tool.schema.changed

Why tool discovery matters:

  • a compromised server may expose new tools
  • a software update may add destructive capability
  • a client may enumerate tools it has never used
  • a schema change may broaden permitted arguments

A catalog hash can help detect changes.

json
{
  "tool_catalog": {
    "tool_count": 18,
    "schema_digest": "sha256:...",
    "server_version": "4.8.1"
  }
}

Tool Request Events

A tool request event should describe the requested action before execution.

Example:

json
{
  "event_type": "mcp.tool.requested",
  "operation": {
    "tool_name": "create_invoice",
    "operation_class": "write",
    "risk_level": "high",
    "target_type": "customer_account",
    "target_id": "customer-456"
  },
  "authorization": {
    "required_scopes": [
      "invoices:create"
    ],
    "granted_scopes": [
      "invoices:create"
    ]
  }
}

This event is different from execution success.

A request may later be:

  • denied
  • cancelled
  • modified
  • approved
  • timed out
  • executed unsuccessfully

Tool Arguments

Tool arguments may contain:

  • credentials
  • personal data
  • confidential documents
  • source code
  • legal information
  • payment data
  • injected instructions
  • large binary content

Do not log every argument automatically.

Use a field policy for each tool.

Example:

json
{
  "argument_audit": {
    "customer_id": "customer-456",
    "currency": "EUR",
    "amount_minor": 150000,
    "description": "[REDACTED]",
    "attachment": {
      "logged": false,
      "sha256": "..."
    }
  }
}

Tool-Specific Audit Schemas

Define allowed audit fields per tool.

Example:

text
Tool:
send_email

Log:
message ID
sender account
recipient domains
recipient count
attachment count
classification
approval ID
outcome

Do not log by default:
full subject
full body
attachment contents
authentication headers

Another example:

text
Tool:
read_file

Log:
normalized path category
approved root
file fingerprint
bytes returned
classification

Do not log by default:
full file contents
secret values
entire home-directory path

Normalized Targets

Raw arguments may represent the same resource in several forms.

text
./documents/report.pdf
/home/user/project/documents/report.pdf
documents/../documents/report.pdf

Audit the normalized target used by authorization and execution.

json
{
  "requested_path": "documents/../documents/report.pdf",
  "normalized_target": "/approved/project/documents/report.pdf",
  "approved_root": "/approved/project"
}

This helps investigate path traversal attempts.


Record Requested and Executed Actions Separately

A model or intermediary may transform arguments.

text
Requested:
Delete staging database

Executed:
Delete production database

A secure audit chain should preserve both.

json
{
  "requested_operation": {
    "environment": "staging",
    "resource_id": "db-test"
  },
  "executed_operation": {
    "environment": "production",
    "resource_id": "db-prod"
  },
  "arguments_changed": true
}

Unexpected differences should trigger an alert.


Authorization Decision Events

Record the decision before execution.

Example:

json
{
  "event_type": "mcp.authorization.decision",
  "decision": "deny",
  "reason_code": "missing_scope",
  "policy_id": "finance-tool-policy",
  "policy_version": "19",
  "required_scopes": [
    "payments:create"
  ],
  "granted_scopes": [
    "payments:read"
  ]
}

Use stable reason codes.

Useful examples:

text
invalid_token
wrong_audience
untrusted_issuer
missing_scope
client_not_approved
tenant_mismatch
object_not_authorized
step_up_required
approval_required
policy_denied
rate_limited
data_transfer_prohibited

Policy Version

The authorization decision depends on the policy active at that time.

Store:

json
{
  "policy": {
    "policy_id": "production-deployment-policy",
    "version": "42",
    "decision": "allow"
  }
}

Without the version, investigators may evaluate an old event against current rules and reach the wrong conclusion.


Approval Events

High-risk tool calls may require user or administrator approval.

Record:

  • approval requested
  • approval displayed
  • approval granted or denied
  • approver identity
  • exact action digest
  • expiration
  • number of allowed uses
  • execution linked to approval

Example:

json
{
  "event_type": "mcp.tool.approval.granted",
  "approval_id": "approval-9182",
  "approver": {
    "subject_id": "user-123"
  },
  "action_digest": "sha256:...",
  "tool_name": "delete_resource",
  "target_id": "resource-456",
  "expires_at": "2026-07-20T15:44:00Z",
  "max_uses": 1
}

Approval Display Evidence

A user can approve only what was meaningfully presented.

Where risk justifies it, preserve a sanitized representation of the approval screen:

json
{
  "approval_display": {
    "template_version": "3.2",
    "summary": "Delete production resource resource-456",
    "risk_label": "irreversible",
    "destination": "production-eu",
    "action_digest": "sha256:..."
  }
}

Do not automatically store a full screenshot containing personal or secret data.


Bind Execution to Approval

Execution should reference the exact approval.

json
{
  "event_type": "mcp.tool.execution.started",
  "approval": {
    "approval_id": "approval-9182",
    "action_digest_match": true,
    "approval_age_seconds": 22,
    "use_number": 1
  }
}

Alert when:

  • approval is expired
  • action digest differs
  • approval was already used
  • approver is not authorized
  • tenant differs
  • client differs
  • tool differs

Tool Execution Events

Execution events should distinguish:

text
Requested
Authorized
Started
Completed
Failed
Cancelled
Timed out

Example:

json
{
  "event_type": "mcp.tool.execution.completed",
  "operation": {
    "tool_name": "create_invoice",
    "target_id": "invoice-789"
  },
  "outcome": {
    "status": "success",
    "duration_ms": 842,
    "records_affected": 1
  }
}

Do not record success merely because the MCP server returned HTTP 200.

The downstream operation may still have failed.


Partial Success

Some tools perform multiple actions.

text
Upload 10 files

8 succeeded
2 failed

Audit the partial result explicitly.

json
{
  "outcome": {
    "status": "partial_success",
    "requested_items": 10,
    "succeeded_items": 8,
    "failed_items": 2
  }
}

A generic success: true would hide important information.


Idempotency and Duplicate Execution

Retries can create duplicate actions.

Record:

  • idempotency key
  • retry count
  • previous request reference
  • duplicate detection result
  • downstream transaction ID
json
{
  "execution": {
    "idempotency_key": "idem-9821",
    "attempt": 2,
    "duplicate_detected": true,
    "original_event_id": "evt-original"
  }
}

This is especially important for:

  • payments
  • email sending
  • ticket creation
  • deployments
  • destructive actions
  • durable tasks

MCP Resource Access Events

Resources may expose files, documents, database content, or generated context.

Audit events may include:

text
mcp.resource.listed
mcp.resource.read
mcp.resource.subscribed
mcp.resource.updated

A resource-read record may contain:

json
{
  "event_type": "mcp.resource.read",
  "resource": {
    "uri": "document://customer-456/report",
    "classification": "confidential",
    "tenant_id": "tenant-a"
  },
  "outcome": {
    "bytes_returned": 18422,
    "records_returned": 1
  }
}

Avoid placing the complete resource content in the audit log.


Prompt Access Events

MCP prompts are user-controlled templates, but they may still contain:

  • internal instructions
  • proprietary workflows
  • user data
  • generated variables
  • sensitive context

Audit:

  • prompt identifier
  • prompt version
  • requester
  • argument names or sanitized values
  • result size
  • destination
  • outcome

Example:

json
{
  "event_type": "mcp.prompt.retrieved",
  "prompt": {
    "name": "customer-risk-review",
    "version": "7",
    "argument_names": [
      "customer_id",
      "review_type"
    ]
  }
}

Do not automatically record the complete rendered prompt.


Sampling Events

Sampling allows an MCP server to request model generation through the client.

Relevant events include:

  • sampling requested
  • sampling approved
  • sampling denied
  • context inclusion selected
  • model selected
  • request sent
  • response returned
  • response shared with server

Useful fields include:

json
{
  "event_type": "mcp.sampling.completed",
  "sampling": {
    "requesting_server": "analysis-mcp",
    "model_provider": "approved-provider",
    "model_id": "model-family",
    "context_mode": "thisServer",
    "input_classification": "internal",
    "input_tokens": 2180,
    "output_tokens": 612
  }
}

Full prompts and model responses should require a separate data-retention decision.


Elicitation Events

Elicitation allows an MCP server to request additional user information.

Audit:

  • requesting server
  • requested field types
  • whether sensitive fields were requested
  • user approval
  • validation result
  • whether values were returned
  • destination

Do not log submitted secrets or personal values by default.

Example:

json
{
  "event_type": "mcp.elicitation.completed",
  "elicitation": {
    "field_names": [
      "project_name",
      "deployment_region"
    ],
    "sensitive_fields_requested": false,
    "user_submitted": true
  }
}

Durable Task Audit Events

The 2025-11-25 MCP specification introduced experimental tasks for durable requests, polling, and deferred result retrieval.

Relevant events include:

text
mcp.task.created
mcp.task.status_changed
mcp.task.polled
mcp.task.cancel_requested
mcp.task.cancelled
mcp.task.completed
mcp.task.expired
mcp.task.result_retrieved

A task may outlive the original connection.

Its audit record should preserve:

  • original user
  • original client
  • authorization context
  • task owner
  • creation time
  • status transitions
  • result retrieval
  • cancellation actor
  • expiration

Authorization for Long-Running Tasks

A task created under valid authorization may complete after:

  • the token expires
  • the user loses permission
  • the client is revoked
  • the tenant membership changes

The audit trail should show which policy applies:

json
{
  "task_authorization": {
    "mode": "authorization_snapshot_at_creation",
    "original_decision_event_id": "evt-auth-123"
  }
}

or:

json
{
  "task_authorization": {
    "mode": "continuous_reevaluation",
    "last_reevaluated_at": "2026-07-20T16:00:00Z"
  }
}

This behavior should be explicit rather than accidental.


Downstream API Events

The MCP server may call another service.

text
MCP Tool
   │
   ▼
Credential Broker
   │
   ▼
Downstream API

Audit enough information to connect the external effect:

json
{
  "downstream": {
    "service": "billing-api",
    "operation": "POST /invoices",
    "credential_identity": "finance-mcp-invoice-role",
    "request_id": "billing-req-9182",
    "resource_id": "invoice-789",
    "status_code": 201
  }
}

Do not log:

  • upstream API token
  • complete authorization headers
  • secret request parameters
  • full customer payload unless specifically justified

Credential Broker Events

Where a credential broker issues temporary access, audit:

  • requesting workload
  • user context
  • tool
  • downstream resource
  • credential profile
  • policy decision
  • lifetime
  • issuance success
  • revocation

Example:

json
{
  "event_type": "credential.issued",
  "credential": {
    "profile": "billing-invoice-create",
    "audience": "billing-api",
    "lifetime_seconds": 300,
    "credential_fingerprint": "sha256:..."
  }
}

The credential itself must remain outside the log.


Data Movement Events

An MCP workflow can move information between servers.

text
CRM MCP
   │
Customer Data
   │
   ▼
Model Context
   │
   ▼
Email MCP

Audit the transfer as a distinct event.

json
{
  "event_type": "mcp.data.transfer",
  "source": {
    "server": "crm-mcp",
    "classification": "confidential",
    "tenant_id": "tenant-a"
  },
  "destination": {
    "server": "email-mcp",
    "destination_class": "external_saas"
  },
  "data": {
    "record_count": 24,
    "fields": [
      "customer_email",
      "account_status"
    ],
    "bytes": 8940
  },
  "decision": "allow_with_redaction"
}

Two individually permitted tool calls can still create an unauthorized combined transfer.


Data Classification

Audit records should preserve classification without copying the protected content.

Possible values:

text
public
internal
confidential
restricted
regulated
secret

Example:

json
{
  "data": {
    "classification": "restricted",
    "contains_personal_data": true,
    "contains_credentials": false,
    "contains_source_code": false
  }
}

This supports:

  • DLP
  • access control
  • retention
  • alerting
  • incident prioritization

Data Volume

Record useful volume indicators.

Examples:

  • records read
  • records modified
  • bytes returned
  • files accessed
  • recipients
  • rows exported
  • tokens sent to a model
json
{
  "data_volume": {
    "records_read": 10000,
    "bytes_returned": 8240012
  }
}

Volume anomalies can reveal:

  • scraping
  • exfiltration
  • runaway agents
  • broken pagination
  • malicious automation

Audit High-Risk Denials

Denied operations are often as important as successful actions.

Audit:

  • wrong audience
  • invalid issuer
  • missing scope
  • cross-tenant request
  • path traversal
  • blocked destination
  • approval mismatch
  • rate-limit violation
  • prohibited data transfer
  • disabled user
  • suspended client
json
{
  "event_type": "mcp.security.request_denied",
  "reason_code": "wrong_audience",
  "expected_audience": "https://finance-mcp.example.com",
  "presented_audience": "https://docs-mcp.example.com"
}

Do not include the raw rejected token.


Authentication Failures

Record enough information to detect attacks without enabling account enumeration.

Possible fields:

json
{
  "event_type": "authentication.failed",
  "reason_code": "invalid_credential",
  "account_reference": "non_reversible_reference",
  "client_id": "enterprise-agent",
  "source": {
    "network_zone": "external",
    "ip_prefix": "203.0.113.0/24"
  }
}

The user-facing response may remain generic while internal logs use a more specific reason.


Rate-Limit Events

Audit significant rate-limit actions:

json
{
  "event_type": "mcp.rate_limit.exceeded",
  "limit_policy": "tool-delete-10-per-hour",
  "subject_id": "user-123",
  "client_id": "enterprise-agent",
  "tool_name": "delete_resource",
  "observed_count": 14
}

Avoid logging every harmless throttled retry if that creates overwhelming noise.

Aggregate where appropriate.


Server Lifecycle Events

Audit:

  • server startup
  • server shutdown
  • configuration loaded
  • policy loaded
  • tool catalog loaded
  • artifact version
  • network policy changed
  • secret reference changed
  • health degradation
  • logging pipeline failure

Example:

json
{
  "event_type": "mcp.server.started",
  "service_name": "finance-mcp",
  "service_version": "4.8.1",
  "artifact_digest": "sha256:...",
  "policy_version": "42",
  "tool_catalog_digest": "sha256:..."
}

This helps identify which code and policy handled an event.


Configuration Changes

Configuration changes may alter:

  • authorization
  • tool availability
  • allowed filesystem paths
  • network destinations
  • tenants
  • credentials
  • logging behavior
  • retention
  • redaction

Audit before and after values where safe.

json
{
  "event_type": "mcp.configuration.changed",
  "change": {
    "field": "allowed_egress_domains",
    "before_digest": "sha256:...",
    "after_digest": "sha256:...",
    "change_ticket": "SEC-9182"
  },
  "actor": {
    "subject_id": "admin-42"
  }
}

Do not store secret values in configuration diffs.


Tool Catalog Changes

Adding a tool can create new execution capability.

Audit:

  • tool added
  • tool removed
  • schema changed
  • annotation changed
  • required scope changed
  • risk classification changed
  • approval requirement changed
json
{
  "event_type": "mcp.tool.schema.changed",
  "tool_name": "deploy_service",
  "old_schema_digest": "sha256:...",
  "new_schema_digest": "sha256:...",
  "risk_change": {
    "before": "medium",
    "after": "high"
  }
}

A changed tool description is also relevant because the model and user may rely on it.


Administrative Events

Audit administrative actions such as:

  • client approval
  • user suspension
  • scope assignment
  • policy override
  • log export
  • retention change
  • alert suppression
  • audit-record deletion request
  • emergency access
  • impersonation

Administrative records should include:

  • administrator identity
  • reason
  • ticket or case
  • affected object
  • previous state
  • new state
  • approval chain

Break-Glass Access

Emergency access should generate enhanced audit records.

json
{
  "event_type": "administration.break_glass_activated",
  "actor": {
    "subject_id": "admin-42"
  },
  "reason": "production incident INC-9182",
  "scope": "deployment-mcp:admin",
  "expires_at": "2026-07-20T17:00:00Z",
  "approver_count": 2
}

Break-glass access should be:

  • time-limited
  • narrow
  • highly visible
  • reviewed afterward
  • excluded from routine use

Audit Access Events

Audit logs themselves contain sensitive information.

Record:

  • who searched logs
  • which tenant or time range
  • which fields were exported
  • which case justified access
  • whether raw payload evidence was viewed
  • whether records were downloaded
json
{
  "event_type": "audit.records.exported",
  "actor": {
    "subject_id": "security-analyst-17"
  },
  "query_scope": {
    "tenant_id": "tenant-a",
    "start": "2026-07-20T15:00:00Z",
    "end": "2026-07-20T16:00:00Z"
  },
  "case_id": "INC-9182",
  "record_count": 842
}

Access to audit evidence should itself be auditable.


What Must Never Be Logged

Do not write reusable secrets into MCP audit logs.

This includes:

  • Access Tokens
  • Refresh Tokens
  • authorization codes
  • Client Secrets
  • Initial Access Tokens
  • Registration Access Tokens
  • private keys
  • session cookies
  • passwords
  • one-time codes
  • API keys
  • database passwords
  • full authentication headers

The MCP logging specification also warns against sending credentials, secrets, personally identifying information, or internal details that could aid attacks through server log notifications.


Data That Requires Careful Treatment

The following may sometimes be logged, but not by default in full:

  • prompts
  • model responses
  • tool arguments
  • tool results
  • resource contents
  • filenames
  • URLs with query parameters
  • email addresses
  • IP addresses
  • customer identifiers
  • document titles
  • database queries
  • stack traces
  • internal hostnames
  • approval screenshots

Use:

  • redaction
  • hashing
  • tokenization
  • classification
  • structured summaries
  • controlled evidence vaults
  • shorter retention

Redaction

Redaction should happen before data reaches the normal log pipeline.

Unsafe:

text
Application logs token
      │
Collector later redacts it

The secret may already exist in:

  • local files
  • container output
  • process buffers
  • sidecar logs
  • crash reports
  • temporary queues

Safer:

text
Application constructs safe event
      │
      ▼
Audit pipeline receives sanitized fields

Allowlist Logging

Prefer defining fields that may be logged.

text
Allowed:
tool name
target ID
record count
outcome
duration

Not included:
everything else

This is safer than attempting to detect every possible secret in arbitrary payloads.


Redaction Failure Detection

Automated scanners can detect patterns such as:

  • Bearer Tokens
  • private-key headers
  • cloud-access keys
  • authorization codes
  • passwords in URLs
  • session cookies

When detected:

  1. block or quarantine the event
  2. generate a security alert
  3. remove exposed data
  4. rotate affected credentials
  5. investigate the source
  6. verify downstream copies

Pattern detection is a safety net, not a replacement for safe event construction.


Log Injection

Untrusted values may contain:

  • newline characters
  • terminal escape sequences
  • fake timestamps
  • JSON fragments
  • HTML
  • spreadsheet formulas
  • control characters

Example attacker input:

text
normal-value
2026-07-20 ALLOW administrator action

If written into unstructured logs, it may create fake entries.

Mitigations:

  • structured JSON
  • length limits
  • control-character handling
  • contextual output encoding
  • safe terminal display
  • safe CSV export
  • no raw HTML rendering

Structured Logging

Structured logs are easier to validate and search.

Prefer:

json
{
  "event_type": "mcp.tool.execution.failed",
  "tool_name": "create_invoice",
  "reason_code": "downstream_timeout",
  "duration_ms": 30000
}

Instead of:

text
Invoice tool failed for some reason after waiting.

Free-form messages may still be included for humans, but machine-readable fields should carry the authoritative meaning.


Severity vs Audit Importance

MCP logging uses syslog-style severity levels.

Audit systems may additionally classify:

  • security impact
  • compliance relevance
  • operational priority
  • investigation urgency

Example:

json
{
  "severity": "notice",
  "security_priority": "high",
  "event_type": "mcp.client.scope_expanded"
}

A normal administrative change may not be a technical error, but it can still be security-critical.


Suggested Severity Mapping

Debug

Detailed development diagnostics that should normally be disabled in production.

Info

Routine successful activity.

Notice

Important normal events such as client registration or configuration activation.

Warning

Suspicious, deprecated, or recoverable conditions.

Error

Failed operations requiring investigation.

Critical

Failure of an important security or service component.

Alert

Immediate response required.

Emergency

System-wide inability to operate securely.

The RFC 5424 severity model defines these levels from emergency through debug.


Audit Logging Failure

The application must decide what happens when the audit pipeline fails.

Possible strategies:

Fail Closed

Reject high-risk operations when authoritative auditing is unavailable.

Appropriate for:

  • payments
  • privilege changes
  • production deletion
  • regulated administration
  • break-glass access

Buffered Operation

Write to a protected local queue and forward later.

Appropriate when temporary disconnection is expected and storage is reliable.

Continue With Alert

Permit lower-risk actions while raising an urgent operational alert.

The choice should depend on event risk.


Never Fail Silently

Unsafe:

text
Audit collector unavailable
        │
        ▼
Application continues
        │
        ▼
No alert

Safer:

text
Audit collector unavailable
        │
        ├── Health signal
        ├── Local protected buffer
        ├── Operations alert
        ├── Capacity limit
        └── Defined fail behavior

Audit-pipeline status should itself be monitored and recorded.


Audit Event Delivery

Possible delivery models include:

  • synchronous API
  • local append-only file
  • system journal
  • message queue
  • event stream
  • sidecar collector
  • agent
  • cloud logging service

A common design is:

text
MCP Application
      │
Safe Structured Event
      │
      ▼
Local Collector
      │
      ▼
Durable Queue
      │
      ▼
Central Audit Store
      │
      ▼
SIEM and Archive

The application should not block indefinitely while sending logs.


Local Buffering

Local buffering protects against short outages.

The buffer should have:

  • encryption
  • disk quota
  • restricted permissions
  • ordered delivery
  • retry
  • duplicate handling
  • corruption detection
  • overflow policy

A full disk should not allow an attacker to silently disable future audit records.


Backpressure

An attacker may generate huge numbers of events.

text
Malicious requests
       │
       ▼
Millions of audit records
       │
       ▼
Logging pipeline overloaded

Controls include:

  • rate limits
  • aggregation
  • priority queues
  • separate security channels
  • capacity reservations
  • bounded diagnostic logging
  • preserving high-value audit events

Do not sample away critical authorization failures or destructive actions merely because volume is high.


Duplicate Events

At-least-once delivery may create duplicates.

Use:

  • unique event IDs
  • producer sequence numbers
  • idempotent ingestion
  • deduplication windows
  • source identifiers

Do not assume two similar events are duplicates merely because their timestamps and tool names match.


Missing Events and Sequence Gaps

A producer may maintain a monotonic sequence:

json
{
  "producer_id": "finance-mcp-instance-7",
  "sequence": 9182
}

The collector can detect:

text
9180
9181
9183

Missing 9182 may indicate:

  • delivery failure
  • process crash
  • tampering
  • queue corruption

Sequence numbers require careful handling across restarts and multiple instances.


Audit Log Integrity

An attacker who compromises an MCP server may try to:

  • delete records
  • alter outcomes
  • change user identities
  • remove failed requests
  • fabricate approvals
  • hide data exports

Audit records should leave the application environment quickly.

text
MCP Server
    │
    ▼
Separate Audit Domain

The server should not have permission to modify or delete previously stored central events.


Append-Oriented Storage

Audit stores should prefer append-oriented behavior.

The producing service may:

text
Create new event

but should not:

text
Update historical event
Delete historical event

Corrections should be represented as new events referencing the original record.

json
{
  "event_type": "audit.correction",
  "original_event_id": "evt-123",
  "reason": "downstream status reconciled",
  "corrected_outcome": "partial_success"
}

Cryptographic Integrity

Possible integrity controls include:

  • event hashes
  • hash chains
  • digital signatures
  • signed batches
  • Merkle trees
  • immutable storage
  • external timestamping

Conceptual hash chain:

text
Event 1 hash
      │
      ▼
Event 2 includes previous hash
      │
      ▼
Event 3 includes previous hash

A gap or modification becomes detectable.

Cryptographic integrity does not prevent deletion unless external checkpoints or independent copies exist.


Signing Audit Events

A producer may sign events using a workload-specific key.

json
{
  "event_id": "evt-123",
  "payload_digest": "sha256:...",
  "signature": "...",
  "signing_identity": "finance-mcp-prod"
}

Key management must ensure:

  • private keys are protected
  • keys are rotated
  • verification keys are retained
  • compromise times are known
  • algorithms are restricted
  • signing does not expose application secrets

A compromised workload with access to its signing key can still sign false events.

Independent collection and runtime telemetry remain important.


Separation of Duties

The people who operate the MCP service should not automatically have unrestricted power over its audit evidence.

Separate roles may include:

  • MCP service operator
  • audit platform administrator
  • security analyst
  • compliance reviewer
  • privacy officer
  • retention administrator
text
Service Operator:
Can run MCP service

Audit Administrator:
Can manage storage

Security Analyst:
Can search approved events

No single role:
Can alter service and erase evidence

Encryption

Protect audit data:

In Transit

Use authenticated encrypted transport between:

  • application and collector
  • collector and queue
  • queue and storage
  • storage and analysis tools

At Rest

Encrypt:

  • local buffers
  • central indexes
  • archives
  • backups
  • evidence exports

Encryption keys should be separated from ordinary application credentials.


Audit Log Access Control

Audit records may reveal:

  • customer activity
  • internal resource names
  • employee behavior
  • security incidents
  • system architecture
  • privileged actions

Use fine-grained access controls based on:

  • role
  • tenant
  • investigation case
  • data classification
  • time range
  • field sensitivity
  • purpose

A developer debugging one MCP server should not automatically see every tenant's complete audit history.


Field-Level Access

Some users may see:

text
event type
time
tool
outcome
duration

while only authorized investigators see:

text
user identity
target identifier
network details
sanitized argument evidence

Field-level controls reduce unnecessary exposure.


Multi-Tenant Audit Isolation

Every event should contain authoritative tenant context.

json
{
  "tenant": {
    "tenant_id": "tenant-a",
    "source": "validated_authorization_context"
  }
}

Audit queries must enforce tenant isolation.

Unsafe:

text
tenant filter supplied only by UI

Safer:

text
tenant access enforced by backend policy
and storage controls

A compromised tenant administrator must not retrieve another tenant's records by changing a query parameter.


Shared Infrastructure Events

Some events may relate to multiple tenants or no single tenant.

Examples:

  • Authorization Server signing-key rotation
  • global policy change
  • shared MCP server outage
  • audit pipeline failure

Use explicit scope:

json
{
  "tenant_scope": "global"
}

Do not assign shared events to an arbitrary customer tenant.


Privacy and Data Minimization

Audit logging creates a new collection of data.

The log system should not become an uncontrolled copy of:

  • prompts
  • customer documents
  • model outputs
  • email bodies
  • source repositories
  • personal information
  • credentials

Record only what is necessary for defined purposes.

NIST log-management guidance treats retention, access, storage, analysis, and disposal as parts of the log lifecycle rather than treating collection as the only concern.


Purpose Limitation

Define why each category is collected.

Example:

FieldPurpose
User IDAccountability and investigation
Client IDClient abuse detection
Tool nameAction reconstruction
Target IDResource impact analysis
Record countExfiltration detection
Full promptNot collected by default

Fields without a clear purpose should be challenged.


Pseudonymization

Some audit use cases may not require directly identifiable user information.

Possible design:

json
{
  "actor_reference": "hmac:8ac9..."
}

A separate controlled service may resolve the reference during an authorized investigation.

Pseudonymization reduces routine exposure but does not make the data anonymous when reidentification remains possible.


IP Addresses

IP addresses can support:

  • attack detection
  • geographic anomaly analysis
  • network investigation
  • abuse prevention

They may also be personal or sensitive data.

Possible minimization includes:

  • prefix truncation
  • regional classification
  • shorter retention
  • separate restricted fields
  • storing only where risk justifies it

Security requirements and privacy obligations must be balanced deliberately.


Retention

There is no universal retention period for MCP audit logs.

Different categories may have different periods.

Example:

text
High-risk administrative actions:
Longer retention

Verbose diagnostic logs:
Short retention

Raw sensitive evidence:
Very short, case-controlled retention

Aggregated security metrics:
Longer retention

Retention should consider:

  • incident detection window
  • regulatory obligations
  • customer contracts
  • legal holds
  • privacy requirements
  • storage cost
  • data sensitivity
  • usefulness of old records

Retention Tiers

A tiered model may use:

Hot

Fast searchable storage for recent events.

Warm

Lower-cost searchable storage.

Cold

Long-term archive.

Evidence Vault

Restricted storage for selected incident evidence.

text
Recent Events
    │
Hot
    │
Warm
    │
Cold Archive

Moving an event between tiers should preserve integrity and schema information.


Disposal

Expired audit data should be disposed of according to policy.

Disposal should include:

  • primary storage
  • replicas
  • indexes
  • caches
  • local buffers
  • exports
  • backups where applicable

Deletion events may themselves require records.

json
{
  "event_type": "audit.retention.disposal_completed",
  "policy_id": "audit-retention-v7",
  "period_end": "2025-07-01",
  "records_affected": 482102
}

Do not include the deleted sensitive records in the disposal event.


A legal or investigation hold may suspend normal deletion.

The hold should be:

  • authorized
  • narrowly scoped
  • documented
  • reviewed
  • removed when no longer needed
json
{
  "event_type": "audit.legal_hold.applied",
  "case_id": "CASE-9182",
  "scope": {
    "tenant_id": "tenant-a",
    "start": "2026-07-01T00:00:00Z",
    "end": "2026-07-20T23:59:59Z"
  }
}

Audit Search Requirements

Investigators should be able to search by:

  • event ID
  • correlation ID
  • user
  • client ID
  • MCP server
  • tool
  • resource
  • tenant
  • token fingerprint
  • approval ID
  • downstream request ID
  • time range
  • outcome
  • reason code
  • data classification

A log archive that cannot be searched during an incident provides limited value.


Audit Timeline Reconstruction

A timeline may show:

text
15:42:18.100
User authenticated

15:42:18.320
Authorization granted

15:42:18.560
Tool requested

15:42:18.590
Policy allowed

15:42:25.200
User approved

15:42:25.310
Credential issued

15:42:25.450
Downstream request sent

15:42:26.118
Invoice created

The timeline should preserve both system-local IDs and shared correlation.


Expected MCP Audit Architecture

A production architecture may look like:

text
Identity Provider
      │
Authorization Server
      │
MCP Host and Client
      │
Gateway
      │
Policy Engine
      │
MCP Server
      │
Credential Broker
      │
Downstream APIs
      │
      └──────────────┐
                     ▼
              Local Collectors
                     │
                     ▼
               Durable Queue
                     │
                     ▼
              Central Audit Store
                     │
              ┌──────┴──────┐
              ▼             ▼
             SIEM      Immutable Archive

Each component emits the events for which it is authoritative.


Do Not Trust One Producer for Everything

The MCP server may report:

text
Tool allowed
Tool executed
Downstream succeeded

Independent systems should contribute their own evidence.

text
Policy engine:
Decision allowed

Credential broker:
Credential issued

Downstream API:
Resource created

Audit collector:
Events received

This reduces reliance on one potentially compromised component.


First Implementation Priorities

A practical first implementation should:

  1. Define a stable audit-event schema.
  2. Generate unique event and correlation IDs.
  3. Record verified user, client, resource, tenant, tool, decision, and outcome.
  4. Create tool-specific argument allowlists.
  5. remove tokens, secrets, and complete prompts from logs.
  6. record authorization and approval decisions separately from execution.
  7. correlate downstream effects.
  8. send events to storage outside the MCP process.
  9. alert on logging failure.
  10. test whether investigators can reconstruct one complete high-risk action.

A small, reliable audit trail is better than an enormous unsafe dump of every prompt and payload.


SIEM Integration

An audit trail becomes significantly more valuable when events from multiple systems are analyzed together.

A Security Information and Event Management (SIEM) platform can combine events from:

  • Identity Provider
  • Authorization Server
  • MCP Host
  • MCP Client
  • MCP Gateway
  • Policy Engine
  • MCP Server
  • Credential Broker
  • Kubernetes
  • Service Mesh
  • Cloud Platform
  • Downstream APIs
  • Endpoint Detection
  • Firewall
  • DNS
  • Email Security
text
Identity
     │
Authorization
     │
MCP
     │
Runtime
     │
Network
     │
Cloud
     │
     ▼
SIEM

A single MCP event may appear harmless.

Multiple correlated events may reveal an active compromise.


Correlation Rules

Rather than evaluating events independently, a SIEM should connect related activities.

Example:

text
Authentication

↓

Token Issued

↓

New MCP Client

↓

High-Risk Tool

↓

Large Export

↓

Unknown Destination

Individually:

All events appear valid.

Combined:

Possible data exfiltration.


Multi-Stage Attack Detection

Example sequence:

text
User Login

↓

Client Registration

↓

Tool Discovery

↓

Privilege Escalation Attempt

↓

Resource Enumeration

↓

Bulk Export

↓

External Transfer

The individual events may span:

  • several servers
  • several minutes
  • multiple identities
  • several network zones

Only correlation exposes the complete attack.


Impossible Travel

If authentication events contain geographic information:

text
09:00
Warsaw

09:18
Singapore

the SIEM may detect:

  • impossible travel
  • stolen session
  • proxy abuse
  • credential theft

Geographic detection should account for:

  • VPN usage
  • corporate proxies
  • cloud egress
  • remote workers

Unusual Client Behavior

Normal usage:

text
Documentation Client

↓

Reads Documentation

↓

Occasional Search

Unexpected:

text
Documentation Client

↓

Finance Tools

↓

Admin Tools

↓

Mass Export

Even with valid tokens, behavior may indicate compromise.


First-Time Events

Alert when something happens for the first time.

Examples:

  • new client
  • new tool
  • new destination
  • new tenant combination
  • new country
  • new workload
  • new cloud region
  • new administrator
  • new approval pattern

Baseline awareness often detects attacks earlier than signature-based rules.


Behavioral Baselines

For every MCP server establish:

  • expected users
  • expected tools
  • expected request frequency
  • expected data volume
  • expected destinations
  • expected working hours
  • expected tenants
  • expected approval frequency

Example:

text
Typical:

40 invoice reads/day

Observed:

18,000 invoice reads

That difference deserves investigation.


Tool Frequency Monitoring

Record typical invocation frequency.

text
delete_document

Normal:
2/day

Observed:
900/hour

Possible causes include:

  • automation bug
  • compromised agent
  • malicious workflow
  • infinite retry
  • prompt injection

High-Risk Tool Monitoring

Assign a risk level to every tool.

Example:

Low

  • read documentation
  • search knowledge base

Medium

  • create ticket
  • update record

High

  • delete resource
  • deploy production
  • transfer money
  • rotate secrets
  • create administrator

High-risk tools deserve:

  • richer audit records
  • stronger alerts
  • longer retention
  • more approvals

Risk Scoring

Multiple small signals can become significant together.

text
New Device
+15

New Client
+20

Admin Tool
+30

Large Export
+35

Unknown Destination
+40

Total:
140

Instead of alerting on every event individually, organizations may alert when the cumulative risk exceeds a threshold.


Prompt Injection Telemetry

Prompt injection attempts often produce unusual behavior.

Possible indicators:

  • repeated tool discovery
  • attempts to bypass approval
  • requests for secrets
  • hidden instructions
  • repeated authorization failures
  • unusual argument combinations
  • privilege escalation attempts

Record the behavior rather than storing the complete malicious prompt.

Example:

json
{
  "event_type": "security.prompt_injection_detected",
  "classification": "possible",
  "signals": [
    "tool_enumeration",
    "approval_bypass_attempt",
    "credential_request"
  ]
}

Repeated Authorization Failures

One denied request is normal.

Thousands may indicate reconnaissance.

text
Wrong Scope

↓

Wrong Audience

↓

Different Tool

↓

Different Tenant

↓

Different Resource

This resembles automated privilege discovery.


Tenant Enumeration

Alert when one identity attempts:

text
tenant-a

tenant-b

tenant-c

tenant-d

even if every request is denied.

Enumeration attempts often precede exploitation.


Resource Enumeration

Repeated requests for:

  • sequential IDs
  • predictable paths
  • hidden tools
  • internal resources

may indicate reconnaissance.

text
customer-001

customer-002

customer-003

customer-004

Large numbers of failures deserve attention.


Large Data Exports

Watch for:

  • unusually large responses
  • many downloads
  • bulk resource reads
  • many files
  • unusual token counts
  • excessive API responses

Example:

text
Normal:

25 documents

Observed:

48,000 documents

New Destinations

Unexpected outbound destinations may indicate:

  • exfiltration
  • malware
  • configuration drift
  • compromised server
text
Known:

storage.internal

Observed:

unknown-example.xyz

Network monitoring should correlate with audit records.


Secret Access Monitoring

Audit whenever protected secrets are accessed.

Examples:

  • vault read
  • credential issuance
  • signing key usage
  • certificate request
  • API key retrieval

Example:

json
{
  "event_type": "credential.accessed",
  "credential_profile": "billing-api",
  "workload": "finance-mcp",
  "reason": "invoice_creation"
}

Unexpected Process Activity

Runtime monitoring should detect:

  • shell launches
  • new binaries
  • unexpected child processes
  • package installation
  • filesystem scans
  • network scanners

These events may never appear in normal MCP protocol logs.


OpenTelemetry Integration

Many organizations already deploy OpenTelemetry.

Audit events may include:

json
{
  "trace_id": "3baf...",
  "span_id": "8d92...",
  "correlation_id": "corr-9182"
}

OpenTelemetry provides:

  • traces
  • metrics
  • logs

Audit records should remain authoritative while optionally linking to traces for investigation.


Audit Dashboards

Useful dashboards include:

Authentication

  • logins
  • failures
  • MFA
  • client registrations

Authorization

  • allow vs deny
  • reason codes
  • scope failures
  • audience failures

Tools

  • most-used tools
  • high-risk tools
  • failed tools
  • destructive tools

Tenants

  • cross-tenant attempts
  • exports
  • approvals

Security

  • suspicious behavior
  • anomalous clients
  • prompt injection
  • DLP events

Investigation Workflow

A typical investigation may begin with:

text
Alert

↓

Correlation ID

↓

Timeline

↓

Affected User

↓

Affected Client

↓

Affected MCP Server

↓

Tool

↓

Downstream Changes

↓

Root Cause

The investigator should not need to manually combine dozens of unrelated log files.


Immutable Storage

Audit evidence should survive:

  • ransomware
  • administrator mistakes
  • compromised workloads
  • accidental deletion

Possible approaches include:

  • append-only storage
  • object lock
  • WORM storage
  • immutable snapshots
  • cryptographic verification
  • offline archive

No single mechanism provides complete protection.


Evidence Packages

During an incident, investigators often export:

  • timeline
  • affected events
  • hashes
  • signatures
  • policy versions
  • approval records
  • downstream transaction IDs

An evidence package should remain verifiable even after export.


Compliance Mapping

Different frameworks require different evidence.

Audit records may support:

  • ISO/IEC 27001
  • SOC 2
  • PCI DSS
  • HIPAA
  • GDPR
  • NIST Cybersecurity Framework
  • NIST SP 800-53
  • internal governance

One audit architecture can satisfy multiple reporting requirements if events are structured consistently.


Performance Considerations

Logging should not become a bottleneck.

Strategies include:

  • asynchronous delivery
  • batching
  • compression
  • durable queues
  • structured events
  • bounded payload sizes
  • efficient indexing

Avoid blocking production requests while waiting for slow audit storage.


Cost Management

Verbose logging increases storage costs.

Consider retaining:

Always:

  • authorization decisions
  • approvals
  • administrative actions
  • destructive operations
  • policy changes
  • security events

Sometimes:

  • complete payloads
  • prompts
  • model outputs
  • verbose diagnostics

Retention should reflect investigative value rather than convenience.


Testing Audit Logging

Test that:

  • every important action creates an event
  • denied requests are logged
  • approvals correlate correctly
  • correlation IDs propagate
  • timestamps remain ordered
  • secrets never appear
  • redaction works
  • failures trigger alerts
  • duplicate handling functions correctly
  • evidence survives service restarts

Security testing should verify the audit system itself.


MCP Audit Logging Checklist

Event Quality

  • Stable event types
  • Unique event IDs
  • UTC timestamps
  • Schema version
  • Correlation IDs
  • Consistent structure

Identity

  • Verified user
  • Client ID
  • Workload identity
  • Tenant
  • Authentication strength

Authorization

  • Issuer
  • Audience
  • Scope
  • Policy version
  • Decision
  • Reason code

Tool Activity

  • Tool name
  • Target
  • Risk level
  • Requested action
  • Executed action
  • Outcome

Data

  • Classification
  • Record count
  • Bytes transferred
  • Destination
  • Redaction

Security

  • No tokens
  • No secrets
  • No passwords
  • No private keys
  • Structured logging
  • Log injection protection

Infrastructure

  • Durable delivery
  • Independent storage
  • Immutable archive
  • Access controls
  • Encryption
  • Monitoring

Detection

  • Correlation rules
  • Baselines
  • Anomaly detection
  • Prompt injection telemetry
  • Cross-tenant monitoring
  • DLP monitoring

Incident Response

  • Timeline reconstruction
  • Evidence export
  • Policy history
  • Approval history
  • Downstream correlation
  • Integrity verification

Common Audit Logging Mistakes

Logging Every Request Body

Large payloads increase cost, expose confidential information, and make investigations harder.

Storing Access Tokens

A compromised audit database should never become a credential vault.

Mixing Debug Logs With Audit Logs

Developers and investigators have different requirements.

Missing Correlation IDs

Without correlation, distributed investigations become slow and error-prone.

Trusting Client-Supplied Fields

Audit records should prioritize verified server-side values.

Ignoring Denied Requests

Repeated failures often reveal attacks before successful compromise.

Allowing Applications to Delete Their Own Logs

A compromised workload should not be able to erase evidence.

Logging Without Monitoring

Collecting millions of events without detection rules rarely improves security.


Want to analyze your API security?

Import your OpenAPI spec and generate a Security Report automatically.

Conclusion

Audit logging is one of the most important security capabilities in an MCP deployment.

Unlike ordinary diagnostic logs, an audit trail must create an authoritative history of identity, authorization, tool execution, approvals, data movement, and downstream effects.

An effective design:

  • records verified facts rather than assumptions
  • correlates events across every MCP component
  • protects credentials and sensitive content
  • preserves integrity through independent storage
  • supports rapid investigations
  • enables compliance reporting
  • detects attacks before they become incidents

The strongest audit architecture is not the one that stores the most data.

It is the one that reliably records the right security events, protects their integrity, minimizes unnecessary sensitive information, and allows investigators to reconstruct exactly what happened when every minute matters.

Continue learning:

Frequently Asked Questions

What is MCP audit logging?

MCP audit logging is the structured recording of security-relevant events across MCP clients, hosts, Authorization Servers, gateways, servers, tools, data sources, and downstream services so organizations can determine who performed an action, through which client and server, against which resource, with what authorization, and what result occurred.

Is MCP protocol logging the same as audit logging?

No. MCP protocol logging allows a server to send structured diagnostic messages to a client. Audit logging is an independent security control that records authoritative events for monitoring, investigations, accountability, compliance, and incident response.

Does MCP require audit logging?

The MCP specification defines structured server-to-client logging but does not define a complete mandatory audit trail for MCP deployments. Implementers must design their own audit architecture based on risk, security policy, privacy obligations, and applicable compliance requirements.

What should an MCP tool audit record contain?

A tool audit record should normally include timestamp, event type, user identity, client identity, MCP server identity, session or request correlation ID, tool name, target resource, tenant, authorization decision, approval state, outcome, duration, and a sanitized summary of arguments and results.

Should MCP prompts and tool arguments be logged?

Not automatically in full. Prompts and arguments may contain personal data, source code, credentials, confidential records, or malicious content. Prefer structured summaries, hashes, classifications, selected approved fields, and controlled evidence storage when complete payload capture is genuinely necessary.

Should Access Tokens be written to MCP logs?

No. Access Tokens, Refresh Tokens, authorization codes, Client Secrets, Registration Access Tokens, API keys, session cookies, passwords, and private keys must not be written to logs. Use non-reversible fingerprints, token identifiers, issuer, audience, scopes, and expiration metadata instead.

How can MCP events be correlated across systems?

Generate a stable correlation identifier at the entry point and propagate it through the host, client, Authorization Server, gateway, MCP server, policy engine, credential broker, background task, and downstream API while keeping local event IDs for each system.

How should multi-tenant MCP audit logs work?

Every event should include authoritative tenant context derived from authenticated policy state rather than only from tool arguments. Access to audit records must also be tenant-isolated so one tenant cannot view another tenant's events.

How long should MCP audit logs be retained?

There is no universal period. Retention should be based on incident-detection needs, regulatory requirements, contractual obligations, data sensitivity, storage cost, litigation or legal-hold requirements, and privacy minimization.

How can MCP audit logs be protected from tampering?

Send logs to a separate append-oriented system, restrict write and delete permissions, use encryption, immutable or write-once storage where appropriate, record hashes or signatures, synchronize time, monitor gaps, and separate operators of the MCP service from administrators of the audit store.

Check your MCP security posture

Generate a Security Score, detect risky tools, and review permissions before exposing APIs to AI agents.