Skip to main content

mcp-audit-trail

Your MCP agent just called 14 tools, accessed employee records, and submitted a PTO request. Do you know what actually happened?

This library sits between any MCP client and server as a transparent proxy, logs every JSON-RPC message, and spits out an HTML report you can actually read. Zero changes to your server code. Zero runtime dependencies.

status python license

MCP Audit Trail report


The problem

MCP gives agents the ability to call tools, query databases, and take real actions. That's great until you need to answer questions like:

  • What data did the agent actually read?
  • Did it access anything it shouldn't have?
  • Which tool call failed, and what arguments did it pass?
  • Who approved that PTO request — a human or the model?

Application logs won't tell you this. You need something that understands the MCP protocol itself.

Install

pip install mcp-audit-trail

No runtime dependencies. Seriously — the core library is pure Python stdlib. You only need the mcp SDK if you want to run the included demo server.

Quickstart

1. Proxy your server (nothing to change)

Stick the proxy between your client and server. Both sides think they're talking to each other directly.

mcp-audit-proxy \
  --server "python my_server.py" \
  --log audit.json \
  --sensitive-tools get_pay_info get_ssn \
  --write-tools submit_time_off delete_record

That's it. Every message flows through, gets logged to audit.json, and lands on the other side untouched.

2. Turn the log into something readable

mcp-audit-report --input audit.json --output report.html

Open report.html in a browser:

Session summary Tool usage and data access map

You get a session summary, tool classification (read/write/sensitive), a data access map, and an interactive timeline — click any event to expand the full arguments and results.

3. Or just use it from Python

from mcp_audit_trail import AuditLogger, generate_report

# log some events
logger = AuditLogger(
    "audit.json",
    sensitive_tools={"get_pay_info"},
    write_tools={"submit_time_off"},
)

logger.log("client_to_server", {
    "method": "tools/call",
    "id": 1,
    "params": {"name": "get_pay_info", "arguments": {"employee_id": "E001"}},
})

logger.save()

# render a report from any existing log
generate_report("audit.json", "report.html")

If you pass output_path=None to generate_report(), it returns the HTML string directly instead of writing to disk. Handy if you want to serve it from a web app or pipe it somewhere.

What gets logged

Every event in the audit log looks roughly like this:

{
  "timestamp": "2026-04-07T10:23:01.442Z",
  "elapsed_seconds": 1.2034,
  "direction": "client_to_server",
  "method": "tools/call",
  "tool_name": "get_pay_info",
  "tool_arguments": { "employee_id": "E001" },
  "flags": ["sensitive"]
}

The logger automatically pulls out tool names, arguments, and results from the JSON-RPC messages. It tracks:

  • Tool calls — name, arguments, result (parsed from tools/call requests + responses)
  • Timestamps — both wall-clock ISO format and elapsed seconds since session start
  • Data entities — any argument containing id or employee in the key name gets tracked as an accessed entity
  • Errors — flagged in both the event and the session summary
  • Direction — client_to_server or server_to_client
  • Custom flags — mark tools as sensitive or write and they show up tagged in the log and report

The final JSON file also includes a summary block at the top with aggregate stats, so you don't have to parse individual events for the common questions.

Flagging tools

Not all tool calls are equal. Reading a compliance rulebook is different from accessing someone's salary or approving a vacation request.

You can tell the logger (or the CLI) which tools are which:

mcp-audit-proxy \
  --server "python hr_server.py" \
  --sensitive-tools get_pay_info get_employee_info get_ssn \
  --write-tools submit_time_off delete_record update_profile

Or in Python:

logger = AuditLogger(
    "audit.json",
    sensitive_tools={"get_pay_info", "get_employee_info"},
    write_tools={"submit_time_off"},
)

Flagged events get tagged in the JSON log and highlighted in the HTML report. Sensitive tools show up in red, write actions in orange. Makes it easy to scan a long session for the stuff that matters.

Event timeline with expanded details

CLI reference

mcp-audit-proxy — transparent stdio proxy

