TechnicalJuly 27, 202615 min read

MCP Audit: Secure and Govern Every Tool Call

A technical guide to MCP security and governance: inventory tools, gate calls with policy and approval, record outcomes, and export verifiable evidence.

Antonella Serine

Antonella Serine

Founder, KLA

Founder of KLA, building the independent runtime governance control plane for regulated AI agents under the EU AI Act.

Protocol boundary

MCP defines discovery, schemas, and tools/call. The host architecture owns organization policy, approval routing, retention, and integrity proof.

Trust boundary

Treat server identity, tool descriptions, annotations, schemas, and returned content as inputs with explicit trust decisions.

Decision contract

Resolve each proposed action to allow, warn, require_approval, or block before the side effect.

Audit unit

Join identity, tool and policy versions, argument and result hashes, approval, outcome, timestamps, and integrity proof under one execution identifier.

An MCP audit should answer one question for every consequential tool call: who or what asked for the action, which authority and policy allowed it, whether a person had to decide, what the tool changed, and how an independent reviewer can verify the record later.

The Model Context Protocol supplies a common connection lifecycle, capability discovery, tool schemas, and JSON-RPC messages. Those primitives make the tool-call boundary observable. Organization policy, approval routing, evidence retention, and cryptographic verification remain responsibilities of the host and the systems around it. This guide turns that boundary into an audit control from discovery through execution and evidence export.

Start with AI agent permissions when identity, delegation, scopes, or server access remain unresolved. Use AI agent audit trails for the wider execution record. The runtime AI governance guide covers the control-plane architecture beyond MCP.

What MCP standardizes, and where governance begins

In the current MCP specification, a client and server initialize a session, negotiate capabilities, and exchange protocol messages. A server with the tools capability can publish tool definitions through tools/list. Each definition can include a name, description, JSON Schema input, optional output schema, and behavior annotations. A client invokes one of those tools with tools/call.

That protocol sequence gives auditors stable objects to reference: protocol version, server implementation information, discovered tool definition, input schema, call identifier, arguments, result, and error state. Accountable ownership, consequence classification, enterprise authority, Decision Request routing, retention, and record-integrity proof belong at the host or gateway layer that sees every call.

The specification also sets an important trust rule. Clients must treat tool annotations as untrusted unless they come from a trusted server. Descriptions guide model tool selection and deserve the same review. Microsoft documents tool poisoning as an indirect prompt-injection path in which malicious instructions are placed inside tool descriptions. A production inventory therefore records the definition received from the server and the approved definition or digest that security reviewed.

MCP protocol objects and the governance record around them
StageProtocol objectGovernance controlEvidence to retain
Connectinitialize and negotiated protocol versionAuthenticate the server and bind the session to an approved environmentClient, server, transport, protocol version, session time, trust decision
Discovertools/list and optional list-change notificationCompare tools, schemas, descriptions, annotations, and versions with the approved inventoryTool-list digest, review status, change diff, owner, approved version
Proposetools/call with name and argumentsValidate schema, identity, scopes, destination, policy, and business consequenceCall ID, execution ID, principal, agent Release, argument hash, policy decision
DecideHost or gateway workflowAllow, warn, require approval, or block; bind approval to the exact callDecision, reason codes, policy version, reviewer, expiry, argument hash
ExecuteTool result or protocol errorApply idempotency, timeout, output validation, redaction, and side-effect reconciliationResult hash, error, duration, downstream receipt, before and after references
ProveEvidence export outside the MCP wire contractSeal a complete manifest and make integrity checks reproducibleManifest, hashes, signatures, chain proof, verification result

Build the governed tool inventory before runtime

An audit population begins with the servers and tools an agent can actually reach. Record the server owner, transport, package or image version, source repository, deployment environment, authentication method, OAuth resource or audience, granted scopes, data destinations, egress paths, and the agents and Processes allowed to connect.

