{
  "markdown": "# audit-ledger-mcp\n\n**Connect Claude, Cursor, LangGraph, or your own agent to the [AI Audit Ledger](https://github.com/shahidh68/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.\n\nIt 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.\n\n[![npm](https://img.shields.io/npm/v/audit-ledger-mcp.svg)](https://www.npmjs.com/package/audit-ledger-mcp) [![License: Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](./LICENSE) [![MCP](https://img.shields.io/badge/MCP-compatible-7c3aed.svg)](https://modelcontextprotocol.io)\n\n> **The AI Audit Ledger family.** This MCP server writes decisions to the\n> [ledger](https://github.com/shahidh68/audit-ledger), which proves what happened\n> and whether the record was changed. The\n> [**AI Decision Evidence Hub**](https://github.com/shahidh68/evidence-hub) sits\n> above the ledger, read-only. It turns each lightweight decision record into an\n> audit case file by showing what evidence is present, what is still missing, who\n> owns each gap, and the current readiness score. Family:\n> [audit-ledger](https://github.com/shahidh68/audit-ledger) · **audit-ledger-mcp** ·\n> [evidence-hub](https://github.com/shahidh68/evidence-hub).\n\n**[Try the live dashboard →](https://d2pfirb2397ixy.cloudfront.net/?demo=1)** &nbsp;&middot;&nbsp; 30 synthetic decisions written via this MCP server, queryable and verifiable.\n\n<p align=\"center\">\n  <img src=\"./demo.gif\" alt=\"LangGraph agents using audit-ledger-mcp — triage, risk, and human-in-the-loop each calling record_decision\" />\n</p>\n\n> A LangGraph workflow calls `record_decision` after each agent step. Three audit events written to the live ledger; every one independently verifiable.\n\n---\n\n## What it does\n\nExposes four tools to any MCP-compatible agent:\n\n| Tool | What it does |\n|---|---|\n| `record_decision`     | Log an AI decision. Hashes inputs locally, then writes through to the ledger. Returns an event ID. |\n| `verify_decision`     | Cross-check a stored record against the immutable S3 Object Lock copy. Returns `integrity_verified: true/false`. |\n| `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?\" |\n| `list_decisions`      | Query recent decisions, optionally filtered by time window. Tenant-scoped by API key. |\n\nEach 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.\n\n---\n\n## Quick start — zero configuration\n\n```bash\nnpx -y audit-ledger-mcp\n```\n\nThat'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.\n\nWhen sandbox mode is active, you'll see a banner on stderr:\n\n```\n[audit-ledger-mcp] ─────────────── SANDBOX MODE ───────────────\n[audit-ledger-mcp] No AUDIT_API_URL configured.\n[audit-ledger-mcp] Using the public sandbox at sandbox-public.\n[audit-ledger-mcp]   View: https://d2pfirb2397ixy.cloudfront.net\n[audit-ledger-mcp] Do NOT write real personal data...\n```\n\n### Sandbox properties\n\n| | |\n|---|---|\n| **Hosted by** | github.com/shahidh68/audit-ledger (same AWS deployment) |\n| **Tenant** | `sandbox-public` (shared, public) |\n| **Rate limit** | 100 requests/minute per IP |\n| **Retention** | 7 years (records cannot be deleted) |\n| **Audience** | Tyre-kickers, integration tests, framework demos |\n| **NOT for** | Production data, customer PII, real compliance records |\n\n### Wire it into Claude Desktop with zero config\n\n```json\n{\n  \"mcpServers\": {\n    \"audit-ledger-sandbox\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"audit-ledger-mcp\"]\n    }\n  }\n}\n```\n\nRestart 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.\n\n---\n\n## Production install\n\nFor real workloads, deploy your own audit ledger and point the MCP server at it:\n\n```bash\nnpm install -g audit-ledger-mcp\n```\n\nConfigure 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:\n\n```bash\nexport AUDIT_API_URL=\"https://<api-id>.execute-api.<region>.amazonaws.com/prod\"\nexport AUDIT_WRITE_KEY=\"<your-tenant-write-key>\"\nexport AUDIT_READ_KEY=\"<your-tenant-read-key>\"\n\n# Strongly recommended. Tenant-held secret used to HMAC PII and prompts\n# locally before sending. Generate once, store next to AUDIT_WRITE_KEY:\n#   node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\"\n# If unset, the MCP falls back to plain SHA-256 and warns once (back-compat).\nexport AUDIT_HMAC_KEY=\"<your-tenant-hmac-secret>\"\n\n# Optional\nexport AUDIT_TIMEOUT_MS=5000        # default 5000\nexport AUDIT_RETRY_ATTEMPTS=3       # default 3\n```\n\nThe full template lives in [`.env.example`](./.env.example).\n\n---\n\n## Wire it into an agent\n\n### Claude Desktop\n\nEdit your `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`, Windows: `%APPDATA%\\Claude\\claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"audit-ledger\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"audit-ledger-mcp\"],\n      \"env\": {\n        \"AUDIT_API_URL\": \"https://<api-id>.execute-api.<region>.amazonaws.com/prod\",\n        \"AUDIT_WRITE_KEY\": \"<your-tenant-write-key>\",\n        \"AUDIT_READ_KEY\": \"<your-tenant-read-key>\",\n        \"AUDIT_HMAC_KEY\": \"<your-tenant-hmac-secret>\"\n      }\n    }\n  }\n}\n```\n\n`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.\n\nRestart 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.\n\n### Cursor\n\nIn Cursor settings → MCP → add server:\n\n```json\n{\n  \"mcpServers\": {\n    \"audit-ledger\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"audit-ledger-mcp\"],\n      \"env\": {\n        \"AUDIT_API_URL\": \"https://<api-id>.execute-api.<region>.amazonaws.com/prod\",\n        \"AUDIT_WRITE_KEY\": \"<your-tenant-write-key>\",\n        \"AUDIT_READ_KEY\": \"<your-tenant-read-key>\",\n        \"AUDIT_HMAC_KEY\": \"<your-tenant-hmac-secret>\"\n      }\n    }\n  }\n}\n```\n\n### LangGraph (Python)\n\nUsing [`langchain-mcp-adapters`](https://github.com/langchain-ai/langchain-mcp-adapters):\n\n```python\nfrom langchain_mcp_adapters.client import MultiServerMCPClient\nfrom langgraph.prebuilt import create_react_agent\nfrom langchain_anthropic import ChatAnthropic\nimport os\n\nclient = MultiServerMCPClient({\n    \"audit-ledger\": {\n        \"command\": \"npx\",\n        \"args\": [\"-y\", \"audit-ledger-mcp\"],\n        \"transport\": \"stdio\",\n        \"env\": {\n            \"AUDIT_API_URL\":   os.environ[\"AUDIT_API_URL\"],\n            \"AUDIT_WRITE_KEY\": os.environ[\"AUDIT_WRITE_KEY\"],\n            \"AUDIT_READ_KEY\":  os.environ[\"AUDIT_READ_KEY\"],\n            \"AUDIT_HMAC_KEY\":  os.environ[\"AUDIT_HMAC_KEY\"],\n        },\n    }\n})\n\ntools = await client.get_tools()\nagent = create_react_agent(\n    ChatAnthropic(model=\"claude-sonnet-4-7-20251022\"),\n    tools,\n)\n\n# The agent can now call record_decision, verify_decision, verify_completeness, list_decisions\nresult = await agent.ainvoke({\n    \"messages\": [{\"role\": \"user\", \"content\": \"Triage this loan application…\"}]\n})\n```\n\n### Custom client (raw MCP)\n\n```bash\nAUDIT_API_URL=... AUDIT_WRITE_KEY=... AUDIT_READ_KEY=... AUDIT_HMAC_KEY=... npx -y audit-ledger-mcp\n```\n\nThe server speaks MCP over stdio. Send `initialize`, `tools/list`, and `tools/call` requests per the [MCP specification](https://modelcontextprotocol.io/specification).\n\n---\n\n## How a `record_decision` call flows\n\n```\nAgent                  audit-ledger-mcp                  AWS (your ledger)\n  |                          |                                 |\n  |--- record_decision ----->|                                 |\n  |   raw_user_input         | (hash locally — no PII over     |\n  |   raw_system_prompt      |  the wire from this point)      |\n  |   decision_output        |                                 |\n  |   human_in_loop          |                                 |\n  |                          |--- HTTPS POST /audit/events --->|\n  |                          |    {hashes + decision +         |\n  |                          |     x-api-key}                  |\n  |                          |                                 |\n  |                          |<--- 202 Accepted ---------------|\n  |                          |    { event_id, ... }            |\n  |<--- event_id ------------|                                 |\n  |     recorded_at          |                                 |\n  |     note                 |                                 |\n```\n\nStorage on the AWS side happens asynchronously through SQS → Processor Lambda → DynamoDB + S3 Object Lock. See the [main repo's ARCHITECTURE.md](https://github.com/shahidh68/audit-ledger/blob/main/ARCHITECTURE.md) for the full path.\n\n---\n\n## Tool reference\n\n### `record_decision`\n\nRecord an AI decision to the ledger.\n\n| Parameter | Type | Required | Notes |\n|---|---|---|---|\n| `model_version` | string | Yes | e.g. `\"claude-sonnet-4-7-20251022\"` |\n| `raw_system_prompt` | string | Yes | Hashed locally |\n| `raw_user_input` | string | Yes | Hashed locally |\n| `ai_decision_output` | object | Yes | Stored verbatim — must not contain raw PII |\n| `human_in_loop` | boolean | Yes | Critical for EU AI Act Article 14 |\n| `event_id` | uuid v4 | No | Auto-generated if omitted |\n| `timestamp` | ISO 8601 | No | Defaults to now |\n\n### `verify_decision`\n\nTamper-check a stored record.\n\n| Parameter | Type | Required | Notes |\n|---|---|---|---|\n| `event_id` | uuid v4 | Yes | The ID of the record to verify |\n\nReturns the DynamoDB record, the S3 record, and `integrity_verified: true/false`.\n\n### `verify_completeness`\n\nDetect 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.\n\n| Parameter   | Type    | Required | Notes |\n|---|---|---|---|\n| `from`      | integer | No       | Inclusive lower bound on sequence_no. Defaults to 1. |\n| `to`        | integer | No       | Inclusive upper bound on sequence_no. Defaults to the tenant's current counter. |\n| `tenant_id` | string  | No       | Required only with the admin read key; ignored otherwise. |\n\nReturns the requested range, the expected vs found count, the list of missing sequence numbers, and a human-readable note.\n\n```json\n{\n  \"tenant_id\": \"acme-prod\",\n  \"range\": { \"from\": 1, \"to\": 142 },\n  \"expected_count\": 142,\n  \"found_count\": 140,\n  \"missing\": [47, 91],\n  \"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.\"\n}\n```\n\n### `list_decisions`\n\nList recent decisions for the calling tenant.\n\n| Parameter | Type | Required | Notes |\n|---|---|---|---|\n| `from` | ISO 8601 | No | Defaults to 7 days ago |\n| `to` | ISO 8601 | No | Defaults to now |\n| `limit` | integer 1–500 | No | Defaults to 100 |\n\n---\n\n## Security\n\n- **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.\n- **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.\n- **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.\n- **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.\n\n---\n\n## What this is not\n\n- **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.\n- **Not a substitute for a model risk audit.** It records what the AI did, not whether it was right.\n- **Not a bias or fairness testing tool.** It is the audit layer underneath whatever testing you already do.\n\n---\n\n## Companion: AI Decision Evidence Hub\n\nThis MCP server **writes** decisions to the ledger — the immutable record of *what\nhappened*. The **[AI Decision Evidence Hub](https://github.com/shahidh68/evidence-hub)**\nis the read-only workbench above the ledger. It answers the next question an\nauditor asks: *the decision is recorded, but is the evidence complete enough to\nreview?*\n\nFor every recorded decision it produces:\n\n- an **audit-readiness score (0–100)** across nine evidence categories (model, data,\n  policy, human review, monitoring, prompt, integrity, retention, decision);\n- exactly **what evidence is present vs missing**, and **who owns** each expected\n  gap;\n- a per-decision **audit pack** that can be printed, saved as PDF, or downloaded\n  as JSON;\n- a dashboard (cross-linked with the ledger's), plus a manifest-based resolver that\n  auto-fills static evidence.\n\nOpen gaps are normal. The ledger keeps the decision record small and\ntamper-evident; Evidence Hub shows the follow-up evidence needed to make that\ndecision audit-ready. It reads the ledger over its API and never modifies a\nrecord. Serverless on AWS (Lambda + DynamoDB). See its\n[Customer Guide](https://github.com/shahidh68/evidence-hub/blob/master/docs/CUSTOMER-GUIDE.md)\nand [Admin Runbook](https://github.com/shahidh68/evidence-hub/blob/master/docs/ADMIN-RUNBOOK.md).\n\n**The family:** [audit-ledger](https://github.com/shahidh68/audit-ledger) (what happened) ·\n**audit-ledger-mcp** (this server — how agents write decisions) ·\n[evidence-hub](https://github.com/shahidh68/evidence-hub) (audit-readiness).\n\n---\n\n## Development\n\n```bash\ngit clone https://github.com/shahidh68/audit-ledger-mcp.git\ncd audit-ledger-mcp\nnpm install\nnpm run build\nnpm test\n```\n\nThe server is TypeScript on Node 20+, ESM, stdio transport, using `@modelcontextprotocol/sdk`.\n\n---\n\n## Related\n\n- **[shahidh68/audit-ledger](https://github.com/shahidh68/audit-ledger)** — the AWS infrastructure this server talks to. CDK stack, Python and Node SDKs, compliance dashboard, full architecture documentation.\n- **[shahidh68/evidence-hub](https://github.com/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](https://github.com/shahidh68/evidence-hub/blob/master/docs/CUSTOMER-GUIDE.md) · [Admin Runbook](https://github.com/shahidh68/evidence-hub/blob/master/docs/ADMIN-RUNBOOK.md))\n\n---\n\n## License\n\nApache License 2.0 — see [LICENSE](./LICENSE).\n\nThe patent grant is intentional. Compliance infrastructure sits adjacent to enterprise legal review and the explicit grant matters there.\n\n---\n\n## Author\n\nBuilt by [Shahid](https://github.com/shahidh68). Available for Principal AI Engineering and Head of AI Engineering roles, and fractional advisory engagements, in UK regulated fintech.\n",
  "bytes": 16456,
  "sha": "64ee8c9c3debec9823a2d5c89d6da459d905959ec4edb6bb5cfd9d18c1561be2",
  "repo_slug": "shahidh68/audit-ledger-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_shahidh68_audit_ledger_mcp_d1ae5754/readme"
}