On this page
What the MCP specification says
Very little. In the current specification (2026-07-28), the page on tools ends with a list of things clients should do, and the last item is: log tool usage for audit purposes. That is the whole of it. There are no required fields, no format, no word on how long to keep anything or who should be able to read it.
Two other parts of the specification sound related and are not. The logging utility lets a server send diagnostic messages to a client, at levels like debug and error. It is for troubleshooting, and the specification says those messages must not contain credentials or personal information. The security best practices page mentions audit trails only in passing, as a reason not to pass tokens through and to keep scopes narrow.
So the question "who called which tool, with what, and can we show it later?" has no official answer. You have to design the record yourself. The rest of this guide is one way to do it.
Where to record the call
A tool call passes through up to three places, and each sees something different.
| Where | What it sees | What it misses | Best for |
|---|---|---|---|
| The client or agent host | The user, the conversation, every server it calls | Nothing, but the agent's own process can often reach the log | Knowing why a call was made |
| A gateway or proxy | Every call to every server, the caller's identity, both request and result | The reasoning behind the call | One consistent record that the agent cannot rewrite |
| The MCP server | The calls it received and what it did | Calls to other servers, and often which person was behind the client | A tool owner's record of what its own system did |
What one record needs
A useful record can be read a year later by someone who was not there. In MCP terms, a tools/call request carries the tool's name and its arguments, and the result carries the content returned and a flag saying whether it was an error. Around those, add who asked, when, and whether a person approved it.
Two details are easy to miss. Record the person and the agent separately, because "the support agent did it" does not tell you whose request it was acting on. And record calls that were refused or failed. A blocked attempt to export every customer record is one of the most useful lines a log can hold.
One MCP tool call, written down
tools/call · issue_refundThe person the agent acts for and the agent itself. A shared service account answers neither.
The server and the tool name from the tools/call request.
The arguments, or only their hash when they hold personal data. The hash still lets you match the call later.
For actions that needed a person: who said yes, tied to this exact call.
Whether it worked, and a fingerprint of the result. Refused and failed calls belong here too.
Both ends of the call, in UTC, from the gateway's clock.
Added where the record is stored, outside the agent's reach. The specification asks for none of this.
What to keep out of the record
Tool arguments and results are where the sensitive data lives: customer names, message bodies, query results, sometimes credentials that should never have been passed at all. An audit log is kept for a long time and read by people who were not part of the conversation, so copy as little of that into it as you can.
Store a fingerprint instead. A SHA-256 hash of the arguments and of the result lets you show later that a particular call happened with exactly those inputs, without the log holding the inputs themselves. Keep the full payloads, if you need them, in a store with shorter retention and tighter access.
Never record access tokens, API keys or session secrets. Leave out the model's private reasoning unless you have decided you need it. And remember that a signed record cannot be edited afterwards, which is the point, so decide what goes in before you sign, not after.
From a log to evidence
A log file on the machine that runs the agent is useful for debugging. It is weak as evidence, for one reason: whoever can change the agent can usually change the file. That includes the agent itself, if a tool gives it shell or file access.
Three properties change that. The record is written somewhere the agent cannot reach, through a credential held by the gateway and not by the agent. Each record is signed and numbered when it is stored, so an edited or missing record is detectable. And the people who may need to rely on it, such as your customer or your security team, can check a record themselves.
None of this is specific to MCP. It is the same standard an audit log for human users has to meet. MCP only makes it more pressing, because an agent can make hundreds of calls in the time a person makes one.
Recording a tool call with Invoance
Invoance is not an MCP gateway and does not sit in the path of your tool calls. It is where the gateway, or your own code, writes the record. Post one event per call to the Event Ledger. Invoance hashes the payload, signs it with your organization's Ed25519 key, stores it where deletes are blocked, and returns an ID with a public proof page.
For calls that change something, write two events: one before the tool runs, saying what is about to happen, and one after, with the outcome. If the first write fails, do not run the tool. That way no action exists without a record of the attempt.
To keep a record of what the model itself said, such as the answer that led to the call, use an AI attestation. It stores a hash of the input and of the output separately, with the model's name. A trace groups all the records from one agent run into a single sealed bundle.
curl -X POST https://api.invoance.com/v1/events \
-H "Authorization: Bearer $INVOANCE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"event_type": "mcp.tool_call.completed",
"payload": {
"user": "user_2207",
"client": "support-agent-v3",
"server": "billing-mcp",
"tool": "issue_refund",
"arguments_hash": "3f9a1c07...e2b4",
"approved_by": "user_0031",
"is_error": false,
"result_hash": "b71d44e9...90ac",
"requested_at": "2026-11-12T09:41:12.000Z",
"completed_at": "2026-11-12T09:41:13.210Z"
}
}'
Letting the agent write records itself
Invoance also runs its own MCP server, at https://mcp.invoance.com/mcp. Add it to Claude, ChatGPT or another MCP client, and the agent gains tools that write the same signed records: log_event for something that happened, attest_ai_output for a model's input and output, and anchor_document for a file's fingerprint. Each returns a proof link.
This is the quick way to start, and it has an obvious limit. A record the agent chooses to write is a record of what the agent reported. It is good for keeping a signed note of decisions and outputs as work happens. It is not a substitute for a gateway that records every call whether or not the agent mentions it. Use the gateway for completeness and the MCP server for convenience.
A checklist to start from
1. Pick the place: a gateway if you have one, the client if you do not.
2. Record every tools/call, including refused and failed ones.
3. Record the person and the agent as separate fields.
4. Hash arguments and results, and keep raw payloads out of the long-lived log.
5. Tie approvals to the exact call they approved.
6. Keep the writing credential out of the agent's environment.
7. Sign and number each record where it is stored.
8. Decide how long to keep records, and write that down.
9. Have someone outside the agent team check a sample on a schedule.
What this does not give you
A signed record shows that the record has not changed since it was written. It does not show that the record was true, or complete. A call that bypassed your gateway leaves nothing, and no signature will reveal it, so the control that matters most is making sure there is no path around the place you record.
It also does not make the tool call safe. Logging tells you what happened. Deciding what an agent is allowed to do, and when a person has to approve it, is a separate job.