For every discovered tool, retain the full definition and a canonical digest. Review the name, description, input schema, output schema, annotations, and any declared task behavior. When a server publishes a changed list, pause newly added or materially changed tools until the owner approves the diff. A model should never gain a new write path because a remote description changed between sessions.

Classify the action from real behavior. Read-only, destructive, idempotent, and open-world annotations are useful review hints. The current MCP schema states that they are hints and gives cautious defaults. Network controls, sandboxing, scoped credentials, and policy enforcement carry the guarantee.

  • Identity: stable server, tool, agent, principal, tenant, and owner identifiers.
  • Supply chain: source, publisher, digest, signature status, dependency review, and approved update channel.
  • Authority: exact tools, actions, destinations, data boundaries, OAuth scopes, and delegation expiry.
  • Change control: approved definition digest, first-seen and last-reviewed times, and a diff for every list change.
  • Runtime placement: environment, region, network boundary, secret reference, and egress policy.

Normalize every tools/call into one gate context

The gateway should parse the JSON-RPC request and add the facts the wire message cannot carry safely. The gate context needs tenant and execution identifiers, principal and agent identities, workflow and step, environment, canonical server and tool names, destination, tool arguments, data classification, model and prompt versions, and the current policy Release.

Validate the arguments against the approved input schema before policy evaluation. Hash the canonical arguments and keep sensitive values out of ordinary logs. The policy engine can evaluate selected structured fields when the tool schema declares them, while the evidence record retains a digest and controlled references to protected source data.

For HTTP transports, follow the MCP authorization specification: bind tokens to the intended resource, validate their audience at the MCP server, request the minimum scopes, and use separate downstream tokens for upstream APIs. For stdio, the MCP specification directs implementations to obtain credentials from the environment. In both cases, store token metadata and scope decisions in the audit record while excluding raw tokens and secrets.

MCP tools/call request at the governance boundary
{
  "jsonrpc": "2.0",
  "id": "call-1842",
  "method": "tools/call",
  "params": {
    "name": "cmb_decision_request.create",
    "arguments": {
      "case_id": "case-1842",
      "recommended_action": "require_human_approval",
      "reason_codes": [
        "confirmed_sanctions_hit"
      ],
      "approver_group": "aml-l1-approval",
      "urgency": "elevated",
      "evidence_refs": [
        "evidence://case-1842/screening"
      ]
    }
  }
}

Evaluate policy before the tool can act

Authentication proves which principal reached the server. Authorization establishes which resource and scope that principal may use. The runtime policy determines whether this action may run here, with these arguments, in this Process, at this time.

Use a fail-closed default. KLA PolicyVersion contracts represent four outcomes. allow releases the call. warn releases it and creates a reviewable signal. require_approval pauses it and routes a Decision Request to an authorized group. block refuses it. Matched rules carry a stable reason code, the fields evaluated, a determinism classification, and configured remediation. The default decision blocks calls that match no rule and emits its generic fallback reason.

The example below matches the current KLA PolicyVersion schema and Policy Builder vocabulary. It uses tool names and the reviewer group from KLA’s current AML guided-demo template. Bind policy scope and tool names to the target Tool Catalog before publication. The default blocks every tool absent from an explicit rule.

