Self-custodial DeFi for AI agents — agent proposes, you approve on your Ledger. GSD-planned rebuild of vaultpilot-mcp.
Two tools with comprehensive descriptions (200+ chars each), detailed parameter schemas with regex patterns and enums, and clear error modes documented. Both tools follow verb_noun naming (prepare_*). Schemas are well-structured with required fields, pattern validation, and descriptions for all parameters. However, output schemas are not explicitly documented in the source code provided, only inferred from description text. Error handling is described narratively but lacks structured error response examples. No tool annotations (readOnlyHint/destructiveHint) present. Both tools are write operations on blockchain state, requiring careful handling.
Revoke an existing ERC-20 approval by setting the allowance to 0 for a specific spender on the specified EVM chain. Returns a handle the agent passes to preview_send before send_transaction. Produces an `approve(spender, 0)` call against the token contract — byte-identical calldata to prepare_token_approve({ ..., amount: "0" }); the distinct tool name routes by user intent. Use when the user wants to revoke a prior approval (defensive hygiene — e.g. after a deprecated dApp interaction; after seeing a `⚠ UNLIMITED APPROVAL` line in preview_send's DECODED ARGS block). Do NOT use to set a NEW non-zero approval — that's prepare_token_approve. Do NOT use for ERC-20 transfers / native ETH / WETH unwrap / other contract calls — each has a dedicated prepare_* tool. `chain` is REQUIRED — pass one of ethereum, arbitrum, polygon, base, optimism. `tokenAddress` is the ERC-20 contract address (0x-prefixed 20-byte hex). `spender` is the contract whose allowance should be revoked. Pass `from` when the user wants to act from a non-default approved account (visible in `get_ledger_status.accountsByChain[chainId]`); otherwise omit and the active account is used. PREPARE RECEIPT surfaces `From:` only when caller-supplied. Requires a paired Ledger (call pair_ledger_live first if get_ledger_status shows paired: false). In demo mode, succeeds against the active persona's address as `from`; send_transaction returns a simulation envelope instead of broadcasting. Returns the same shape as prepare_token_approve (`{ handle, chain, chainId, from, spender, tokenAddress, amount: "0", amountWei: "0", payloadFingerprint }`) plus the PREPARE RECEIPT and DECODED ARGS surface in preview_send. Failure modes: WALLET_NOT_PAIRED if no live session (real mode), WRONG_MODE if demo mode is on but no persona set OR if `from` doesn't match the active persona, INVALID_INPUT if chain/tokenAddress/spender/from malformed, INVALID_ACCOUNT if `from` is not in the per-chain approved set.
Use when ANOTHER owner proposed a Safe tx and the user wants to co-sign. Off-chain typed-data sign — does NOT broadcast on-chain. Fetches the pending SafeTx from the Safe Tx Service, re-derives the EIP-712 typed-data structure from on-chain Safe state (defends against Tx Service drift), returns a handle the user signs via Ledger ETH app over WalletConnect (eth_signTypedData_v4); agent then calls submit_safe_tx_signature to publish the signature. Required args: chain, safeAddress, safeTxHash. Returns `{ handle, chain, chainId, from, safeAddress, safeVersion, safeTxHash, safeNonce, operation, to, value, data, payloadFingerprint, typedDataStructure, domainSeparatorMatches, duplicateSignWarning, handleNotFound }` plus PREPARE RECEIPT + CHECKS PERFORMED + LEDGER DISPLAY text blocks. Refuses pre-v1.3.0 Safes (UNSUPPORTED_SAFE_VERSION). Refuses if the Tx Service-reported safeTxHash diverges from the local recompute (INVALID_INPUT + txServiceDrift — defends against compromised Tx Service serving a wrong pending SafeTx). Failure modes: UNSUPPORTED_SAFE_VERSION, WALLET_NOT_PAIRED, INVALID_INPUT (Tx Service not-found / unsupported-chain / rate-limited / error / txServiceDrift / sender-not-owner), WRONG_MODE, INTERNAL_ERROR.
Output schemas not explicitly documented in source. Descriptions reference return shapes (e.g., '{ handle, chain, chainId, ... }') but no formal JSON Schema for responses is visible. LLMs cannot reliably parse unstructured output.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) present. Both tools perform write operations on blockchain state (signing transactions), but this is not machine-readable in the tool definition.
Error modes documented in description text only (WALLET_NOT_PAIRED, WRONG_MODE, INVALID_INPUT, etc.), but no structured error response schema or recovery guidance examples provided. LLMs cannot programmatically distinguish error types.
Inferred effective spec: 2025-06-18+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | 2025-06-18+ | v2 |
Parameter descriptions reference external state (e.g., 'must be one of the per-chain approved accounts in get_ledger_status.accountsByChain[chainId]') without providing discovery tools or examples. Agents cannot validate inputs without calling other tools first.
Only 2 tools visible in this server. No read tools (get_ledger_status, get_safe_positions) are shown in the provided source excerpt, limiting ability to assess tool composition and chaining patterns.