insumer_attest
Verify on-chain conditions (token balances, NFT ownership, EAS attestations, Farcaster identity) across 33 chains. Returns ECDSA-signed boolean results preserving privacy. Supports EVM, Solana, XRPL, Bitcoin.
Instructions
Create on-chain verification (attestation). Verify 1-10 conditions (token balances, NFT ownership, EAS attestations, Farcaster identity) across 33 chains. Returns ECDSA-signed boolean results with a kid field identifying the signing key (fetch public key via insumer_jwks). Never exposes actual balances. Each result includes evaluatedCondition (exact logic checked), conditionHash (SHA-256 for tamper-evidence), and blockNumber/blockTimestamp for RPC chains (freshness). XRPL results include ledgerIndex and ledgerHash (validated ledger hash) instead of blockNumber/blockTimestamp; trust line token results also include trustLineState: { frozen: boolean } (frozen trust lines cause met: false). Standard mode costs 1 credit. Pass proof: 'merkle' for EIP-1186 Merkle storage proofs (2 credits). For EAS attestations, use a compliance template (Coinbase Verifications, Gitcoin Passport) or raw schemaId. For Farcaster, use type 'farcaster_id' (checks IdRegistry on Optimism). Use insumer_compliance_templates to list available templates.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| wallet | No | EVM wallet address (0x...) | |
| solanaWallet | No | Solana wallet address (base58) | |
| xrplWallet | No | XRPL wallet address (r-address). For verifying XRP, trust line tokens (RLUSD, USDC), or NFTs on XRP Ledger. | |
| bitcoinWallet | No | Bitcoin address (P2PKH, P2SH, bech32, or Taproot). For verifying native BTC balance. Use chainId 'bitcoin' with contractAddress 'native'. | |
| proof | No | Set to 'merkle' for EIP-1186 Merkle storage proofs (2 credits). Proofs available for token_balance on RPC chains only. | |
| format | No | Set to 'jwt' to include a Wallet Auth by InsumerAPI token (ES256-signed JWT) in the response. Verifiable by any standard JWT library using JWKS at /.well-known/jwks.json. | |
| conditions | Yes | 1-10 on-chain conditions to verify |
Implementation Reference
- src/index.ts:226-261 (registration)Registration of the 'insumer_attest' tool on the MCP server. This is where the tool is defined with name, description, input schema (using Zod), and handler.
server.tool( "insumer_attest", "Create on-chain verification (attestation). Verify 1-10 conditions (token balances, NFT ownership, EAS attestations, Farcaster identity) across 33 chains. Returns ECDSA-signed boolean results with a kid field identifying the signing key (fetch public key via insumer_jwks). Never exposes actual balances. Each result includes evaluatedCondition (exact logic checked), conditionHash (SHA-256 for tamper-evidence), and blockNumber/blockTimestamp for RPC chains (freshness). XRPL results include ledgerIndex and ledgerHash (validated ledger hash) instead of blockNumber/blockTimestamp; trust line token results also include trustLineState: { frozen: boolean } (frozen trust lines cause met: false). Standard mode costs 1 credit. Pass proof: 'merkle' for EIP-1186 Merkle storage proofs (2 credits). For EAS attestations, use a compliance template (Coinbase Verifications, Gitcoin Passport) or raw schemaId. For Farcaster, use type 'farcaster_id' (checks IdRegistry on Optimism). Use insumer_compliance_templates to list available templates.", { wallet: z.string().optional().describe("EVM wallet address (0x...)"), solanaWallet: z.string().optional().describe("Solana wallet address (base58)"), xrplWallet: z.string().optional().describe("XRPL wallet address (r-address). For verifying XRP, trust line tokens (RLUSD, USDC), or NFTs on XRP Ledger."), bitcoinWallet: z.string().optional().describe("Bitcoin address (P2PKH, P2SH, bech32, or Taproot). For verifying native BTC balance. Use chainId 'bitcoin' with contractAddress 'native'."), proof: z.enum(["merkle"]).optional().describe("Set to 'merkle' for EIP-1186 Merkle storage proofs (2 credits). Proofs available for token_balance on RPC chains only."), format: z.enum(["jwt"]).optional().describe("Set to 'jwt' to include a Wallet Auth by InsumerAPI token (ES256-signed JWT) in the response. Verifiable by any standard JWT library using JWKS at /.well-known/jwks.json."), conditions: z .array( z.object({ type: z.enum(["token_balance", "nft_ownership", "eas_attestation", "farcaster_id"]).describe("Condition type: token_balance, nft_ownership, eas_attestation, or farcaster_id (Farcaster IdRegistry on Optimism)"), contractAddress: z.string().optional().describe("Token or NFT contract address (required for token_balance and nft_ownership)"), chainId: ChainId.optional(), threshold: z.number().optional().describe("Minimum balance required (for token_balance). Must be > 0 when proof is merkle."), decimals: z.number().int().min(0).max(77).optional().describe("Token decimals (default 18)"), label: z.string().max(100).optional().describe("Human-readable label"), schemaId: z.string().optional().describe("EAS schema ID (bytes32 hex). Required for eas_attestation unless template is provided."), attester: z.string().optional().describe("Expected attester address (optional, for eas_attestation)"), indexer: z.string().optional().describe("EAS indexer contract address (optional, for eas_attestation)"), template: z.enum(["coinbase_verified_account", "coinbase_verified_country", "coinbase_one", "gitcoin_passport_score", "gitcoin_passport_active"]).optional().describe("Compliance template name. Use instead of raw schemaId/attester/indexer for eas_attestation. Gitcoin Passport templates check Sybil resistance on Optimism."), currency: z.string().optional().describe("XRPL trust line currency code (e.g. 'RLUSD', 'USDC'). Required for XRPL trust line tokens, ignored for other chains."), taxon: z.number().int().optional().describe("XRPL NFToken taxon filter (optional, for nft_ownership on XRPL only). Filters NFTs by issuer + taxon."), }) ) .min(1) .max(10) .describe("1-10 on-chain conditions to verify"), }, async (args) => { const result = await apiCall("POST", "/attest", args); return formatResult(result); } ); - src/index.ts:229-256 (schema)Input schema for insumer_attest: accepts wallet addresses (EVM, Solana, XRPL, Bitcoin), optional proof/format flags, and 1-10 conditions of type token_balance, nft_ownership, eas_attestation, or farcaster_id.
{ wallet: z.string().optional().describe("EVM wallet address (0x...)"), solanaWallet: z.string().optional().describe("Solana wallet address (base58)"), xrplWallet: z.string().optional().describe("XRPL wallet address (r-address). For verifying XRP, trust line tokens (RLUSD, USDC), or NFTs on XRP Ledger."), bitcoinWallet: z.string().optional().describe("Bitcoin address (P2PKH, P2SH, bech32, or Taproot). For verifying native BTC balance. Use chainId 'bitcoin' with contractAddress 'native'."), proof: z.enum(["merkle"]).optional().describe("Set to 'merkle' for EIP-1186 Merkle storage proofs (2 credits). Proofs available for token_balance on RPC chains only."), format: z.enum(["jwt"]).optional().describe("Set to 'jwt' to include a Wallet Auth by InsumerAPI token (ES256-signed JWT) in the response. Verifiable by any standard JWT library using JWKS at /.well-known/jwks.json."), conditions: z .array( z.object({ type: z.enum(["token_balance", "nft_ownership", "eas_attestation", "farcaster_id"]).describe("Condition type: token_balance, nft_ownership, eas_attestation, or farcaster_id (Farcaster IdRegistry on Optimism)"), contractAddress: z.string().optional().describe("Token or NFT contract address (required for token_balance and nft_ownership)"), chainId: ChainId.optional(), threshold: z.number().optional().describe("Minimum balance required (for token_balance). Must be > 0 when proof is merkle."), decimals: z.number().int().min(0).max(77).optional().describe("Token decimals (default 18)"), label: z.string().max(100).optional().describe("Human-readable label"), schemaId: z.string().optional().describe("EAS schema ID (bytes32 hex). Required for eas_attestation unless template is provided."), attester: z.string().optional().describe("Expected attester address (optional, for eas_attestation)"), indexer: z.string().optional().describe("EAS indexer contract address (optional, for eas_attestation)"), template: z.enum(["coinbase_verified_account", "coinbase_verified_country", "coinbase_one", "gitcoin_passport_score", "gitcoin_passport_active"]).optional().describe("Compliance template name. Use instead of raw schemaId/attester/indexer for eas_attestation. Gitcoin Passport templates check Sybil resistance on Optimism."), currency: z.string().optional().describe("XRPL trust line currency code (e.g. 'RLUSD', 'USDC'). Required for XRPL trust line tokens, ignored for other chains."), taxon: z.number().int().optional().describe("XRPL NFToken taxon filter (optional, for nft_ownership on XRPL only). Filters NFTs by issuer + taxon."), }) ) .min(1) .max(10) .describe("1-10 on-chain conditions to verify"), }, - src/index.ts:257-260 (handler)Handler function for insumer_attest. Makes an apiCall POST to /attest with the provided arguments and formats the result.
async (args) => { const result = await apiCall("POST", "/attest", args); return formatResult(result); } - src/index.ts:17-40 (helper)The apiCall helper used by insumer_attest's handler. Sends authenticated requests to the InsumerAPI backend.
async function apiCall( method: string, path: string, body?: Record<string, unknown> ): Promise<{ ok: boolean; data?: unknown; error?: unknown; meta?: unknown }> { if (!apiKey) { return { ok: false, error: "INSUMER_API_KEY is not set. Call the insumer_setup tool to generate a free API key instantly, then add it to your MCP config as INSUMER_API_KEY and restart." }; } const url = `${API_BASE}${path}`; const res = await fetch(url, { method, headers: { "Content-Type": "application/json", "X-API-Key": apiKey, }, body: body ? JSON.stringify(body) : undefined, }); return res.json() as Promise<{ ok: boolean; data?: unknown; error?: unknown; meta?: unknown; }>; } - src/index.ts:61-76 (helper)The formatResult helper used by insumer_attest's handler. Wraps API responses into MCP content blocks.
function formatResult(result: { ok: boolean; data?: unknown; error?: unknown; meta?: unknown; }) { if (result.ok) { return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }], }; } return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }], isError: true, }; }