Schema-valid KLA PolicyVersion example
{
  "schemaVersion": "1.0.0",
  "policyId": "pol_mcp_tool_calls",
  "workspaceId": "workspace-regulated-operations",
  "name": "MCP tool-call controls",
  "description": "Governs AML alert reads, evidence retrieval, and Decision Desk routing.",
  "status": "draft",
  "version": "1.0.0",
  "policyKind": "guardrail",
  "scope": {
    "workflowIds": [],
    "agentIds": [],
    "stepIds": [],
    "environments": [
      "prod"
    ]
  },
  "defaultDecision": "block",
  "rules": [
    {
      "ruleId": "allow-alert-read",
      "name": "Allow scoped alert reads",
      "interceptionPoint": "tool_call",
      "when": {
        "expression": {
          "==": [
            {
              "var": "context.action.toolName"
            },
            "cmb_alerts.read"
          ]
        }
      },
      "then": {
        "decision": "allow",
        "reason": "The registered read tool may inspect an alert within its configured data scope.",
        "reasonCodes": [
          "aml_scoped_alert_read"
        ]
      },
      "execution": {
        "mode": "deterministic"
      },
      "evidence": {
        "evaluatedFields": [
          "context.action.toolName"
        ],
        "artifactRefs": [],
        "sensitivityTier": "internal"
      }
    },
    {
      "ruleId": "warn-evidence-retrieval",
      "name": "Flag evidence retrieval",
      "interceptionPoint": "tool_call",
      "when": {
        "expression": {
          "==": [
            {
              "var": "context.action.toolName"
            },
            "cmb_evidence.retrieve"
          ]
        }
      },
      "then": {
        "decision": "warn",
        "reason": "The tool retrieves case evidence under class-aware governance.",
        "reasonCodes": [
          "aml_evidence_retrieval"
        ],
        "remediation": {
          "summary": "Review the evidence class and references before a consequential action.",
          "steps": []
        }
      },
      "execution": {
        "mode": "deterministic"
      },
      "evidence": {
        "evaluatedFields": [
          "context.action.toolName"
        ],
        "artifactRefs": [],
        "sensitivityTier": "restricted"
      }
    },
    {
      "ruleId": "approve-decision-desk-routing",
      "name": "Decision Desk routing requires approval",
      "interceptionPoint": "tool_call",
      "when": {
        "expression": {
          "==": [
            {
              "var": "context.action.toolName"
            },
            "cmb_decision_request.create"
          ]
        }
      },
      "then": {
        "decision": "require_approval",
        "reason": "An AML L1 reviewer must confirm the material recommendation.",
        "reasonCodes": [
          "aml_decision_desk_routing_requires_approval"
        ],
        "remediation": {
          "summary": "Assign the request to AML L1 review.",
          "steps": [
            {
              "title": "Review the case packet",
              "description": "Inspect the recommendation, rationale, evidence references, and missing information."
            }
          ]
        },
        "approverGroup": "aml_l1_reviewers"
      },
      "execution": {
        "mode": "deterministic"
      },
      "evidence": {
        "evaluatedFields": [
          "context.action.toolName",
          "context.action.toolArgs"
        ],
        "artifactRefs": [],
        "sensitivityTier": "restricted"
      }
    }
  ]
}

Make human approval a durable control

A durable approval control records that an authorized person reviewed a defined action under a defined policy before execution.

Show the reviewer the agent and principal, tool and destination, material arguments in a safe display, business consequence, policy basis, reason codes, evidence references, expiry, and the exact decision requested. Enforce maker-checker separation where one person proposed or initiated the action. Check the reviewer role when the decision is submitted.

Bind the Decision Request to the argument hash and gate identifier. After approval, re-drive the same logical call and verify the arguments against the sealed hash. A changed amount, destination, record ID, or evidence reference requires a new decision. Reject expired approvals and approvals issued for another tenant, environment, policy version, or tool.

MCP tools/call does not define an enterprise approval workflow. The host can pause through its durable workflow engine, return a structured approval-required marker, or use the experimental task-augmented flow when both parties negotiate support. The control objective stays constant: no side effect occurs until the authorized decision resolves, and retries cannot create duplicate effects.

  • Pending: persist the Decision Request and stop before execution.
  • Approved: verify authority, expiry, gate ID, policy version, and argument hash; execute once.
  • Rejected: close the request and return a stable blocked outcome.
  • Changed call: create a new request with a new hash and decision history.
  • Timeout or outage: apply the published fail-closed outcome and preserve the failed attempt.

Control execution, output, and retries

