Skip to main content

Ed25519 receipt signing plugin for Google ADK agents. Every tool call produces a cryptographic receipt following the IETF Internet-Draft format.

Project description

License: MIT IETF Draft PyPI

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:

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

protect_mcp_adk-0.1.0.tar.gz (9.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

protect_mcp_adk-0.1.0-py3-none-any.whl (9.1 kB view details)

Uploaded Python 3

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

Hashes for protect_mcp_adk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 88c474850f196b4f676d831cec8e1c2dbc8d8c49e498f03127ef046a3d0c6d87
MD5 c52a22171569d83ac1f78cd515486061
BLAKE2b-256 aa6b11add042fb414c17a2238bac2bba7f717835a4c7c2d7231eb4cd736c5b06

See more details on using hashes here.

File details

Details for the file protect_mcp_adk-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for protect_mcp_adk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 161f4f9e30b3dab67885ce56957740f610d8fa9f046ef8684f2c823823573dea
MD5 6c5d317e58f090634596871e8c2d9852
BLAKE2b-256 da53544ccb2cf55090480c0af2f82ff1cb46f83d669744ddb991968ca05429d6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page