The legal mandate layer for AI agents.
AMR is an open-source MCP server that registers, verifies, and audits legal mandates authorizing AI agents to act on behalf of principals. It provides a cryptographically chained audit trail designed for compliance with EU AI Act Art.26 (effective August 2026) and eIDAS 2.0.
Modern AI agent infrastructure covers many concerns — but the legal mandate layer is missing:
| Concern | Existing tools | AMR |
|---|---|---|
| Infrastructure & orchestration | ✅ LangChain, AutoGen, CrewAI | — |
| Security & sandboxing | ✅ Docker, RBAC, network policies | — |
| Permission & access control | ✅ OAuth, IAM, API keys | — |
| Observability & tracing | ✅ OpenTelemetry, Langfuse | — |
| Legal mandate & accountability | ❌ Not covered | ✅ AMR |
EU AI Act Art.26 (August 2026) requires operators of high-risk AI systems to maintain tamper-evident logs of agent mandates and actions. Non-compliance: fines up to €30M or 6% global turnover. AMR closes this gap.
git clone https://github.com/your-org/amr.git
cd amr
uv sync
uv run amrAdd AMR to your Claude Desktop config file:
Location: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"amr": {
"command": "uv",
"args": ["--directory", "C:\\dev\\amr", "run", "amr"]
}
}
}Restart Claude Desktop. AMR's four tools will be available immediately.
Register a new legal mandate authorizing an AI agent to act on behalf of a principal.
Parameters:
| Parameter | Type | Description |
|---|---|---|
principal_id |
str | Principal granting the mandate. E.g. "user:audric" |
agent_id |
str | Agent receiving authorization. E.g. "agent:korvex-advisor-v1" |
scope |
str | What the agent is authorized to do |
legal_basis_regulation |
str | Regulation or contract. E.g. "EU AI Act Art.26" |
legal_basis_article |
str | Specific article or clause. E.g. "Art.26(1)(a)" |
duration_hours |
float | Duration in hours (max 8760 = 1 year) |
legal_basis_jurisdiction |
str | Jurisdiction code (default "EU") |
parent_mandate_id |
str | null | UUID of parent mandate for delegation chains |
metadata |
dict | Optional string key-value pairs for annotations |
Returns:
{
"status": "created",
"mandate_id": "550e8400-e29b-41d4-a716-446655440000",
"principal_id": "user:audric",
"agent_id": "agent:korvex-advisor-v1",
"scope": "Compare and recommend financial products to retail clients",
"expires_at": "2026-05-13T20:00:00+00:00",
"chain_hash": "a3f5c2d1e8b9..."
}Check whether an AI agent has a currently active, non-expired mandate.
Parameters:
| Parameter | Type | Description |
|---|---|---|
agent_id |
str | Agent to check. E.g. "agent:korvex-advisor-v1" |
action |
str | Action the agent wants to perform |
context |
str | Optional context for audit logging |
Returns:
{
"authorized": true,
"mandate_id": "550e8400-e29b-41d4-a716-446655440000",
"reason": "Active mandate found",
"scope": "Compare and recommend financial products to retail clients",
"expires_at": "2026-05-13T20:00:00+00:00"
}Log an agent action under an active mandate. Cryptographically chained to previous actions.
Parameters:
| Parameter | Type | Description |
|---|---|---|
mandate_id |
str | UUID of the mandate under which the action was performed |
action |
str | Description of the action performed |
evidence |
str | Optional reference or evidence. E.g. "email:msg_abc123" |
result |
str | Optional outcome. E.g. "Delivered" |
Returns:
{
"status": "logged",
"action_id": "7f3e9b2a-...",
"mandate_id": "550e8400-...",
"action": "Generated investment recommendation for Product X",
"chain_hash": "c8d7e6f5..."
}Generate a complete Proof Pack — a full audit bundle for a mandate including all actions and cryptographic chain verification.
Parameters:
| Parameter | Type | Description |
|---|---|---|
mandate_id |
str | UUID of the mandate to prove |
format |
str | Output format (currently "json") |
Returns:
{
"proof_pack_version": "0.1.0",
"generated_at": "2026-04-13T18:00:00+00:00",
"mandate": { "...": "full mandate details" },
"actions": [ "...list of all logged actions..." ],
"events": [],
"chain_integrity": {
"actions_chain_valid": true,
"total_actions": 5,
"total_events": 0
},
"compliance_notes": {
"ai_act_art26": "This Proof Pack documents the mandate chain for AI Act Art.26 compliance.",
"retention": "Logs must be retained for minimum 6 months per AI Act Art.26(6)."
}
}┌─────────────────────────────────────────────────────────────────────┐
│ PRINCIPAL │
│ (user:audric, org:acme-corp) │
└──────────────────────────┬──────────────────────────────────────────┘
│ create_mandate()
▼
┌─────────────────────────────────────────────────────────────────────┐
│ MANDATE (SHA-256 chained) │
│ id · principal · agent · scope · legal_basis · expires_at │
│ chain_hash = SHA256(mandate_data + prev_hash) │
└──────────────────────────┬──────────────────────────────────────────┘
│ verify_mandate() → authorized: true
▼
┌─────────────────────────────────────────────────────────────────────┐
│ AGENT │
│ (agent:korvex-advisor-v1) │
└──────────────────────────┬──────────────────────────────────────────┘
│ log_action() × N
▼
┌─────────────────────────────────────────────────────────────────────┐
│ ACTION LOG (append-only, SHA-256 chained) │
│ action_1 ──hash──▶ action_2 ──hash──▶ action_3 ──hash──▶ ... │
│ Each action links to the previous via chain_hash │
└──────────────────────────┬──────────────────────────────────────────┘
│ get_proof()
▼
┌─────────────────────────────────────────────────────────────────────┐
│ PROOF PACK (JSON) │
│ mandate + actions + chain_integrity + compliance_notes │
│ Ready for regulatory audit, eIDAS submission, or archival │
└─────────────────────────────────────────────────────────────────────┘
-
Pydantic v2 validation — All tool inputs are validated before any DB interaction. Unknown fields are rejected (
extra="forbid"). Duration, string lengths, and UUID formats are enforced at the model layer. -
Parameterized SQL only — Every database query uses
?placeholders. No string interpolation or f-strings in SQL. Enforced byruffS608 rule on every commit. -
Append-only tables — The
mandatesandaction_logstables are neverUPDATEd orDELETEd. The audit trail is immutable by design. Status changes use a separatemandate_eventstable. -
SHA-256 cryptographic chain — Each mandate and each action log entry is linked to the previous one via a SHA-256 hash (git-style). Any tampering invalidates all subsequent hashes, making the trail tamper-evident.
-
stdio transport only — AMR runs as a local MCP server over stdio. No listening port, no inbound network exposure, no outbound HTTP from tools. The attack surface is minimal.
| Regulation | Relevance to AMR |
|---|---|
| EU AI Act Art.26 | High-risk AI system operators must maintain logs of agent mandates and actions. AMR provides the technical infrastructure for this obligation. Effective August 2026. |
| EU AI Act Art.26(6) | Logs must be retained for a minimum of 6 months. AMR's append-only SQLite database and Proof Pack export support this requirement. |
| eIDAS 2.0 | Electronic mandates for AI agents acting on behalf of natural or legal persons. AMR's mandate chain maps to the eIDAS electronic delegation trust framework. |
| Fines | EU AI Act fines up to €30M or 6% of global annual turnover for non-compliance with high-risk AI obligations. AMR directly reduces this regulatory risk. |
| Version | Features |
|---|---|
| v0.1 (current) | 4 MCP tools · SQLite · SHA-256 chain · Pydantic validation · Proof Pack JSON · Claude Desktop integration |
| v0.2 | PDF Proof Pack export · SSE transport for remote MCP clients · Mandate revocation workflow |
| v0.3 | PostgreSQL backend · Multi-tenant support · REST API alongside MCP |
| v0.4 | eIDAS 2.0 qualified electronic signature integration · Cross-border mandate recognition |
| v0.5 | Managed Agents registry · Sub-delegation chains · Webhook notifications on mandate events |
# Install all dependencies including dev extras
uv sync --all-extras
# Run the full test suite (20 tests)
uv run pytest -v
# Run with short traceback on failure
uv run pytest -v --tb=short
# Lint and security check (src + tests)
uv run ruff check src/ tests/
# Auto-fix safe issues
uv run ruff check --fix src/ tests/
# Start the MCP server (stdio — normal to wait for input)
uv run amrsrc/amr/
├── config.py # Settings via pydantic-settings (env prefix: AMR_)
├── server.py # FastMCP server entrypoint (stdio transport)
├── models/mandate.py # Pydantic models: MandateCreate, Mandate, ActionLog
├── crypto/chain.py # compute_hash() and verify_chain() — stdlib only
├── db/engine.py # init_db(), get_db(), get_last_mandate_hash()
└── tools/
├── create_mandate.py
├── verify_mandate.py
├── log_action.py
└── get_proof.py
tests/
├── conftest.py # Isolated temp DB fixture (autouse)
├── test_create_mandate.py # 5 tests
├── test_verify_mandate.py # 3 tests
├── test_log_and_proof.py # 5 tests
└── test_crypto.py # 7 tests
| Variable | Default | Description |
|---|---|---|
AMR_DB_PATH |
amr_mandates.db |
Path to the SQLite database file |
AMR_LOG_LEVEL |
INFO |
Logging verbosity |
AMR_SERVER_NAME |
Agent Mandate Registry |
MCP server display name |
Apache License 2.0 — See LICENSE for full terms.
Free to use in commercial products. Compatible with EU AI Act open-source provisions.
⚠️ Disclaimer: AMR is a technical infrastructure tool. It does not constitute legal advice. Compliance with EU AI Act, eIDAS 2.0, or any other regulation remains the responsibility of the operator. Consult qualified legal counsel for your specific regulatory obligations.