audit event mcp
@kajaril/audit-event-mcp
Agent steward infrastructure — hash-chained audit log with Merkle notarisation and a GDPR/AI-Act compliance skill.
What it does
Records agent events (tool calls, decisions, human turns) to a per-client SQLite log with a SHA-256 hash chain — every record is cryptographically linked to the previous one
Optionally notarises batches with a Merkle root + Ed25519 signature (paid tier) — external auditors can verify without contacting kajaril
Exports all events for a data subject as NDJSON on demand (GDPR Art. 20 portability)
Ships a Claude Code skill that runs 8 GDPR/AI-Act axes against any event store
MCP endpoint
https://audit-event.kajaril.com/mcpJSON-RPC 2.0 over HTTPS, authenticated via Cloudflare Access. Contact studio@kajaril.com for a service token.
Tools
Tool | Description |
| Write one audit event. Returns |
| Recompute |
| Filter by session, agent, event type, or date range. |
| Export all events for a |
Quick start
Record an event:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "record_event",
"arguments": {
"eventType": "tool.call",
"purpose": "User requested flight search via travel assistant",
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
"input": { "tool": "search_flights", "origin": "LHR", "dest": "JFK" },
"lawfulBasis": "contract",
"subjectId": "user-8821"
}
}
}Verify the chain:
{ "jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": { "name": "verify_chain", "arguments": { "limit": 100 } } }Export a data subject's records:
{ "jsonrpc": "2.0", "id": 3, "method": "tools/call",
"params": { "name": "export_dossier", "arguments": { "subjectId": "user-8821" } } }How it works
Hash chain
Every event commits to all events before it. The chain is recomputable from first principles:
input_hash_slot = input_hash ?? input_hash_omitted_reason
chain_hash = SHA-256(id + "|" + event_type + "|" + input_hash_slot + "|" + prev_hash)When a caller supplies inputHashOmittedReason instead of input, the reason string enters the chain — the omission itself is tamper-evident.
Merkle notary (paid tier)
Every 15 minutes (or at 1,000 pending events), the notary Worker:
Collects
{ id, chain_hash }pairs from pending recordsSorts them by id and builds a SHA-256 binary Merkle tree
Signs the root with Ed25519
Writes
merkle_root+notary_sigback to each record
The notary public key is published at /.well-known/notary-pubkey. Any auditor can verify signatures offline without contacting kajaril. The notary never receives input_hash, payload_ref, or any payload content.
Privacy design
inputis hashed locally; the raw value is not stored unless an R2 bucket is explicitly boundinput_hashis excluded from allquery_eventsandexport_dossierresponsespayload_refis never returned to callers — enforced at every handler boundaryAn empty
export_dossierresult (eventCount: 0) is valid GDPR evidence that no data exists for a subject
Event types
tool.call | tool.result | decision.made |
human.turn | memory.read | memory.write | error.raisedLawful basis (GDPR Art. 6)
legitimate_interest | contract | legal_obligation |
vital_interest | public_task | consentProvide lawfulBasis for any event that processes personal data. Omit it for events that do not.
Tiers
Capability | Free | Paid |
Hash-chained event writes | yes | yes |
| yes | yes |
| yes | yes |
R2 payload storage | optional | optional |
Merkle root + Ed25519 notarisation | — | yes |
compliance-audit axis 6 (notary coverage) | skipped | evaluated |
compliance-audit skill
skills/compliance-audit/SKILL.md is a Claude Code skill that runs 8 GDPR/AI-Act compliance axes against any event store. Copy it into your workspace:
cp -r node_modules/@kajaril/audit-event-mcp/skills/compliance-audit .claude/skills/Axes:
Lawful basis present — GDPR Art. 5–6
Purpose specificity — GDPR Art. 5(1)(b)
Subject linkage on
human.turneventsRetention bounded (≤ 730 days)
Chain integrity — 10% sample recompute
Notary coverage ≥ 95% (paid tier only)
High-risk event completeness — AI Act Art. 12–13
Data minimisation signal —
payload_reffraction
Each axis produces pass | fail | warn with an evidence snippet. Output is JSON + a markdown summary block.
Self-hosted deployment
Prerequisites
Cloudflare account with Workers and Durable Objects enabled
wranglerCLI authenticated
Steps
# 1. Create R2 bucket
wrangler r2 bucket create audit-payloads
# 2. Set notary signing key (paid tier)
wrangler secret put NOTARY_PRIVATE_KEY --config wrangler.notary.jsonc
# Value: hex-encoded Ed25519 private key — never committed to source
# 3. Deploy Workers
wrangler deploy
wrangler deploy --config wrangler.notary.jsonc
# 4. Add audit-event.kajaril.com as a CF Access Self-hosted Application
# Issue one service token per client with custom.client_id claim
# 5. Onboard a client
npx tsx src/scripts/onboard-client.ts --client-id acme-crm --tier free --region eu
# 6. Verify
curl https://audit-event.kajaril.com/healthNever run wrangler deploy from a dirty working tree. The deployed code must match git HEAD.
Development
npm install
npm test # 81 tests (node:sqlite adapter, no cloudflare/vitest-pool-workers)
npm run typecheck
npm run lintLicense
MIT. Copyright © 2026 Kajaril Ltd.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mightbesaad/audit-event-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server