Write an idempotency intent before a side-effecting call. Pass the idempotency key downstream when the tool supports it, then commit the outcome. A retry can return the committed result, resume a pending approval, or recover an in-flight intent under the same key. It cannot silently run the side effect twice.

Validate structured output against the approved output schema when the tool declares one. Treat returned text, links, embedded resources, images, and structured content as untrusted data. Apply redaction, content policy, destination controls, and an output gate before the model or another tool consumes the result.

Record protocol errors and tool execution errors separately. MCP tool results can carry isError: true, while malformed requests and unknown tools use protocol errors. Preserve both classes because they support different control tests: client validation, server availability, downstream business failure, and policy refusal.

Minimum negative-path tests for a governed MCP call
TestExpected resultEvidence
Input violates approved JSON SchemaReject before policy evaluation or executionValidation error, schema digest, call ID
Token has the wrong audience or expired scopeReject at the server boundaryAuthentication result and token metadata without token material
Policy decision point is unavailableApply the published fail-closed outcomeSystem reason code, outage time, no downstream receipt
Arguments change after approvalBlock the re-drive and require a new Decision RequestApproved hash, observed hash, mismatch reason
Duplicate delivery after a timeoutReturn the committed result or recover under the same idempotency keyIntent, downstream key, single side-effect receipt
Output violates schema or content policyHold, redact, or block before releaseOutput hash, failed checks, safe-display result

Record the complete audit unit

One MCP audit record should connect the proposed action, governance decision, human decision, execution outcome, and proof. A client trace with tool name and latency covers only part of that unit.

Use one correlation identifier across the client, gateway, policy engine, approval service, tool server, downstream system, Audit Trail, and evidence export. Reconcile counts across those layers. Every discovered call should end in one terminal governance state, and every executed side effect should have one decision plus one outcome record.

Fields an auditor should be able to resolve for one tool call
Evidence groupRequired fieldsAudit question
Identity and scopeTenant, principal, roles, delegation, agent and Release, Process, environmentWho acted, for whom, and where?
Tool provenanceServer and tool IDs, approved definition digest, package or image version, transportWhich reviewed capability received the call?
RequestCall and execution IDs, argument hash, controlled input references, destination, timestampWhat exact action was proposed?
PolicyPolicy ID and Release, rule, decision, reason codes, evaluated fields, determinismWhich control ran and why did it resolve this way?
Human decisionDecision Request, reviewer identity and role, safe display, rationale, time, expiryWho approved or rejected the consequential action?
OutcomeResult hash, error class, duration, idempotency key, downstream receipt, before and after referencesWhat happened, and did it happen once?
IntegrityLedger reference, manifest entry, content hash, signature, chain or inclusion proof, verifier resultCan an independent reviewer detect alteration or omission?

Seal evidence and preserve verification limits

KLA’s Evidence Factory exports a Sealed Evidence Bundle with a manifest, content hashes, signatures, verification material, and a documented population boundary. Keep raw records append-only where possible and preserve the policy and tool-definition snapshots needed to interpret them.

KLA evidence tooling creates a SHA-256 digest of the canonical manifest and signs it with ES256 service and tenant keys. The bundle carries public verification keys, and the offline verifier checks the manifest signatures, governance receipt signatures and ordering links, applicable ledger hash graphs, artifact Merkle inclusion, and timestamp anchor. Each check has an explicit result.

Integrity proof has a boundary. A valid signature proves that signed bytes match the key and manifest. Completeness requires an independently defined population, reconciliation to source systems, and a terminal anchor or equivalent control where a chain could be truncated. State missing records and unavailable dependencies as limitations in the audit report.

Use the execution lineage sample to inspect the shape of a review artifact. The policy-as-code guide explains the authoring side, and Execution Lineage covers investigation and replay.

Run the MCP audit as a repeatable program

Define the period, environments, agents, servers, tools, and consequential actions in scope. Export the approved inventory and every observed tool call. Reconcile client calls to gateway decisions, tool outcomes, downstream receipts, and evidence entries before selecting samples.

