<div align="center">

```
     ╔══════════════════════════════════════════════════════════╗
     ║                                                          ║
     ║     █████╗ ████████╗████████╗███████╗███████╗████████╗   ║
     ║    ██╔══██╗╚══██╔══╝╚══██╔══╝██╔════╝██╔════╝╚══██╔══╝  ║
     ║    ███████║   ██║      ██║   █████╗  ███████╗   ██║     ║
     ║    ██╔══██║   ██║      ██║   ██╔══╝  ╚════██║   ██║     ║
     ║    ██║  ██║   ██║      ██║   ███████╗███████║   ██║     ║
     ║    ╚═╝  ╚═╝   ╚═╝      ╚═╝   ╚══════╝╚══════╝   ╚═╝     ║
     ║                    ███╗   ███╗ ██████╗██████╗              ║
     ║                    ████╗ ████║██╔════╝██╔══██╗             ║
     ║                    ██╔████╔██║██║     ██████╔╝             ║
     ║                    ██║╚██╔╝██║██║     ██╔═══╝              ║
     ║                    ██║ ╚═╝ ██║╚██████╗██║                  ║
     ║                    ╚═╝     ╚═╝ ╚═════╝╚═╝                  ║
     ║                                                          ║
     ╚══════════════════════════════════════════════════════════╝
```

**Continuous compliance evidence for AI agent memory.**

*Your agents remember everything. Now prove it.*

