Skip to main content
Glama
shahidh68

audit-ledger-mcp

by shahidh68

audit-ledger-mcp

Connect Claude, Cursor, LangGraph, or your own agent to the AI Audit Ledger. This MCP server gives an agent the tools to record, check, and list decisions in a tamper-evident log with one line of config.

It is built for teams that need a clear record of AI decisions: EU AI Act Article 12 logging, FCA SS1/23 model risk evidence, and GDPR data minimisation. Raw personal data is hashed locally before anything is sent, so the ledger only sees fingerprints.

npm License: Apache 2.0 MCP

The AI Audit Ledger family. This MCP server writes decisions to the ledger, which proves what happened and whether the record was changed. The AI Decision Evidence Hub sits above the ledger, read-only. It turns each lightweight decision record into an audit case file by showing what evidence is present, what is still missing, who owns each gap, and the current readiness score. Family: audit-ledger · audit-ledger-mcp · evidence-hub.

Try the live dashboard →  ·  30 synthetic decisions written via this MCP server, queryable and verifiable.

A LangGraph workflow calls record_decision after each agent step. Three audit events written to the live ledger; every one independently verifiable.


What it does

Exposes four tools to any MCP-compatible agent:

Tool

What it does

record_decision

Log an AI decision. Hashes inputs locally, then writes through to the ledger. Returns an event ID.

verify_decision

Cross-check a stored record against the immutable S3 Object Lock copy. Returns integrity_verified: true/false.

verify_completeness

Detect deleted or missing records. Compares the ledger's per-tenant counter against the rows actually present and returns any sequence numbers that are gone. The answer to "can you prove the log is complete?"

list_decisions

Query recent decisions, optionally filtered by time window. Tenant-scoped by API key.

Each call ends up as a regulator-grade audit record in your deployed ledger — DynamoDB for query, S3 Object Lock COMPLIANCE mode for the immutable copy, 7-year retention by default.


Related MCP server: sigmodx-mcp

Quick start — zero configuration

npx -y audit-ledger-mcp

That's it. With no environment variables, the server boots into sandbox mode and writes records to a shared public tenant on a hosted ledger. You can try every tool — record_decision, verify_decision, verify_completeness, list_decisions — without provisioning anything.

When sandbox mode is active, you'll see a banner on stderr:

[audit-ledger-mcp] ─────────────── SANDBOX MODE ───────────────
[audit-ledger-mcp] No AUDIT_API_URL configured.
[audit-ledger-mcp] Using the public sandbox at sandbox-public.
[audit-ledger-mcp]   View: https://d2pfirb2397ixy.cloudfront.net
[audit-ledger-mcp] Do NOT write real personal data...

Sandbox properties

Hosted by

github.com/shahidh68/audit-ledger (same AWS deployment)

Tenant

sandbox-public (shared, public)

Rate limit

100 requests/minute per IP

Retention

7 years (records cannot be deleted)

Audience

Tyre-kickers, integration tests, framework demos

NOT for

Production data, customer PII, real compliance records

Wire it into Claude Desktop with zero config

{
  "mcpServers": {
    "audit-ledger-sandbox": {
      "command": "npx",
      "args": ["-y", "audit-ledger-mcp"]
    }
  }
}

Restart Claude Desktop. The four tools appear in the MCP menu immediately. Try asking Claude to "record this decision: should X be approved?" and watch a record land in the sandbox dashboard.


Production install

For real workloads, deploy your own audit ledger and point the MCP server at it:

npm install -g audit-ledger-mcp

Configure with the API URL plus your tenant keys (any of them being set switches off sandbox mode). AUDIT_HMAC_KEY is technically optional for backwards compatibility but strongly recommended — see the note above the value below:

export AUDIT_API_URL="https://<api-id>.execute-api.<region>.amazonaws.com/prod"
export AUDIT_WRITE_KEY="<your-tenant-write-key>"
export AUDIT_READ_KEY="<your-tenant-read-key>"

