Logging tool calls for a trading audit trail
Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs before acting on a number.
The MCP specification lists this among what clients should do:
Clients SHOULD: … Log tool usage for audit purposes
For most tools that is a security recommendation. For trading it is that and something more useful: the log is the only record of what was proposed, what you approved, and what the market did about it. Without it, reviewing your own decisions is reconstruction from memory, and memory is generous.
Two different logs
Worth separating, because they answer different questions and mixing them produces something that answers neither well.
The protocol log — what was called, with what arguments, and what came back. This is the audit trail. It answers “what happened”.
The decision log — what was proposed, what the reasoning was, whether it was approved, and what the outcome was. This answers “was that a good idea”, which is the question you actually want answered a month later.
The protocol log is cheap and mechanical. The decision log requires deciding in advance what a decision consists of, which is the part worth thinking about.
What to capture per tool call
For the protocol log:
- Timestamp, with enough precision to order events that happen within the same second — which order submissions do.
- Tool name and full arguments. The arguments as submitted, not as summarised. This is the field that answers the wrong-parameter question.
- Result, including
isError. MCP reports tool execution failures in the result withisError: true, distinct from JSON-RPC protocol errors for things like unknown tools or invalid arguments. Capture which kind you got; they mean different things. - Duration. Slow calls precede ambiguous ones.
- Which server and which version. Tool sets change —
notifications/tools/list_changedexists for exactly that — so “which server was this” is not a constant.
Do not log credentials. Obvious, and yet: a handler that logs full request objects will include headers. The specification’s requirement that servers “sanitize tool outputs” is about this class of problem, and the same care belongs on the client side.
What to capture per decision
This is the part that pays off.
- The proposal as a structured object — symbol, side, size, entry, stop, and the computed risk. Not prose.
- The reasoning the model gave. Verbatim. This is how you later find out whether particular kinds of reasoning correlate with particular outcomes, and the answer is frequently uncomfortable.
- Approved or rejected, and when. Rejections are the more interesting half. A log of only approved trades cannot tell you whether your filtering is adding value, which is the most important thing to know about an approval step.
- Which limits were evaluated and what they returned. Including the ones that passed. “The daily-loss breaker was at 0.4% of 2%” is information; silence is not.
- The outcome, linked back to the proposal. Fill price, exit, result. The link is what makes the whole thing a dataset rather than a diary.
The question the log should be able to answer
Design backwards from these. If the log cannot answer them, it is the wrong log.
- What did I approve on the day I lost the most, and what did I reject?
- Are the trades I reject systematically worse than the ones I approve? (If not, the approval step is costing time and adding nothing — worth knowing.)
- How often did a limit actually fire, versus how often I believed it protected me?
- Did the model’s stated confidence predict anything?
- Which parameter mistakes reached the approval screen, and did I catch them?
That last one is the most valuable and the least commonly captured. It measures the approval step itself. If wrong parameters are reaching you and being approved, the screen is not working — and no amount of care will fix a screen that does not surface the thing.
Practical notes
Append-only, or close to it. A log you can quietly edit is a log you will eventually quietly edit.
Structured, not prose. You will want to aggregate this. Line-delimited JSON is enough; a spreadsheet is enough. A chat transcript is not.
Local. This is a complete record of your trading decisions and your account activity. It belongs where your keys are, which is on your machine.
Retention long enough to cover a full bad stretch. A month of logs tells you about a month. The patterns worth finding — drift in approval standards, degradation after losses — need longer.
Review on a schedule, not on a feeling. Logs reviewed only after bad outcomes produce a biased sample and a demoralising ritual. A weekly pass over everything, including the boring weeks, is where the signal is.
FAQ
Isn’t the exchange’s trade history enough?
It tells you what filled, which is the least ambiguous and least useful part. It cannot tell you what was proposed and rejected, what the reasoning was, or which limits fired. The rejected proposals in particular are where you find out whether your judgement is adding anything to the model’s.
What is the difference between a protocol error and a tool execution error?
MCP uses two channels. Protocol errors are standard JSON-RPC errors for things
like an unknown tool name or invalid arguments — the call never reached the
tool’s logic. Tool execution errors come back in the result with isError: true
and mean the tool ran and failed, for example an API failure downstream. Log
both and keep them distinguishable; “the tool does not exist” and “the exchange
rejected the order” are different problems.
Should I log the full model conversation?
The reasoning attached to each proposal, yes. The entire conversation, usually not — it is bulky, it dilutes the structured record, and it may contain material you would rather not retain. The useful unit is the proposal and its rationale, linked to its outcome.
How long should I keep this?
Long enough to contain a full drawdown and recovery, since that is the period the interesting questions are about. That is typically longer than the few weeks people default to.