Files
timmy-config/docs/finance-integration.md
Rockachopa e99c6d4660
Some checks failed
Architecture Lint / Linter Tests (pull_request) Successful in 28s
Smoke Test / smoke (pull_request) Failing after 32s
Validate Config / YAML Lint (pull_request) Failing after 23s
Validate Config / JSON Validate (pull_request) Successful in 20s
Validate Config / Python Syntax & Import Check (pull_request) Failing after 1m5s
Validate Config / Python Test Suite (pull_request) Has been skipped
Validate Config / Shell Script Lint (pull_request) Failing after 1m4s
Validate Config / Cron Syntax Check (pull_request) Successful in 15s
Validate Config / Deploy Script Dry Run (pull_request) Successful in 13s
PR Checklist / pr-checklist (pull_request) Failing after 4m54s
Validate Config / Playbook Schema Validation (pull_request) Successful in 32s
Architecture Lint / Lint Repository (pull_request) Failing after 24s
feat: integrate USDC/x402 secure payment plugin (#965)
Add hermes-finance-plugin MCP server with approval workflows.

Changes:
- mcp/servers.json: register hermes-finance-plugin MCP server
- config.yaml: extend approvals with finance policy (threshold $10, daily cap $100)
- docs/finance-integration.md: full integration guide
- mcp/setup.sh: add Node.js + plugin installation
- bin/test-finance-payment.py: dry-run demo and smoke test script

Supported networks: Sepolia, Base Sepolia, Base, Ethereum.
Approval: payments >$10 require second signature; $100 daily cap per agent.
Security: private key via env, append-only audit logs, revocation path.

Closes #965
2026-04-29 20:25:08 -04:00

7.6 KiB

USDC/x402 Payment Integration — Finance Plugin

Ticket: #965
Plugin: hermes-finance-plugin
Type: MCP Server (stdio transport)
Status: Integrated


Overview

The hermes-finance-plugin is an MCP server that exposes USDC/x402 payment tools to Timmy. It enables agents to:

  • Send USDC on Ethereum L1 and L2s (Ethereum, Base, Base Sepolia, Sepolia)
  • Enforce per-transaction and daily approval limits
  • Log all payment attempts for audit
  • Support multi-step approval workflows for high-value transfers

This integration configures the plugin as a sidecar MCP server in timmy-config, wires approval policies into config.yaml, and provides sandbox testing instructions.


Supported Networks & Wallet Requirements

Networks

Network Chain ID x402 Enabled Faucet
Sepolia (testnet) 11155111 https://sepoliafaucet.com
Base Sepolia 84532 https://faucet.base.org
Base Mainnet 8453 N/A (real funds)
Ethereum Mainnet 1 N/A (real funds)

Wallet Requirements

  • Private key stored in FINANCE_PRIVATE_KEY env var (no 0x prefix)
  • RPC endpoint in FINANCE_RPC_URL (Infura, Alchemy, or public RPC)
  • USDC balance — ensure sufficient funds + gas on chosen network
  • x402 marketplace support — recipient must support x402 payment requests

Approval Workflow Steps

1. Agent Requests Payment

Agent calls payment_send MCP tool with:

{
  "to": "0x...",
  "amount_usd": 25.50,
  "network": "sepolia",
  "reason": "API service fee"
}

2. Threshold Evaluation

Plugin compares amount_usd against FINANCE_APPROVAL_THRESHOLD_USD (default: $10):

  • ≤ $10 → auto-approved, transaction proceeds
  • > $10 → requires second signature (manual approval step)

3. Approval Routing

For amounts > $10, the plugin:

  1. Logs approval request to ~/.hermes/logs/finance_approvals.jsonl
  2. Sends approval request via configured notifier (see config.yamlnotifications)
  3. Waits for explicit payment_approve or payment_reject signal
  4. Proceeds only after approval or times out after 24h

4. Daily Cap Enforcement

The plugin maintains a rolling 24h spend ledger per agent in ~/.hermes/logs/finance_spend.jsonl. If an agent's total since yesterday exceeds FINANCE_DAILY_CAP_USD (default: $100), all payment requests are rejected until the window slides.


Rate Limiting & Daily Caps

Rate limiting: Built into the x402 protocol itself — each payment request is EIP-712 signed and non-replayable.

Daily caps: Per-agent accounting enforced client-side by the plugin. Ledger location:

~/.hermes/logs/finance_spend.jsonl

Sample ledger entry:

{
  "timestamp": "2026-04-29T12:34:56Z",
  "agent_id": "allegro",
  "tx_hash": "0xabc123...",
  "amount_usd": 25.00,
  "network": "sepolia",
  "to": "0xrecipient...",
  "status": "completed"
}

Configuring Approval Policies

Add the following to config.yaml under approvals::

approvals:
  mode: manual
  finance:
    threshold_usd: 10        # Payments > $10 require second signature
    daily_cap_usd: 100       # Daily limit per agent
    require_second_signature: true
    enabled_networks:
      - sepolia
      - base-sepolia
      - base
      - ethereum

Configurable via environment variables (take precedence):

  • FINANCE_THRESHOLD_USD
  • FINANCE_DAILY_CAP_USD
  • FINANCE_REQUIRE_SECOND_SIGNATURE (true/false)

Setup & Installation

Prerequisites

  • Node.js ≥ 18 (for npx)
  • npm or yarn
  • Access to a funded testnet wallet (Sepolia or Base Sepolia)

One-line Install

cd ~/.timmy/timmy-config/mcp
bash setup.sh

The setup.sh script:

  1. Verifies Node.js installation
  2. Installs hermes-finance-plugin via npm
  3. Validates environment variables
  4. Runs a smoke test with --dry-run

Environment Variables

Set these in ~/.zshrc or ~/.bashrc:

# Network selection (sepolia | base-sepolia | base | ethereum)
export FINANCE_NETWORK=sepolia

# Private key (no 0x prefix, keep secret!)
export FINANCE_PRIVATE_KEY=abc123...

# RPC endpoint (Infura/Alchemy/public)
export FINANCE_RPC_URL=https://sepolia.infura.io/v3/YOUR_KEY

# Approval policy (optional — overrides config.yaml)
export FINANCE_DAILY_CAP_USD=100
export FINANCE_APPROVAL_THRESHOLD_USD=10

Never commit private keys. Use .env files or system keychain.


Testing the Plugin

Dry-Run (no funds)

~/.hermes/bin/test-finance-payment.py --dry-run --amount 25 --to 0xRecipient

Expected output:

[DRY-RUN] Would send $25.00 USDC on sepolia to 0xRecipient
[CHECK] Amount > $10 → requires manual approval
[APPROVAL] Request logged to ~/.hermes/logs/finance_approvals.jsonl

Live Test (Sepolia testnet)

# 1. Get Sepolia ETH & USDC from faucets
#    - https://sepoliafaucet.com (ETH)
#    - USDC: https://www.usdcfaucet.com (sepolia)

# 2. Run real transaction
~/.hermes/bin/test-finance-payment.py \
  --amount 5.00 \
  --to 0xYourTestAddress \
  --network sepolia

Expected result:

  • Transaction hash appears in output
  • Transaction visible on sepolia.etherscan.io
  • Approval log entry appears if amount > $10

Verification Deliverables

After sandbox testing, produce:

  1. Testnet transaction hash
    Example: 0x4f3a...c2d1 from Sepolia Etherscan

  2. Config snippet showing policy
    Save output of:

    grep -A5 'approvals:' ~/.timmy/timmy-config/config.yaml
    
  3. Screenshot of approval log entry

    tail -1 ~/.hermes/logs/finance_approvals.jsonl | jq .
    
  4. Risks and mitigations note (see below)


Security Considerations

Key Storage

  • Risk: Private key compromise → total fund loss
  • Mitigation:
    • Store keys in macOS Keychain or pass (Unix password manager)
    • Use dedicated burner wallet for each agent
    • Never check keys into git; enforce via pre-commit hooks
    • Rotate keys monthly

Revocation

  • Risk: Compromised key cannot be revoked on-chain (EVM)
  • Mitigation:
    • Use smart-contract wallets (Safe, Argent) with owner rotation
    • Emergency finance_revoke MCP tool immediately disables plugin
    • Maintain hot/cold wallet split — daily cap limits exposure

Audit Trail

  • Risk: Tampered logs hide malicious activity
  • Mitigation:
    • Append-only finance_spend.jsonl and finance_approvals.jsonl with daily hash chaining
    • Ship logs to remote SIEM (Splunk/Graylog) via secure syslog
    • Weekly attestation: git commit logs to immutable storage (S3 with WORM)
    • All approval decisions require cryptographic signature from approver

Additional Safeguards

  • Enable tirith security guard in config.yaml
  • Enforce security.redact_secrets: true to avoid private-key logging
  • Run plugin in isolated network namespace (optional)

Troubleshooting

Symptom Likely Cause Fix
npx: command not found Node.js not installed brew install node
ENOENT: hermes-finance-plugin npm package not found npm install -g hermes-finance-plugin
PRIVATE_KEY not set Env var missing export FINANCE_PRIVATE_KEY=...
insufficient funds Testnet wallet empty Visit faucets above
approval timeout No manual approver Set FINANCE_REQUIRE_SECOND_SIGNATURE=false for test

References