# Strongly recommended. Tenant-held secret used to HMAC PII and prompts
# locally before sending. Generate once, store next to AUDIT_WRITE_KEY:
#   node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# If unset, the MCP falls back to plain SHA-256 and warns once (back-compat).
export AUDIT_HMAC_KEY="<your-tenant-hmac-secret>"

# Optional
export AUDIT_TIMEOUT_MS=5000        # default 5000
export AUDIT_RETRY_ATTEMPTS=3       # default 3

The full template lives in .env.example.


Wire it into an agent

Claude Desktop

Edit your claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json, Windows: %APPDATA%\Claude\claude_desktop_config.json):

{
  "mcpServers": {
    "audit-ledger": {
      "command": "npx",
      "args": ["-y", "audit-ledger-mcp"],
      "env": {
        "AUDIT_API_URL": "https://<api-id>.execute-api.<region>.amazonaws.com/prod",
        "AUDIT_WRITE_KEY": "<your-tenant-write-key>",
        "AUDIT_READ_KEY": "<your-tenant-read-key>",
        "AUDIT_HMAC_KEY": "<your-tenant-hmac-secret>"
      }
    }
  }
}

AUDIT_HMAC_KEY is the tenant secret used to keyed-hash PII locally before any payload leaves the MCP server process. Generate it once with node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" and store the result in the env block above. The MCP never transmits this value, only reads it.

Restart Claude Desktop. You'll see "audit-ledger" in the MCP tools menu. Ask Claude something like "Record this decision: I declined the application because…" and watch it call record_decision automatically.

Cursor

In Cursor settings → MCP → add server:

{
  "mcpServers": {
    "audit-ledger": {
      "command": "npx",
      "args": ["-y", "audit-ledger-mcp"],
      "env": {
        "AUDIT_API_URL": "https://<api-id>.execute-api.<region>.amazonaws.com/prod",
        "AUDIT_WRITE_KEY": "<your-tenant-write-key>",
        "AUDIT_READ_KEY": "<your-tenant-read-key>",
        "AUDIT_HMAC_KEY": "<your-tenant-hmac-secret>"
      }
    }
  }
}

LangGraph (Python)

Using langchain-mcp-adapters:

from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic
import os

client = MultiServerMCPClient({
    "audit-ledger": {
        "command": "npx",
        "args": ["-y", "audit-ledger-mcp"],
        "transport": "stdio",
        "env": {
            "AUDIT_API_URL":   os.environ["AUDIT_API_URL"],
            "AUDIT_WRITE_KEY": os.environ["AUDIT_WRITE_KEY"],
            "AUDIT_READ_KEY":  os.environ["AUDIT_READ_KEY"],
            "AUDIT_HMAC_KEY":  os.environ["AUDIT_HMAC_KEY"],
        },
    }
})

tools = await client.get_tools()
agent = create_react_agent(
    ChatAnthropic(model="claude-sonnet-4-7-20251022"),
    tools,
)

# The agent can now call record_decision, verify_decision, verify_completeness, list_decisions
result = await agent.ainvoke({
    "messages": [{"role": "user", "content": "Triage this loan application…"}]
})

Custom client (raw MCP)

AUDIT_API_URL=... AUDIT_WRITE_KEY=... AUDIT_READ_KEY=... AUDIT_HMAC_KEY=... npx -y audit-ledger-mcp

The server speaks MCP over stdio. Send initialize, tools/list, and tools/call requests per the MCP specification.


How a record_decision call flows

Agent                  audit-ledger-mcp                  AWS (your ledger)
  |                          |                                 |
  |--- record_decision ----->|                                 |
  |   raw_user_input         | (hash locally — no PII over     |
  |   raw_system_prompt      |  the wire from this point)      |
  |   decision_output        |                                 |
  |   human_in_loop          |                                 |
  |                          |--- HTTPS POST /audit/events --->|
  |                          |    {hashes + decision +         |
  |                          |     x-api-key}                  |
  |                          |                                 |
  |                          |<--- 202 Accepted ---------------|
  |                          |    { event_id, ... }            |
  |<--- event_id ------------|                                 |
  |     recorded_at          |                                 |
  |     note                 |                                 |