Test full populations for deterministic assertions such as approved server digest, recognized tool, valid schema, policy decision present, approval required where configured, argument hash unchanged, unique idempotency key, terminal outcome, and manifest entry. Sample human judgment for rationale, reviewer authority, safe-display sufficiency, exception handling, and business consequence.

Bias the sample toward new or changed tools, write and destructive actions, open-world retrieval, sensitive data, cross-tenant or cross-region boundaries, approval overrides, denials, errors, retries, policy outages, evidence failures, and the first calls after a tool or policy Release.

  • Population test: every observed call maps to an approved server and tool definition.
  • Control test: every call has one terminal validation or policy outcome; every schema-valid call has one enforced decision under the policy active at that time.
  • Approval test: every required approval precedes execution and binds to the same argument hash.
  • Outcome test: executed calls reconcile to one downstream effect and one result record.
  • Integrity test: bundle verification passes and negative tamper tests fail as expected.
  • Completeness test: source counts, exclusions, late events, failed exports, and unresolved gaps are quantified.

Current primary sources and scope

Protocol behavior in this guide was checked on 27 July 2026 against the official MCP 2025-11-25 tools specification, authorization specification, lifecycle specification, experimental tasks specification, and MCP security best practices.

The tool-poisoning description and mitigations were checked against Microsoft for Developers, Protecting against indirect prompt injection attacks in MCP. Exploit counts, forum claims, and product-flaw reports without primary advisories are excluded.

MCP evolves through dated protocol revisions. Pin the revision under audit, archive the schema and tool definitions received in that session, and re-check the current specification when changing client, server, or authorization behavior.

Frequently Asked Questions

What should an MCP audit log contain?

Record tenant, principal and agent identities, delegation, Process and environment, server and tool versions, approved definition digest, call and execution IDs, argument hash, policy Release and decision, reason codes, approval and reviewer authority, result hash, error, idempotency key, downstream receipt, timestamps, and integrity references. Exclude raw tokens and secrets.

Does MCP provide an audit trail?

MCP provides stable protocol messages and schemas that a host can observe. The host or gateway must add organization policy, approval records, retention, side-effect reconciliation, manifesting, signatures, and completeness controls to create audit evidence.

How should a client handle MCP tool descriptions and annotations?

Treat them as untrusted until the server and definition are approved. Store the reviewed definition digest, compare each discovered version with it, and hold new or materially changed tools for review. Enforce risk with credentials, policy, network controls, and sandboxing.

Where should an MCP approval happen?

Place approval before the side effect at a host or gateway that sees the proposed call. Persist a Decision Request, show the reviewer the consequence and policy basis, bind the decision to the call and argument hash, verify reviewer authority, and re-drive the same logical call after approval.

How do you prove an MCP tool call was not altered?

Hash canonical request and result data, store the governance records in tamper-evident storage, include them in a signed manifest, and verify the signature and applicable chain or inclusion proofs offline. Separately reconcile the bundle to a defined source population to test completeness.

What happens when the policy or evidence service is unavailable?

When policy evaluation is unavailable, apply the published fail-closed outcome, preserve a stable system reason code, and prevent the downstream side effect. When evidence export fails after execution, preserve an explicit failed or degraded evidence state, the source records, job failure, time, and recovery action. Alert the owner and retry without hiding the executed action.

Key Takeaways

A defensible MCP control starts with an approved tool inventory and places one policy checkpoint on every proposed call. It binds human approval to the exact arguments, executes side effects once, validates returned content, and joins the decision and outcome under one verifiable record. Map the wider control plane with the runtime AI governance guide, test your evidence with the Agent Audit Readiness Assessment, and inspect the execution lineage sample.

See It In Action

Ready to automate your compliance evidence?

Book a 20-minute demo to see how KLA helps you prove human oversight and export audit-ready Annex IV documentation.

MCP Audit: Secure and Govern Every Tool Call | KLA Blog