Ed25519 receipt signing plugin for Google ADK agents. Every tool call produces a cryptographic receipt following the IETF Internet-Draft format.
Project description
protect-mcp-adk
Ed25519 receipt signing plugin for Google ADK agents. Every tool call produces a cryptographic receipt following the IETF Internet-Draft format.
Install
pip install protect-mcp-adk
Usage
from google.adk import Agent
from google.adk.tools import FunctionTool
from protect_mcp_adk import ReceiptPlugin, ReceiptSigner
# Generate signing keys (or load from file)
signer = ReceiptSigner.generate()
# Add the plugin to your agent
agent = Agent(
model="gemini-2.0-flash",
tools=[FunctionTool(my_tool)],
plugins=[ReceiptPlugin(signer, auto_export_path="receipts.jsonl")],
)
# After execution, verify the receipt chain:
# npx @veritasacta/verify@0.2.5 receipts.jsonl --key <public-key-hex>
What It Does
Every tool call your ADK agent makes produces a signed receipt:
{
"payload": {
"type": "protectmcp:decision",
"spec": "draft-farley-acta-signed-receipts-01",
"tool_name": "search",
"tool_input_hash": "sha256:ff7e27...",
"decision": "allow",
"output_hash": "sha256:a3f8c9...",
"issued_at": "2026-04-06T21:30:00.000Z",
"session_id": "sess_a1b2c3d4e5f6",
"sequence": 1,
"previousReceiptHash": null,
"agent_name": "research_agent",
"invocation_id": "inv_xyz"
},
"signature": {
"alg": "EdDSA",
"kid": "sb:adk:de073ae64e43",
"sig": "3da3162da83e..."
}
}
Privacy-preserving: Tool inputs and outputs are SHA-256 hashed, not stored raw. The receipt proves what happened without exposing what was said.
Chain-linked: Each receipt includes previousReceiptHash, creating a tamper-evident chain. If any receipt is modified or removed, the chain breaks.
Offline verifiable: Receipts verify without contacting any server:
npx @veritasacta/verify@0.2.5 receipts.jsonl --key <public-key-hex>
# Exit 0 = valid, 1 = invalid (tampered), 2 = error (malformed)
API
ReceiptSigner
# Generate a new keypair
signer = ReceiptSigner.generate()
# Load from a key file
signer = ReceiptSigner.from_key_file("keys/agent.json")
# Save keys for reuse
signer.save_key("keys/agent.json")
# Access public key (for verification)
print(signer.public_key_hex)
print(signer.kid)
ReceiptPlugin
plugin = ReceiptPlugin(
signer,
auto_export_path="receipts.jsonl", # Auto-export as receipts are produced
log_receipts=True, # Log each receipt to Python logger
)
# After execution
print(plugin.receipt_count)
plugin.export_receipts("audit-bundle.jsonl")
print(plugin.get_verification_command())
Plugin Callbacks
| Callback | When | What it signs |
|---|---|---|
after_tool_callback |
After every tool execution | Tool name, input hash, output hash, decision |
on_tool_error_callback |
On tool execution error | Tool name, input hash, error reason |
before_tool_callback |
Before tool execution | Override for policy evaluation (Cedar) |
Interoperability
Receipts produced by this plugin verify against the same tooling as:
- protect-mcp (TypeScript/MCP)
- Agent Passport System (TypeScript)
- Any implementation following the IETF draft envelope format
Three independent implementations have been verified to produce interoperable receipts.
Algorithm Note
This plugin uses Ed25519 (RFC 8032) for signing. The receipt envelope's signature.alg field supports algorithm negotiation. For environments requiring post-quantum signatures (NIST FIPS 204), the same envelope format works with ML-DSA-65 by changing the alg field. See the IETF draft for algorithm agility details.
Related
- IETF Draft: Signed Receipts
- IETF Draft: Knowledge Units
- protect-mcp (TypeScript, MCP/Claude Code)
- ScopeBlind
- Veritas Acta
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file protect_mcp_adk-0.1.0.tar.gz.
File metadata
- Download URL: protect_mcp_adk-0.1.0.tar.gz
- Upload date:
- Size: 9.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88c474850f196b4f676d831cec8e1c2dbc8d8c49e498f03127ef046a3d0c6d87
|
|
| MD5 |
c52a22171569d83ac1f78cd515486061
|
|
| BLAKE2b-256 |
aa6b11add042fb414c17a2238bac2bba7f717835a4c7c2d7231eb4cd736c5b06
|
File details
Details for the file protect_mcp_adk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: protect_mcp_adk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
161f4f9e30b3dab67885ce56957740f610d8fa9f046ef8684f2c823823573dea
|
|
| MD5 |
6c5d317e58f090634596871e8c2d9852
|
|
| BLAKE2b-256 |
da53544ccb2cf55090480c0af2f82ff1cb46f83d669744ddb991968ca05429d6
|