Storage on the AWS side happens asynchronously through SQS → Processor Lambda → DynamoDB + S3 Object Lock. See the main repo's ARCHITECTURE.md for the full path.


Tool reference

record_decision

Record an AI decision to the ledger.

Parameter

Type

Required

Notes

model_version

string

Yes

e.g. "claude-sonnet-4-7-20251022"

raw_system_prompt

string

Yes

Hashed locally

raw_user_input

string

Yes

Hashed locally

ai_decision_output

object

Yes

Stored verbatim — must not contain raw PII

human_in_loop

boolean

Yes

Critical for EU AI Act Article 14

event_id

uuid v4

No

Auto-generated if omitted

timestamp

ISO 8601

No

Defaults to now

verify_decision

Tamper-check a stored record.

Parameter

Type

Required

Notes

event_id

uuid v4

Yes

The ID of the record to verify

Returns the DynamoDB record, the S3 record, and integrity_verified: true/false.

verify_completeness

Detect missing records. Sister tool to verify_decision: that one proves a record that exists has not been altered; this one proves no records have been deleted.

Parameter

Type

Required

Notes

from

integer

No

Inclusive lower bound on sequence_no. Defaults to 1.

to

integer

No

Inclusive upper bound on sequence_no. Defaults to the tenant's current counter.

tenant_id

string

No

Required only with the admin read key; ignored otherwise.

Returns the requested range, the expected vs found count, the list of missing sequence numbers, and a human-readable note.

{
  "tenant_id": "acme-prod",
  "range": { "from": 1, "to": 142 },
  "expected_count": 142,
  "found_count": 140,
  "missing": [47, 91],
  "note": "Found 2 missing sequence number(s) in range. Each gap represents a deleted, lost, or never-written record. Cross-check against burned_sequence log entries before treating as a deletion."
}

list_decisions

List recent decisions for the calling tenant.

Parameter

Type

Required

Notes

from

ISO 8601

No

Defaults to 7 days ago

to

ISO 8601

No

Defaults to now

limit

integer 1–500

No

Defaults to 100


Security

  • PII hashing happens in this process, not in the ledger. HMAC-SHA256 over UTF-8, keyed off the AUDIT_HMAC_KEY you set in your environment. The key never leaves your process; only the 64-char hex digest is sent. Plain SHA-256 of low-entropy values (names, emails) is brute-forceable in seconds and under ICO/EDPB guidance still counts as personal data, which is why the keyed version is the default for new installs. For backwards compatibility, if AUDIT_HMAC_KEY is unset the MCP falls back to plain SHA-256 and logs a one-time deprecation warning on stderr; existing setups keep working unchanged.

  • API keys are never logged. They come from environment variables, are passed in the x-api-key header, and are never echoed back to the agent or written to disk.

  • Two key namespaces. Write keys cannot read; read keys cannot write. A leaked write key cannot exfiltrate data; a leaked read key cannot plant fake records.

  • Errors are propagated with HTTP status passthrough. Rate limit, invalid key, and validation errors surface to the agent so it can react appropriately rather than retry blindly.


What this is not

  • Not legal advice. This is infrastructure that produces audit evidence. Whether that evidence satisfies any specific regulatory obligation is a question for your legal team.

  • Not a substitute for a model risk audit. It records what the AI did, not whether it was right.

  • Not a bias or fairness testing tool. It is the audit layer underneath whatever testing you already do.


Companion: AI Decision Evidence Hub

This MCP server writes decisions to the ledger — the immutable record of what happened. The AI Decision Evidence Hub is the read-only workbench above the ledger. It answers the next question an auditor asks: the decision is recorded, but is the evidence complete enough to review?