[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
[![Python](https://img.shields.io/badge/python-3.12%2B-blue.svg)](https://www.python.org/downloads/)
[![Tests](https://img.shields.io/badge/tests-107%20passed-brightgreen.svg)](#development)
[![SOC 2](https://img.shields.io/badge/SOC%202-CC6.1%20%7C%20CC6.3%20%7C%20CC7.2%20%7C%20CC8.1-purple.svg)](#soc-2-control-mapping)

</div>

---

```
                    ┌─────────────────────┐
                    │                     │
  Agent Client ────▶│   AttestMCP Proxy   │────▶ Memory Server
                    │                     │      (Mem0, Zep,
  ◀── response ◀───│  ┌───────────────┐  │◀──   Anthropic KG,
      unchanged     │  │  🔐 Identity  │  │      Hindsight...)
                    │  │  📋 Policy    │  │
                    │  │  🔗 Evidence  │  │
                    │  └───────┬───────┘  │
                    │          │          │
                    │    ┌─────▼─────┐    │
                    │    │  Audit DB │    │
                    │    │  SHA-256  │    │
                    │    │  chained  │    │
                    │    └───────────┘    │
                    └─────────────────────┘
```

## The Problem

AI agent memory servers store what agents know. **None of them can prove what agents *did* with that knowledge.** Without audit trails:

```
  ❌  No SOC 2 attestation for agent behavior
  ❌  Enterprise deals blocked at security review
  ❌  No answer when auditors ask "who accessed what, when?"
  ❌  Cyber insurance carriers want documented AI controls
```

## What AttestMCP Does

```
  ✅  Zero modification     Agents and memory servers work exactly as before
  ✅  Identity attribution  Every operation tied to a verified agent/user
  ✅  Hash-chained evidence Tamper-evident records detect any modification
  ✅  SOC 2 mapping         Evidence mapped to CC6.1 / CC6.3 / CC7.2 / CC8.1
  ✅  HTML reports          Self-contained evidence you hand to an auditor
  ✅  Any MCP memory server Mem0, Anthropic KG, Zep, Hindsight, any
```

## Quick Start

### pip

```bash
pip install attestmcp

# Point to your memory server
export ATTESTMCP_UPSTREAM_URL="http://localhost:8000/mcp"

# Start the proxy
attestmcp serve
```

### Docker

```bash
docker run -d \
  -e ATTESTMCP_UPSTREAM_URL="http://host.docker.internal:8000/mcp" \
  -v attestmcp-data:/data \
  -p 8080:8080 \
  attestmcp/proxy
```

Then point your agent's MCP config to the proxy instead of the memory server directly.

## How It Works

Every MCP JSON-RPC call through the proxy generates a tamper-evident audit record:

```json
{
  "record_id": "0192e4a1-7b3c-7def-8a12-4f6789abcdef",
  "timestamp": "2026-04-15T14:32:01.847392+00:00",
  "agent_identity": {
    "source": "oauth_jwt",
    "user": "deploy-bot@acme.com",
    "agent_name": "support-agent-v2",
    "org": "acme-corp",
    "verified": true,
    "trust_level": "verified"
  },
  "method": "tools/call",
  "tool_name": "search_memories",
  "params_hash": "a1b2c3d4e5f6...",
  "policy_decision": "allow",
  "result_hash": "f6e5d4c3b2a1...",
  "chain_hash": "9f8e7d6c5b4a..."
}
```

Records are **hash-chained** — each record's `chain_hash` = `SHA-256(previous_chain_hash + canonical_json(record))`. Modify, delete, or reorder any record and the entire chain breaks:

```
  Record 1          Record 2          Record 3
  ┌──────────┐      ┌──────────┐      ┌──────────┐
  │ data     │      │ data     │      │ data     │
  │          │      │          │      │          │
  │ hash: ■──┼─────▶│ hash: ■──┼─────▶│ hash: ■  │
  └──────────┘      └──────────┘      └──────────┘
       ▲
  genesis: 0x000...
```

## CLI

```bash
attestmcp serve                          # Start the proxy
attestmcp verify                         # Verify chain integrity
attestmcp export --since 2026-01-01      # Export as JSON lines
attestmcp report -o evidence.html        # HTML report for auditors
```

## Python API

```python
from attestmcp.proxy import create_app
from attestmcp.store import SQLiteAuditStore
from attestmcp.report import generate_report
from attestmcp.soc2 import map_controls
```

## SOC 2 Control Mapping

AttestMCP maps every audit record to specific Trust Services Criteria:

```
  ┌────────┬──────────────────────────────┬──────────────────────────┐
  │ Control│ Name                         │ What AttestMCP proves    │
  ├────────┼──────────────────────────────┼──────────────────────────┤
  │ CC6.1  │ Logical Access Controls      │ Identity on every record │
  │ CC6.3  │ Access Authorization         │ Policy decisions logged  │
  │ CC7.2  │ System Monitoring            │ Continuous audit trail   │
  │ CC8.1  │ Change Management            │ Tamper-evident chain     │
  └────────┴──────────────────────────────┴──────────────────────────┘
```

## Architecture

```
  ┌─────────────────────────────────────────────────────────┐
  │                     AttestMCP Proxy                     │
  │                                                         │
  │  ┌─────────────┐  ┌─────────────┐  ┌────────────────┐  │
  │  │  FastAPI     │  │  Identity   │  │  Prometheus    │  │
  │  │  POST /mcp   │  │  JWT/JWKS   │  │  GET /metrics  │  │
  │  └──────┬───────┘  └──────┬──────┘  └────────────────┘  │
  │         │                 │                              │
  │         ▼                 ▼                              │
  │  ┌──────────────────────────────────┐                    │
  │  │        Audit Pipeline            │                    │
  │  │  parse → identify → hash → chain │                    │
  │  └──────────────┬───────────────────┘                    │
  │                 │                                        │
  │  ┌──────────────▼───────────────────┐                    │
  │  │     SQLite + WAL                 │                    │
  │  │     Synchronous writes           │                    │
  │  │     SHA-256 hash chain           │                    │
  │  └──────────────────────────────────┘                    │
  │                                                         │
  │  ┌──────────────────────────────────┐                    │
  │  │     httpx async → upstream       │                    │
  │  │     Zero payload modification    │                    │
  │  └──────────────────────────────────┘                    │
  └─────────────────────────────────────────────────────────┘
```

## Configuration

All via environment variables (prefix `ATTESTMCP_`):

```
  Variable                  Default                       Description
  ─────────────────────────────────────────────────────────────────────
  ATTESTMCP_UPSTREAM_URL    http://localhost:8000/mcp      Memory server
  ATTESTMCP_HOST            0.0.0.0                        Bind address
  ATTESTMCP_PORT            9090                           Listen port
  ATTESTMCP_DB_PATH         attestmcp_audit.db             SQLite path
  ATTESTMCP_JWKS_URL        (none)                         JWKS endpoint
  ATTESTMCP_JWT_AUDIENCE    (none)                         JWT audience
  ATTESTMCP_JWT_ISSUER      (none)                         JWT issuer
```

## Development

```bash
git clone https://github.com/attestmcp/attestmcp.git
cd attestmcp
python3.12 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

pytest -v            # 107 tests including tamper detection
ruff check src/ tests/
mypy src/
```

## Status

```
  ██████████████████████████████████████░░░░  Phase 1 Complete
```

### ✅ Shipped

- Core data models and canonical serialization (FROZEN spec)
- Hash-chained SQLite audit store with tamper detection
- MCP proxy (FastAPI + httpx transparent forwarding)
- JWT identity extraction (anonymous / claimed / verified)
- Prometheus observability metrics
- Evidence export (JSON lines)
- HTML evidence report generator
- SOC 2 control mapping (CC6.1, CC6.3, CC7.2, CC8.1)
- CLI (`attestmcp serve | verify | export | report`)
- Dockerfile (multi-stage, non-root, healthcheck)

### 🔜 Roadmap

- Live integration tests with Mem0 + Anthropic KG Memory
- OPA policy engine integration
- SSE streaming response support
- Drata / Vanta evidence push
- Multi-tenant PostgreSQL backend

## License

Apache 2.0 — see [LICENSE](LICENSE).

---

<div align="center">

```
  Built for the teams who hear:
  "We love your AI product, but we can't pass security review."
```

</div>
