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
Metadata
Release files for protect-mcp-adk 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| protect_mcp_adk-0.1.0.tar.gz | 9.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| protect_mcp_adk-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.2 kB
Release files / protect_mcp_adk-0.1.0.tar.gz
| Download URL | protect_mcp_adk-0.1.0.tar.gz |
|---|---|
| Size | 9.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
88c474850f196b4f676d831cec8e1c2dbc8d8c49e498f03127ef046a3d0c6d87
|
|
BLAKE2b-256 checksum How to use checksums |
aa6b11add042fb414c17a2238bac2bba7f717835a4c7c2d7231eb4cd736c5b06
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / protect_mcp_adk-0.1.0-py3-none-any.whl
| Download URL | protect_mcp_adk-0.1.0-py3-none-any.whl |
|---|---|
| Size | 9.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
161f4f9e30b3dab67885ce56957740f610d8fa9f046ef8684f2c823823573dea
|
|
BLAKE2b-256 checksum How to use checksums |
da53544ccb2cf55090480c0af2f82ff1cb46f83d669744ddb991968ca05429d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|