For every recorded decision it produces:

  • an audit-readiness score (0–100) across nine evidence categories (model, data, policy, human review, monitoring, prompt, integrity, retention, decision);

  • exactly what evidence is present vs missing, and who owns each expected gap;

  • a per-decision audit pack that can be printed, saved as PDF, or downloaded as JSON;

  • a dashboard (cross-linked with the ledger's), plus a manifest-based resolver that auto-fills static evidence.

Open gaps are normal. The ledger keeps the decision record small and tamper-evident; Evidence Hub shows the follow-up evidence needed to make that decision audit-ready. It reads the ledger over its API and never modifies a record. Serverless on AWS (Lambda + DynamoDB). See its Customer Guide and Admin Runbook.

The family: audit-ledger (what happened) · audit-ledger-mcp (this server — how agents write decisions) · evidence-hub (audit-readiness).


Development

git clone https://github.com/shahidh68/audit-ledger-mcp.git
cd audit-ledger-mcp
npm install
npm run build
npm test

The server is TypeScript on Node 20+, ESM, stdio transport, using @modelcontextprotocol/sdk.


  • shahidh68/audit-ledger — the AWS infrastructure this server talks to. CDK stack, Python and Node SDKs, compliance dashboard, full architecture documentation.

  • shahidh68/evidence-hub — the audit workbench above the ledger. It scores each decision's evidence, treats open gaps as expected follow-up work, and generates printable/downloadable audit packs. (Customer Guide · Admin Runbook)


License

Apache License 2.0 — see LICENSE.

The patent grant is intentional. Compliance infrastructure sits adjacent to enterprise legal review and the explicit grant matters there.


Author

Built by Shahid. Available for Principal AI Engineering and Head of AI Engineering roles, and fractional advisory engagements, in UK regulated fintech.

Available Tools

3 tools
list_decisionsA

List recorded AI decisions for the calling tenant within a time window. Returns newest first. The read key scopes the result to the caller's tenant — cross-tenant reads require an admin read key. Use this for compliance review, audit prep, or agent self-inspection of recent activity.

ParametersJSON Schema
NameRequiredDescriptionDefault
fromNoISO 8601 start of the time window (inclusive). Defaults to 7 days before now.
toNoISO 8601 end of the time window (inclusive). Defaults to now.
limitNoMaximum number of records to return (default 100, max 500). Returned newest-first.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It describes scoping via read key, default time window (7 days), and sort order (newest first). However, it lacks detail on the exact return fields or behavior under errors, which slightly reduces transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences long, front-loads the main purpose, and includes no redundant information. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 3 optional parameters, 100% schema coverage, and no output schema, the description covers the purpose, ordering, and tenant scoping well. It could be improved by mentioning the main fields in each decision record, but overall it is sufficiently complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description does not add additional meaning beyond what the schema already provides for parameters 'from', 'to', and 'limit'. No extra context about defaults or constraints beyond schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists AI decisions for the calling tenant within a time window, returned newest first. It distinguishes itself from siblings (record_decision, verify_decision) through its focus on listing, compliance, and audit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly mentions use cases: compliance review, audit prep, or agent self-inspection. It also notes that cross-tenant reads require an admin read key. While it doesn't explicitly say when not to use, the context of siblings and clear purpose provides adequate guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

record_decisionA

Record an AI decision to the audit ledger. Stores model version, hashed inputs, structured output, and human-review flag. The record is immutably sealed in S3 Object Lock for 7 years and queryable for the lifetime of the decision. Use this immediately after any AI decision that may need to be audited later — credit, hiring, fraud, customer routing, content moderation.

ParametersJSON Schema
NameRequiredDescriptionDefault
model_versionYesThe model and version that produced the decision (e.g. 'claude-sonnet-4.7', 'gpt-4o-2024-08-06'). Required for traceability and model risk audits.
raw_system_promptYesThe system prompt used. Hashed locally before transit — the raw text never leaves this MCP server.
raw_user_inputYesThe user input the model decided on (CV text, transaction, customer message, etc.). Hashed locally before transit — raw PII never leaves this MCP server.
ai_decision_outputYesThe structured decision the model produced. Stored verbatim. Should NOT contain raw PII — only the decision itself (score, classification, recommendation, reasoning summary).
human_in_loopYesWhether a human reviewed or approved this decision before it took effect. Critical for EU AI Act Article 14 (human oversight) compliance.
event_idNoOptional UUID v4 to identify this decision. Auto-generated if omitted. Useful when the calling system already has its own decision ID.
timestampNoOptional ISO 8601 timestamp of when the decision was made. Defaults to the current time. Use this only if recording a backfilled decision.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description reveals key behaviors: the record is immutably sealed in S3 Object Lock for 7 years, queryable for lifetime, and that raw inputs are hashed locally before transit (the raw text never leaves the server). It also warns that ai_decision_output should not contain raw PII.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences cover purpose, key features, and usage guidance. No wasted words; every sentence adds value. Front-loaded with the main action.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description provides substantial context: data handling, retention, compliance, and typical use cases. It does not explicitly describe the return value, but the focus on audit trail and immutability implies a confirmation or ID. Overall, nearly complete for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema already covers all parameters with detailed descriptions. The main description adds context like 'hashed locally' for raw inputs and mentions EU AI Act relevance for human_in_loop, which goes beyond the schema. Baseline 3 with extra value gives a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb (Record) and resource (AI decision to the audit ledger), and it lists what is stored. It also implicitly distinguishes from siblings list_decisions and verify_decision by focusing on writing rather than reading or verifying.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use: immediately after any AI decision that may need auditing (credit, hiring, etc.). Does not mention when not to use or alternatives, but the sibling tools are for different purposes, so guidance is clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

verify_decisionA

Verify a recorded AI decision has not been altered since it was written. The ledger fetches the queryable copy (DynamoDB) and the immutable copy (S3 Object Lock COMPLIANCE mode) independently and compares them. Returns integrity_verified=true if they match. Use this to satisfy a regulator request or to prove an audit trail to a compliance team.

ParametersJSON Schema
NameRequiredDescriptionDefault
event_idYesThe UUID v4 event ID of the decision to verify.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Describes the internal process: fetching from DynamoDB and S3 Object Lock COMPLIANCE mode and comparing them. Explains the return indicator 'integrity_verified=true'. No annotations provided, so description carries full burden and does it well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the purpose, no redundant information. Every word adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one parameter and no output schema, the description explains the verification process and return value. It implicitly covers what the agent needs to know. Could explicitly mention the output structure, but not necessary given the simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter event_id is fully described in the schema (100% coverage). The description does not add additional meaning beyond what the schema already provides, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'verify' and the resource 'recorded AI decision'. It distinguishes from siblings by specifying the verification of integrity, whereas sibling tools list or record decisions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states usage contexts: 'satisfy a regulator request' or 'prove an audit trail'. No explicit when-not-to-use, but the use cases are well-defined and imply not for other purposes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.5/5.0
Disambiguation5/5

Each tool has a distinct and clear purpose: listing decisions, recording new decisions, and verifying integrity. No functional overlap.

Naming Consistency5/5

All tool names follow a strict verb_noun pattern (list_decisions, record_decision, verify_decision), with consistent snake_case and action-object ordering.

Tool Count5/5

Three tools perfectly cover the core audit ledger operations: create, read, and verify. The count is minimal yet complete for the domain.

Completeness5/5

The toolset covers the essential lifecycle of audit records: recording, listing, and verification. Update and delete are intentionally omitted to preserve immutability, so no gaps.

Maintenance

ActivityInactive
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Audit infrastructure for AI agents to log consequential decisions (invoice, GL, anomaly) and verify attestations via MCP tools.
    6
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    A governance-layer MCP server that gates AI writes to systems of record, requiring human signatures and providing a tamper-evident audit trail. It offers read, propose, approve, commit, and audit tools, with demo and Xero backends.
    25
    MIT

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/shahidh68/audit-ledger-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server