mcp-audit-proxy --server COMMAND [--log PATH] [--sensitive-tools TOOLS...] [--write-tools TOOLS...]
Flag Default What it does
--server (required) Shell command to start the MCP server
--log audit_log.json Where to write the JSON audit log
--sensitive-tools (none) Space-separated list of tools to flag as sensitive
--write-tools (none) Space-separated list of tools to flag as write actions

mcp-audit-report — HTML report generator

mcp-audit-report --input PATH [--output PATH]
Flag Default What it does
--input audit_log.json Path to the JSON audit log
--output audit_report.html Where to write the HTML report

Python API

Three things are exported from the top-level package:

Export What it is
AuditLogger The core logger class. Create one, call .log() for each message, call .save() when you're done. Thread-safe.
run_proxy(server_command, log_path, ...) Starts a server subprocess and proxies all stdio through the logger. Blocking — runs until the server exits.
generate_report(input_path, output_path, ...) Reads a JSON audit log, writes (or returns) an HTML report.
from mcp_audit_trail import AuditLogger, run_proxy, generate_report

AuditLogger is probably what you want if you're integrating into existing code. run_proxy is more of a "start and forget" wrapper — it's what the CLI uses under the hood.

Try the demo

There's a sample HR server in the repo with fake employee data, pay info, compliance rules, and a PTO system. The demo script runs a bunch of tool calls against it and generates a report.

git clone https://github.com/khushidahi/mcp-audit-trail.git
cd mcp-audit-trail
pip install -e ".[demo]"
python -m examples.run_demo

Then open audit_report.html. The demo covers the main scenarios: regular reads, sensitive data access, write actions, cross-department lookups, and an error case (querying an employee that doesn't exist).

Running tests

pip install -e ".[dev]"
pytest

There are ~55 tests covering the logger, report generator, CLI, and a full integration test that runs real MCP tool calls against the sample server.

Project layout

mcp_audit_trail/
    __init__.py         → public API (AuditLogger, run_proxy, generate_report)
    proxy.py            → the audit logger + stdio proxy
    report.py           → HTML report generator
    cli.py              → CLI entry points
examples/
    sample_server.py    → demo MCP server with HR tools
    run_demo.py         → end-to-end demo script
tests/                  → pytest suite
pyproject.toml          → package config (hatchling)

Known limitations

  • The proxy works over stdio only — no SSE/HTTP transport yet
  • Entity detection is heuristic (looks for id / employee in argument keys). Works well for common patterns but won't catch everything
  • The HTML report is self-contained (no external assets) but it's not designed for logs with thousands of events — it'll work, just gets long
  • No built-in log rotation or multi-session merging

License

MIT — do whatever you want with it.


If you run into issues or have ideas, open an issue. PRs welcome.

Metadata

Release files for mcp-audit-trail 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-audit-trail 0.1.1
File Size Uploaded Provenance Actions
mcp_audit_trail-0.1.1.tar.gz 279.5 kB Without provenance Details for mcp_audit_trail-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for mcp-audit-trail 0.1.1
File Interpreter ABI Platform Actions
mcp_audit_trail-0.1.1-py3-none-any.whl Python 3 none any Details for mcp_audit_trail-0.1.1-py3-none-any.whl

Total release size: 293.7 kB

Release files / mcp_audit_trail-0.1.1.tar.gz

Download URL mcp_audit_trail-0.1.1.tar.gz
Size 279.5 kB
Tags Source
SHA-256 checksum
How to use checksums
07856ce6559f5a3e3f477ee74d072d504c29d4b5971a6f2c0c0af3f4dcf3d919
BLAKE2b-256 checksum
How to use checksums
563ee875e63f07ede270a1f89298e036b3714fa911edcf5de0952e8d345fb662
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.11

Release files / mcp_audit_trail-0.1.1-py3-none-any.whl

Download URL mcp_audit_trail-0.1.1-py3-none-any.whl
Size 14.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2ceaa0bafcf3dfa43d485630126bde13f2c7faba1333dc1ba704bc88c8be7342
BLAKE2b-256 checksum
How to use checksums
6dd18ac45730c348be62470fdf86ceaf4ace1660b706cbc6728ea0332f56c163
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.11

Security for mcp-audit-trail 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page