Skip to main content
Glama
Alubiama
by Alubiama

Aerodrome MCP for Base — independent read-only tools

Aerodrome MCP for Base

See what changed in an Aerodrome position — with the block references and missing data kept visible.

A local MCP server for Aerodrome on Base mainnet (chain ID 8453). Compare your current veNFT voting positions and bounded claimable rewards against a saved snapshot, or compare selected pools' voting evidence.

Independent community project. Not affiliated with Aerodrome or Base. This release supports Aerodrome only, not every protocol on Base.

Version: 0.5.2. License: MIT.

Try it and check the result · One-minute demo · Integration guide · Security boundaries · Brand notes

A small job you can try today

You maintain an Aerodrome dashboard or an assistant for veAERO holders. A reward amount changed between two checks. Your interface needs to show what changed, which blocks were compared, and what remains unknown.

This MCP returns that evidence as structured data. The example below changes one synthetic reward from 100 → 125 raw units, with deltaRaw: "25" and block references 100 → 101. It does not label the change as earned income or a claimed reward.

Synthetic reward change: 100 to 125 raw units; blocks 100 to 101; cause unknown

First step: run the offline example and compare its output. No wallet connection or API key is needed for this example once dependencies are installed. Live reads require an RPC connection and cover only the documented scope.

For builders: start with the existing stdio client and integration guide. For holders: supply a public address to the overview through your MCP client; the offline demo is a fixture, not your account.

Related MCP server: Aerodrome Finance MCP Server

Quick start

Requires Node.js 24 or newer and npm.

git clone https://github.com/Alubiama/aerodrome-mcp-base.git
cd aerodrome-mcp-base

From your local repository checkout:

npm ci --ignore-scripts
npm run typecheck
npm test
npm run demo

The demo uses synthetic data, a real local MCP connection and temporary storage. It needs no wallet, network, API key or model. It shows an address-only overview followed by BASELINE_CREATED and COMPARED, with a test reward amount increasing from 100 to 125 raw units.

To set optional local wallet defaults:

cp config.example.json config.json

Local configuration is optional for public protocol/pool reads and for wallet_overview with an explicit wallet address. If using config.json, replace its synthetic wallet with your public address. veNftTokenIds may be empty; the overview discovers owned IDs automatically. Configured snapshot/change tools continue to use the explicitly configured IDs. Add gauge addresses only if you want LP rewards checked. Never enter a seed phrase or private key. Unknown configuration fields are rejected. Configured veNFT ownership is checked for wallet reward reads.

Connect an MCP client

Use absolute paths for your checkout and Node executable:

{
  "mcpServers": {
    "aerodrome": {
      "command": "/absolute/path/to/node",
      "args": [
        "--import", "/absolute/path/to/aerodrome-mcp-base/node_modules/tsx/dist/loader.mjs",
        "/absolute/path/to/aerodrome-mcp-base/src/mcp/index.ts"
      ]
    }
  }
}

Use a client tool timeout of 150 seconds. The server deadline is 120 seconds; concurrency is capped at two active reads. Paths are resolved relative to the checkout, so launching from another directory works. Run Node directly for stdio; do not put npm banners on the protocol stream.

For Codex, add the equivalent [mcp_servers.aerodrome] table to project .codex/config.toml in a trusted project, with command, args, startup_timeout_sec = 20 and tool_timeout_sec = 150.

Ask your assistant

  • “What changed in my wallet since the last check?”

  • “Show my current Aerodrome voting positions and bounded rewards.”

  • “Compare the voting weights and gauge status of these pool addresses: …”

The server exposes 14 tools:

Tool

Purpose

aerodrome_pool_directory

Newest voting-pool registrations, paginated, with pair metadata

aerodrome_voting_incentives

Epoch deposits and conditional vote-allocation estimates in reward-token units

aerodrome_protocol_status

Official contract identity, block, epoch and protocol weights

aerodrome_voting_position

Configured or supplied veNFT voting positions

aerodrome_wallet_rewards

Current-vote reward scope and explicitly configured LP gauges

aerodrome_wallet_accounting

Receipt-backed escrow cash flows, selected voting-pool rewards and rebases, with independent end-block holdings

aerodrome_wallet_overview

Address-first balances, automatic veNFT discovery, locks, voting, rewards and an English brief

aerodrome_wallet_snapshot

All wallet sections at one block with a final block-hash recheck

aerodrome_compare_pools

2–16 distinct pool addresses; voting evidence, not investment ranking

aerodrome_wallet_changes

Capture with a UUID requestId; retry the same ID to recover the same report

aerodrome_wallet_report

Retrieve a saved report by reportId, without RPC or baseline changes

aerodrome_compare_allocations

Compare simultaneous splits and competing-vote sensitivity on one pinned block

aerodrome_decision_card

Export a private draft or explicitly selected allocation card

aerodrome_reward_plan

Bounded retention and direct-USDC quote scenarios for explicit veNFT selections; never executes a trade

Discover pools and inspect voting incentives (0.3)

aerodrome_pool_directory reads up to 16 registry slots (default 8), newest first. Use nextBeforeIndex as the next request's beforeIndex; the cursor advances over examined slots, including failed rows. To check registrations since a previous observation, pass its totalPoolCount as sinceIndex. A first page is not a complete market scan. Registry order means gauge registration, not token listing date or pool creation time. Pair token addresses are authoritative within the RPC evidence; symbols are untrusted labels. Missing metadata stays partial.

{"name":"aerodrome_pool_directory","arguments":{"limit":8}}

Use discovered or explicitly chosen addresses in aerodrome_voting_incentives (1–8 pools). With no scenario input it returns current-epoch deposited bribes and fees only. Reward-token scans are limited to 8 entries per contract by default (maximum 16); truncation and failed reads remain visible.

For hypothetical full allocation, supply 1–4 normal veNFT tokenIds. Current voting power is read on chain; existing balances in each reward contract are subtracted before adding the proposed allocation. Each pool is a separate alternative using all supplied voting power, not simultaneous allocations. This does not establish wallet ownership, eligibility, delegation or transaction success. Non-normal positions or unavailable inputs suppress estimates.

Alternatively, additionalVoteRaw models new marginal voting weight and does not remove any existing votes. It is mutually exclusive with tokenIds. Raw voting power uses the escrow token's units; do not pass a human-readable token amount as a raw integer.

{"name":"aerodrome_voting_incentives","arguments":{"pools":["0x0000000000000000000000000000000000000010"],"tokenIds":["1"]}}

The address and ID above are synthetic: replace them with actual discovered values. The response distinguishes deposited amounts from estimatedRewardRaw / estimatedRewardFormatted. candidateVoteRaw, removedExistingVoteRaw and scenarioDenominatorRaw expose the calculation. Full-allocation estimate per reward token:

depositedRaw * candidateVoteRaw / (totalSupplyRaw - removedExistingVoteRaw + candidateVoteRaw)

Integer division rounds down. Estimates are in each reward token separately; tokens must not be summed or ranked by raw amounts. Zero deposits now do not imply zero final-epoch rewards. Votes and deposits may change before epoch end. Actual claimable rewards use epoch-end checkpoints, not this current-state scenario. No token prices, USD APR, liquidity/volume ranking or guaranteed payout is provided. Unknown decimals leave formatted values null. Dead gauges remain visible with no estimates.

The source basis is the official Voter registration logic and Reward accounting. All RPC reads are pinned to one block, with a final hash recheck and bounded request lifetime.

One-address overview

{"name":"aerodrome_wallet_overview","arguments":{"wallet":"0x0000000000000000000000000000000000000002"}}

Use your own public address instead of the synthetic example. No manual veNFT IDs or local config are required. The result separates:

  • Liquid ETH, the escrow's underlying token (AERO), configured USDC and up to 16 extra tokens supplied by address. This is a bounded token list, not all assets in a wallet.

  • Up to 16 directly owned veNFTs from the official escrow owner list, with verified ownership, normal locked principal and unlock time.

  • Current voting power and epoch state. The normal voting window alone does not establish transaction eligibility or success.

  • Current-vote rewards and up to 16 explicitly supplied gauges. Configured gauges are inherited only for the same configured wallet. LP principal valuation, historical rewards, rebases and managed rewards are not included.

summary gives an English brief; structured values retain addresses, source links, raw amounts and the common observed block. Missing values are null. Failed sections leave independently verified sections available; a changed block hash rejects the whole observation. Managed positions have UNSUPPORTED_MANAGED and null personal principal: pooled balances must not be attributed to the wallet owner. No aggregate net worth is calculated.

decimalsSource distinguishes on-chain/canonical units from assumed or unknown units. New reward reads set amountFormatted=null if decimals are assumed; the raw amount remains available. Token labels are untrusted display data.

The overview is a fresh read and does not update local history. wallet_changes also tracks ETH, the escrow token (AERO), configured USDC, and lock principal/state for the explicitly configured veNFT IDs. These are bounded assets, not all wallet holdings. Newly discovered overview NFTs do not automatically change the history scope. New reports include findings: English explanations with codes, block interval and source links. They describe observations, not inferred deposits, sales or claimed income. Old reports remain retrievable and may have no findings or unit provenance.

Protocol basis: the official VotingEscrow implementation and interface define owner enumeration, lock tuples and managed escrow types. Runtime reads are pinned to a single Base block and rechecked; these source references are not a substitute for RPC verification.

Upgrading from 0.2.0

Use summary instead of summaryRu, and findings[].message instead of findings[].messageRu. All generated prose is English. Historical report findings are rendered in English from their stored structured evidence; report IDs, observations and raw changes remain unchanged. Retrieval does not rewrite the stored file or make RPC calls.

Read the result correctly

  • BASELINE_CREATED: no earlier snapshot exists. It does not mean no changes occurred.

  • COMPARED: changes relative to the last complete baseline. A new request ID updates that baseline. Reusing the same request ID returns the original report, including its original block interval.

  • PARTIAL: the report is saved, unavailable sections are not compared, and the previous complete baseline is retained.

  • When a configured veNFT has another owner, excludedTokenIds records its ID and observed owner. Other owned veNFT and configured gauge rewards are still returned. Rewards are marked partial; the voting section can still show the ownership change. A failed ownership RPC still fails the read; it is not evidence of a transfer.

  • Missing reward rows mean unknown, not zero. A reward decrease does not prove a claim or income.

  • Historical vote pools and historical unclaimed rewards are not scanned. Zero current rewards does not prove no historical rewards.

  • Raw amounts are authoritative within the RPC evidence. Token labels are untrusted; unverified decimals are identified and new reads leave their formatted amount null. Legacy reports may contain an older display fallback; retain raw amounts and provenance.

  • Voting weight is not APR. Prices, liquidity, volume and profitability are not calculated. Basis-point shares are rounded down; 0 bps can represent a positive share below 0.01%.

Balance and lock history (0.3)

Snapshots now include an optional assets section so old stored snapshots remain readable. Fresh reads include liquid ETH/AERO/USDC balances, configured lock principal, observed owner, permanence and unlock time at the same block as voting and rewards. Permanent locks use unlockAt=null; unsupported managed principal remains unknown.

Within one configured snapshot, identical successful contract reads at its pinned block are reused. The cache is bounded and discarded after the request; later snapshots read fresh data. Failed reads, chain checks and final block-hash verification are not cached. This reduces redundant RPC work but does not guarantee completion during public endpoint delays.

wallet_changes uses balances and locks sections. The first complete observation after a legacy snapshot returns initializedSections and SECTION_BASELINE_CREATED findings; it emits no inferred deposit or balance/lock delta. A subsequent complete snapshot can report changes. Missing/failed data is not zero. Partial sections are skipped and the last complete baseline is retained, while independently complete sections can still be compared. New values do not establish a transfer, sale, deposit or realized income. Token amounts are kept separate and formatted only with known compatible units.

Fresh captures write history version 3. Existing v1/v2 history and immutable reports remain readable, and report IDs are preserved. Old server versions cannot safely read/write this extended format: restart old clients before capturing into the live history with this build. Reads of saved old reports do not rewrite storage. A fresh snapshot missing asset coverage cannot replace an existing asset-aware baseline.

Capture, retry and read again (0.1.1)

Upgrade: stop older server processes before switching versions; mixed-version writers do not share the new canonical lock. aerodrome_wallet_changes now requires a client-generated UUID requestId. Generate it before sending the call and retain it until the response is received. Old calls with {} are rejected before any RPC or baseline update.

{"name":"aerodrome_wallet_changes","arguments":{"requestId":"a8098c1a-f86e-4b13-9ac8-83efbafec0d1"}}

If the response is lost, repeat that exact call. It returns the same saved report and never consumes the comparison twice. To read it later, including after server restart:

{"name":"aerodrome_wallet_report","arguments":{"reportId":"a8098c1a-f86e-4b13-9ac8-83efbafec0d1"}}

The example UUID is illustrative: use a fresh UUID only when deliberately requesting a new comparison. reportId equals the original requestId. reportSaved confirms the atomic commit; baselineSaved describes that original capture, not an update during replay. IDs are scoped to the configured wallet, veNFTs, gauges and contracts. Changing actual scope selects a different history; changing 1 to 01, address case, or gauge ordering does not.

Two processes share an exclusive scope lock acquired before RPC. A competing capture gets HISTORY_BUSY; retry with the same ID after the writer finishes. Already committed reports remain readable while a writer holds the lock. After an interrupted uncommitted capture, verify that its process has stopped before removing its leftover lock, then retry the same ID. RPC failure or cancellation before commit leaves the baseline and reports unchanged.

Local data and boundaries

config.json and .snapshot-history/ are local and git-ignored. History retains one complete baseline plus immutable change reports per configured scope, not every past snapshot. Report and baseline are stored together in one atomic replacement. Each scope is limited to 100 reports and 32 MB: HISTORY_FULL refuses new captures rather than evicting retry IDs. Existing reports remain readable. Archive the history locally before explicitly starting a new history; old IDs require the archived history and original scope. New history directories use 0700, files 0600, with atomic replacement and exclusive locks; files are not encrypted. Atomic replacement protects against process interruption; power-loss durability and network filesystems are not guaranteed. Corrupt history fails closed. Version 1 baselines are imported on the next successful capture; equivalent noncanonical files are retained. If several equivalent legacy baselines exist, capture stops for manual reconciliation rather than choosing one silently. After a crash, inspect the process before manually removing a leftover .lock.

wallet_changes writes local history (readOnlyHint=false); every tool is read-only on chain. No keys, signing, transactions, model calls, schedules or automatic farming. Public RPC endpoints see requested addresses, and the connected MCP client receives configured wallet evidence. Endpoints: mainnet.base.org, mainnet-preconf.base.org, base-rpc.publicnode.com.

RPC trust is required. A block-hash recheck is not a cryptographic proof of correctness or permanent finality. See SECURITY.md and CHANGELOG.md.

Development

npm test covers input bounds, partial evidence, block consistency, cancellation, RPC isolation, persistence and real cross-directory stdio startup. npm run demo exercises the user scenario through MCP without network calls. Dependencies are locked; install scripts are disabled.

Source and published releases: https://github.com/Alubiama/aerodrome-mcp-base . Installation is from source; this is not an npm-published package.

Reward token cards and retention plans (0.3)

aerodrome_reward_plan compares 1–3 selected pools as independent full-allocation scenarios for 1–4 explicit normal veNFT IDs. It reuses voting_incentives; it neither establishes ownership/voting eligibility nor predicts final epoch payouts.

Modes:

  • USDC: consider conversion of all observed scenario rewards to canonical Base USDC.

  • HOLD_SELECTED: retain all units of the exact preferredTokens addresses; consider conversion of the rest.

  • MIXED: retain keepBps / 10000 of each selected token's units; consider conversion of the remainder and all unselected tokens. This is not a portfolio percentage in USD. Rounding stays in integer token units; nothing is lost between retain and convert amounts.

Example arguments (replace the public addresses and veNFT IDs with the intended selection):

{
  "pools": ["0x0000000000000000000000000000000000000001"],
  "tokenIds": ["101"],
  "mode": "MIXED",
  "preferredTokens": ["0x940181a94A35A4569E4529A3CDfB74e38FD98631"],
  "keepBps": 2500,
  "slippageBps": 100,
  "includeMarket": true,
  "maxRewardTokens": 4
}

Preferences are request inputs, not persistent settings. The server never chooses tokens to hold automatically. includeMarket=true sends only reward token addresses to the fixed public Dexscreener API. Wallet addresses, veNFT IDs and research notes are not sent to it. The cards use a separately fetched indexer observation; fetch time is not proof that its price is fresh. The selected observed pair is not an exhaustive liquidity assessment. Prices, volume and project links do not establish token quality or sellability.

USDC quotes read the official classic Router's getAmountsOut at the reward block for two direct routes (stable and volatile, default factory). The greater available output is shown with a slippage-adjusted scenario amount. Missing or failing routes remain unknown; routeChecksComplete discloses incomplete route checks. Slipstream, multihop and other exchanges are not searched. Transfer taxes/restrictions, actual claimable balances, gas and claim costs are not simulated. netUsdcAfterGas is always null. A quote is not proof that a swap will succeed. Totals cover converted portions only, excluding retained tokens; do not rank different retention policies by USDC output alone. No transaction construction or execution is provided.

Each reward-token card includes market observations and research gaps for team, product, tokenomics, holders, contract control, sell restrictions and demand. The connected assistant can use its web research tools to investigate those topics and provide bounded researchNotes with token, topic, claim, source (HTTPS) and checkedAt (UTC). Prefer primary sources and distinguish project claims from independent corroboration. The MCP never follows those links or promotes claims to verified facts. Claims older than seven days receive STALE_SOURCE_CLAIM as a conservative review reminder, not a universal factual expiry; future-dated claims are flagged. Even supplied topics remain unverified. A card has no growth score or x10 prediction.

All missing research is visible. SCENARIO_ONLY describes calculation coverage, never safety or investment quality. Market failure is reported on the card without erasing independently read reward evidence. Unknown reward entries and truncated contracts prevent a complete USDC subtotal. Cards are capped at 16 tokens; omitted addresses are explicit. All on-chain reads have cancellation/deadline bounds and a final block-hash check. Nothing is published, traded, signed or written to wallet history by this tool.

Private SSH hosting

For a small private pilot, an SSH command can carry the existing stdio protocol directly. A public HTTP listener is not required. Run the compiled server as a dedicated unprivileged account, with a root-owned forced-command launcher and an SSH key restricted to that command. Give each future user a separate account, key, configuration and history directory; do not share the pilot identity.

npm run build emits JavaScript to dist/. Production installs need only the locked production dependencies and Node.js 24+. The launcher can set:

  • AERODROME_CONFIG_PATH: absolute path to that account's strict wallet configuration. An explicitly selected missing file is an error; it does not silently use public defaults.

  • AERODROME_HISTORY_DIR: absolute path to that account's private report directory. Existing local defaults remain unchanged when these variables are absent.

Keep code/runtime immutable to the service account, history private, and credentials outside the repository. A private pilot can restrict one active SSH session per account and cap the Node heap; these are not proof of capacity for public multi-user hosting. Stdio processes start when a client connects and stop when it disconnects. For Codex's command/args setup, see OpenAI's MCP documentation.

Historical cash-flow accounting

aerodrome_wallet_accounting answers what was paid into escrow, withdrawn, received as voting rewards, or credited as a rebase within an explicit block window and contract scope. Each accepted event has a transaction hash, block hash, protocol log index and matching ERC-20 transfer log index. Raw amounts are grouped by category and token with the contributing event IDs. Unknown decimals remain raw units.

{"name":"aerodrome_wallet_accounting","arguments":{"wallet":"0x0000000000000000000000000000000000000002","fromBlock":"40000000","toBlock":"40001999","blockSpan":2000,"tokenIds":["1"],"pools":[]}}

The address and ID above are synthetic; supply the public wallet, veNFT IDs and historical voting-pool addresses you actually want to inspect. With no explicit wallet, local wallet configuration is used. Configured IDs are inherited only for that same wallet; an explicit different wallet never inherits them. No automatic historical pool/veNFT discovery is performed. Empty pools means voting reward contracts were not scanned, not that no rewards were earned. At most eight pools and sixteen IDs are accepted. The selected pools' fee/bribe sources are verified through official Voter mappings at toBlock.

Pagination is deterministic and inclusive: use returned nextFromBlock with the same wallet, IDs, pools and fixed toBlock. The default page is 2,000 blocks, configurable from 1 to 10,000. A partial page returns retryFromBlock and no continuation; retry that page with a smaller span or after RPC recovery. Deduplicate events by id when combining retries. Limits are 500 protocol events and 32 receipt attempts per call. All totals are page sums, not lifetime totals. A successful empty scan covers only the reported sources and block window. RPC providers may impose smaller log limits.

Categories:

  • WALLET_DEPOSIT: a wallet-funded escrow deposit, which may fund someone else's veNFT. It is not the purchase cost of AERO.

  • WALLET_WITHDRAWAL: escrow principal paid to the wallet.

  • VOTING_REWARD_RECEIVED: matching gross transfer from a verified selected pool's voting reward contract.

  • REBASE_RECEIVED: a selected veNFT's rebase paid directly to this wallet, e.g. after lock expiry.

  • SELECTED_POSITION_REBASE_LOCKED: a rebase credited to the selected veNFT's locked principal. Ownership must match the wallet both before and after the event block, with no NFT transfers anywhere in that block. Otherwise the event is excluded. This is not liquid wallet income.

  • UNVERIFIED_EVENT: receipt, provenance or transfer matching did not verify; excluded from sums. Zero-value verified protocol events require no transfer and represent no cash movement.

currentHoldings independently reads ETH/AERO/USDC and selected normal locks at toBlock; it is not a calculated remainder from the reported flows, and it is not a balance of every reward token. Never sum the repeated holdings across pages. Historical ownership reads and a no-transfer check gate rebase totals; same-block mint/transfer cases are conservatively excluded. NFT ownership transfers, split/merge/managed positions, LP principal, external vaults, swaps, opening balances, gas, cost basis and USD valuation are not reconciled. netProfitUsd stays null. Contract mappings are resolved at the end block, so replaced historical reward sources remain outside scope. RPC log completeness is trusted; accepted events are checked against successful receipts and canonical block responses, not cryptographic inclusion proofs. Non-standard tokens may report transfers that do not equal net wallet balance changes.

The event layouts and classification are based on the official VotingEscrow interface, Reward implementation and RewardsDistributor implementation. No wallet signing, paid scanner, external model or local history write is used by this tool.

Compare simultaneous voting allocations

aerodrome_compare_allocations compares 1–4 explicit scenarios across 1–5 distinct pools for 1–4 normal veNFTs. Each weightsBps array follows the input pool order and must sum to 10000 (100%). The same split applies to each supplied veNFT. This is a comparison, not an optimizer or a voting transaction.

{
  "pools": ["0x0000000000000000000000000000000000000010", "0x0000000000000000000000000000000000000011"],
  "tokenIds": ["1"],
  "scenarios": [
    {"name": "Equal split", "weightsBps": [5000, 5000]},
    {"name": "First pool only", "weightsBps": [10000, 0]}
  ]
}

Addresses and ID above are synthetic. Replace them with selected public pool addresses and veNFT IDs. All scenarios reuse one block-pinned evidence read. Each pool's denominator subtracts the supplied veNFTs' existing reward-contract balances and adds their proposed allocated votes. Vote and reward rounding are per veNFT; vote dust is exposed as unallocatedRoundingRaw. Per-token raw subtotals group only identical token addresses and carry a completeness flag. Failed or truncated reads are not zero rewards; missing decimals suppress formatted values. The nested evidence contains the original independent full-allocation estimates; use scenarios for simultaneous split results.

No token-value ranking, USD total, fee forecast, ownership/eligibility check, transaction simulation, or execution is provided. Current deposits and votes can change; these scenarios are not claimable amounts or guaranteed epoch-end payouts.

Every allocation scenario now includes sensitivity for +20%, +50% and +100% competing votes. For each reward contract, competing weight is totalSupplyRaw - removedExistingVoteRaw; added competing weight is floored in raw units. Deposits and proposed own votes stay fixed. All supplied veNFTs share the same denominator, while their reward amounts are floored individually. No additional RPC reads are needed.

Each stress result preserves per-token subtotals and completeness. tokenChanges exposes the decrease in raw units and basis points; percentage decrease is null when the baseline is zero. Partial-subtotal changes are not complete portfolio changes. Zero observed competing votes remain zero under proportional stress, which does not exclude new voters. These are uniform hypothetical stresses, not forecasts, guaranteed bounds, or a model of where new votes will actually go.

Private decision cards

aerodrome_decision_card accepts { "allocation": <compare_allocations input>, "selectedScenario": "optional exact scenario name", "reason": "your reason" }. Omit selectedScenario for a DRAFT. Only supply it after the user explicitly chooses; selection also requires a nonempty reason. USER_SELECTED records the caller's assertion, not verified human approval or an executed vote. The tool fetches one pinned evidence set and returns the card without writing files.

The card keeps input, comparison, sensitivity, block provenance and a SHA-256 content checksum. The checksum detects accidental changes; it is not a signature or independent authenticity check. To save a card response locally, export only its structuredContent as JSON, then run:

npm run --silent save-card < /path/to/private-card.json

This writes an exclusive, non-overwriting .decision-cards/<checksum>.json file with owner-only permissions. Cards contain position identifiers and your reasoning: keep them private. They are excluded from Git and the package. A saved card does not establish future payouts or profit. After an epoch, accounting receipts must be checked separately; automatic outcome attribution is not part of this release.

Try the entire generation/save flow offline with synthetic data:

npm run --silent demo:allocations | npm run --silent save-card

This demonstrates DRAFT cards, two simultaneous splits, three competing-vote stress levels and private saving. It uses an in-memory MCP connection, no network or real wallet. Repeating the exact same demo refuses to overwrite the identical card.

For integrators

Start with the stdio example and integration guide, the interactive synthetic panel in integration-demo/, and the proposed external pilot. Run npm run demo:integration:build to regenerate the panel data through MCP and verify its arithmetic. This is an offline integration example, not a live dashboard or hosted API.

Available Tools

14 tools
aerodrome_compare_allocationsCompare simultaneous veAERO pool allocationsA
Read-onlyIdempotent

Compare 1–4 user-specified basis-point splits across 1–5 explicit pools for 1–4 normal veNFTs using one block. Same split per NFT; subtract existing votes, round per NFT, preserve per-token partial subtotals. Includes hypothetical +20/50/100% competing-vote sensitivity with own votes and deposits fixed; not forecasts. Evidence includes independent full-allocation estimates: use scenarios for split results. No optimizer, USD ranking, eligibility or guaranteed earnings.

ParametersJSON Schema
NameRequiredDescriptionDefault
poolsYes
tokenIdsYes
scenariosYes
maxRewardTokensNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
evidenceYes
readOnlyYes
warningsYes
scenariosYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the read-only/idempotent annotations by disclosing the exact comparison algorithm: same split per NFT, subtracting existing votes, rounding per NFT, preserving per-token partial subtotals, and fixing own votes and deposits for sensitivity. It also clarifies that the hypothetical sensitivity is not a forecast, which is important for correct interpretation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The main capability is front-loaded and the caveats are grouped into short, purposeful sentences. Some phrasing, especially 'Evidence includes independent full-allocation estimates: use scenarios for split results,' is dense and less clear, but overall there is little wasted text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a comparison tool with an output schema and safety annotations, the description covers the algorithm, scope, and limitations well. It is incomplete mainly because maxRewardTokens is left unexplained and the pool-count mismatch with the schema creates ambiguity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description carries most of the semantic burden and does so well for the key parameters: scenarios are basis-point splits, pools are explicit and limited, and tokenIds are normal veNFTs. However, maxRewardTokens is not mentioned, and the stated '1–5 explicit pools' appears inconsistent with the schema's pools maxItems of 8.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource, then quantifies the scope: 1–4 basis-point splits, 1–5 pools, 1–4 veNFTs, one block. It clearly differentiates this from sibling tools by stating it is not an optimizer and does not provide USD ranking or eligibility.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-not guidance: it is not a forecast, it uses fixed hypothetical sensitivity scenarios, and it lacks optimizer, USD ranking, eligibility, and guaranteed earnings. It does not explicitly name an alternative sibling tool for those needs, so it stops short of fully explicit alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_compare_poolsCompare selected Aerodrome poolsA
Read-onlyIdempotent

Compare 2–16 distinct pool addresses using official Voter weights, protocol weight shares, gauge registration/liveness and reward contract addresses at one Base block. Preserves input order. Unknown data stays null; no yield, liquidity or profitability ranking.

ParametersJSON Schema
NameRequiredDescriptionDefault
poolsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
epochYes
poolsYes
voterYes
statusYes
chainIdYes
coverageYes
readOnlyYes
warningsYes
observationYes
totalProtocolWeightRawYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds real behavioral value beyond that: deterministic output ordering ('Preserves input order'), explicit null semantics for missing data ('Unknown data stays null'), single-block snapshot semantics, and a disclaimer that no ranking is produced.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences, each carrying distinct information (what is compared, ordering/null behavior, what is excluded). Front-loaded with the core operation and free of filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, and annotations cover the safety profile. The description supplies the remaining essentials: input cardinality, uniqueness, ordering guarantees, null handling, and scope exclusions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only one parameter at 0% schema description coverage, the description carries the semantic load and does so: it states the count bounds (2–16, matching minItems/maxItems), the 'distinct' uniqueness requirement the schema does not enforce, and that input order is preserved in output. Address format is left to the schema's regex.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb (Compare), a bounded resource (2–16 distinct Aerodrome pool addresses), and enumerates exactly what is compared (Voter weights, protocol weight shares, gauge registration/liveness, reward contracts). This clearly separates it from the wallet- and protocol-oriented siblings, which none of them do.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It sets explicit boundaries on what this tool is for ('no yield, liquidity or profitability ranking') and constrains the input shape ('2–16 distinct pool addresses ... at one Base block'), giving clear context for when it applies. It does not, however, point to an alternative tool for the excluded analyses, so it stops short of explicit when-not/alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_decision_cardPrivate allocation decision cardA
Read-onlyIdempotent

Return an exportable decision card with allocation evidence, sensitivity and content checksum. Default DRAFT. Set selectedScenario and reason only when explicitly chosen by the user. USER_SELECTED is a caller assertion, never a transaction or recommendation. No disk writes; save privately with the local save-card command. Never publish cards.

ParametersJSON Schema
NameRequiredDescriptionDefault
reasonNo
allocationYes
selectedScenarioNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
inputYes
cardIdYes
readOnlyYes
comparisonYes
limitationsYes
schemaVersionYes
decisionStatusYes

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds substantial behavioral context beyond the readOnlyHint, openWorldHint, and idempotentHint annotations. It discloses default state ('Default DRAFT'), caller assertion semantics ('USER_SELECTED is a caller assertion, never a transaction or recommendation'), and persistence behavior ('No disk writes; save privately with the local save-card command. Never publish cards.'). There is no contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is four tightly written sentences with no filler. It front-loads the core purpose, then states the essential usage caveats and persistence rules. Every sentence carries meaningful, non-redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers status defaults, caller assertion semantics, disk-write behavior, and the save-card alternative, which is strong contextual coverage especially given the annotations and output schema. The main gap is the undocumented meaning of the required allocation object, which relies on the schema's structural names. Overall, an agent can likely select and invoke the tool correctly in most cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description must compensate, but it only addresses selectedScenario and reason. The required allocation parameter, including its nested pools, tokenIds, scenarios, and weightsBps, receives no semantic explanation in the description. The schema provides structure but not the meaning needed to construct a valid allocation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Return an exportable decision card with allocation evidence, sensitivity and content checksum.' It clearly identifies the tool's output and purpose. It does not explicitly contrast with sibling tools, but the decision-card deliverable is distinct enough to be recognizable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit conditions on when to set fields: 'Set selectedScenario and reason only when explicitly chosen by the user.' It also provides guidance on what not to do and an alternative action: 'No disk writes; save privately with the local save-card command. Never publish cards.' It does not name sibling tools as alternatives, but it offers clear context and exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_pool_directoryRecently registered Aerodrome voting poolsA
Read-onlyIdempotent

Browse bounded pages of official Voter pool registrations, newest index first, with token pair metadata and gauge state. Registration order is not token listing or pool creation time. Preserve partial rows and pagination coverage.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
sinceIndexNo
beforeIndexNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
poolsYes
voterYes
statusYes
chainIdYes
hasMoreYes
scannedYes
sourcesYes
coverageYes
readOnlyYes
warningsYes
observationYes
totalPoolCountYes
nextBeforeIndexYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only, idempotent, and non-destructive behavior. The description adds a useful caveat that registration order is not token listing or pool creation time, and instructs to preserve partial rows and pagination coverage—valuable beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that front-loads the primary purpose and adds necessary caveats without excess wording. It could be more structured but is concise and clear.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with three parameters and no schema descriptions, the description must explain pagination mechanics. It fails to clarify how sinceIndex/beforeIndex work or that limit sets page size. An agent cannot reliably use the tool without guessing, despite the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description does not explain the meaning of sinceIndex or beforeIndex. It mentions 'bounded pages' and 'pagination coverage' but does not define cursor parameters or explicitly tie limit to page size, leaving the agent to infer from names alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'browse' and the resource 'official Voter pool registrations', with specifics on ordering (newest index first) and data included (token pair metadata and gauge state). It distinguishes from siblings by focusing on the pool directory rather than positions, rewards, or wallet data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear context: this tool is for browsing bounded pages of official registrations, not general token listings. However, it does not explicitly name alternatives or state when not to use it, only implies that ordering differs from other sources.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_protocol_statusAerodrome protocol statusA
Read-onlyIdempotent

Verify official configured Aerodrome contracts, Base block, vote totals, pool count, and the current epoch window at one block.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds genuine context by noting the read happens 'at one block,' implying a consistent point-in-time snapshot, but says nothing about freshness, caching, or failure modes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence that enumerates the returned data without filler or redundancy. Every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no parameters and no output schema, the description must convey what the call yields, and it does so by listing the five data points. It is complete enough to invoke correctly, though it stops short of explaining return structure or error conditions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the schema has nothing to document and the baseline of 4 applies. The description appropriately adds no parameter information because none is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Verify') plus an enumerated resource set (contracts, block, vote totals, pool count, epoch window), so the agent knows exactly what this tool surfaces. It doesn't explicitly name which sibling it differs from, but the protocol-wide scope clearly contrasts with the wallet/voting siblings' narrower focus.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to reach for this tool versus the six sibling tools, nor any stated prerequisites or exclusions. Usage is only implied by the content it reports.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_reward_planReward token cards and retention scenariosA
Read-onlyIdempotent

Compare 1–3 independent full-veNFT reward allocations in USDC, HOLD_SELECTED or MIXED mode. Retain explicitly selected token addresses; MIXED keepBps applies to each selected token's units. Fetch bounded public Base-token market cards from Dexscreener (token addresses only); includeMarket=false skips this external source. Attach dated client-researched source claims, never automatically verified. Quote direct classic USDC routes at the reward block; no net-after-gas, guaranteed sellability, growth score or execution. Missing research and quotes remain unknown.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeYes
poolsYes
keepBpsNoMIXED only: fraction of each selected token's units to retain, not a portfolio USD allocation.
tokenIdsYes
slippageBpsNo
includeMarketNo
researchNotesNoClient-researched source claims. The server does not verify them or follow these URLs.
maxRewardTokensNo
preferredTokensNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
poolsYes
statusYes
chainIdYes
keepBpsYes
coverageYes
readOnlyYes
warningsYes
incentivesYes
tokenCardsYes
observationYes
slippageBpsYes
omittedCardTokensYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Even though annotations already declare readOnly, openWorld, idempotent, and non-destructive behavior, the description adds meaningful operational limits: market data is fetched from Dexscreener only for token addresses, includeMarket=false disables it, research claims are never verified, and no execution guarantees are made. This is far more than the annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well-structured, front-loading the core comparison purpose before layering in retention mode specifics, external data behavior, and limitations. Every sentence adds information without repeating the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex 9-parameter tool, the description covers the most important execution-relevant semantics, external data dependencies, research-note handling, and explicit non-guarantees, while an output schema covers result expectations. A small gap remains around preferredTokens and maxRewardTokens behavior, but the description is largely complete and actionable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 22% schema coverage, the description compensates well by explaining key parameter meaning: keepBps applies to each selected token's units, includeMarket=false skips Dexscreener, researchNotes are unverified client claims, and selected token addresses are retained in HOLD_SELECTED/MIXED modes. It does not clarify slippageBps, maxRewardTokens, or preferredTokens, so it is not a full substitute for schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action and resource: comparing 1–3 independent full-veNFT reward allocations across USDC, HOLD_SELECTED, and MIXED modes. The title and details about retention scenarios clearly separate this from sibling tools like wallet rewards or voting incentives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context for when to call this tool and what it is for, including mode-specific behavior, external Dexscreener fetching, and explicit non-goals such as 'no net-after-gas, guaranteed sellability, growth score or execution.' It does not explicitly name alternative sibling tools or state when not to use them, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_voting_incentivesEpoch voting incentives and vote allocation scenariosA
Read-onlyIdempotent

Read deposited bribes and fees for 1–8 explicit pools at one block. Optionally estimate rewards for additional new votes or full allocation of 1–4 explicit normal veNFTs, subtracting their existing reward-contract weights. Each pool is an independent hypothetical allocation; no ownership/eligibility, claimable reward, guaranteed payout or APR claim. No cross-token value ranking.

ParametersJSON Schema
NameRequiredDescriptionDefault
poolsYes
tokenIdsNo
maxRewardTokensNo
additionalVoteRawNoHypothetical NEW marginal votes; it does not read or remove existing wallet allocations.

Output Schema

ParametersJSON Schema
NameRequiredDescription
poolsYes
voterYes
statusYes
chainIdYes
coverageYes
readOnlyYes
scenarioYes
tokenIdsYes
warningsYes
epochStartYes
observationYes
tokenPositionsYes
maxRewardTokensYes
candidateVoteRawYes
additionalVoteRawYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive, so the description adds value by detailing the 'at one block' snapshot, the independence of each pool's hypothetical allocation, and the explicit disclaimer that no ownership/eligibility or guaranteed payout is claimed. This goes beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is four sentences, front-loaded with the core read action, then the optional estimation, then disclaimers. No fluff; each sentence serves a purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The output schema covers return values, and annotations cover safety. However, the description does not explain the maxRewardTokens parameter, and it does not mention how the block is chosen (though it says 'at one block'). For a tool with this complexity, the missing parameter semantics is a notable gap, so it's not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 25% (only additionalVoteRaw has a description). The description text clarifies pools and veNFTs (tokenIds) and hypothetical votes (additionalVoteRaw), but maxRewardTokens is not explained anywhere. The description partially compensates for the low schema coverage but leaves a gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reads deposited bribes and fees for 1-8 explicit pools at a specific block, and optionally estimates rewards for additional votes or full allocation of veNFTs. It is specific about the action, resource, and scope, and the disclaimers (no ownership/eligibility, no APR) help differentiate it from wallet-focused siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context on what the tool does (read bribes/fees and estimate hypothetical rewards) but does not explicitly state when to use it over siblings like aerodrome_voting_position or aerodrome_wallet_rewards. It implies usage for scenario analysis but lacks explicit alternatives or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_voting_positionAerodrome voting positionA
Read-onlyIdempotent

Read current veNFT voting power, pool allocations, pool weight shares, gauge liveness, and epoch timing. Uses configured token IDs when none are supplied.

ParametersJSON Schema
NameRequiredDescriptionDefault
tokenIdsNoOptional public veNFT token IDs; at most 16.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, and open-world behavior, so the safety profile is covered. The description adds a genuinely useful behavioral detail beyond the annotations: when no tokenIds are passed it falls back to configured token IDs, and it discloses the breadth of returned data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with no waste, the primary read action front-loaded and the fallback behavior stated second. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, and the description compensates by enumerating the returned fields, which is what an agent needs to decide to call it. A brief note on whether results require a wallet/address context or how multiple token IDs aggregate would make it fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With a single parameter at 100% schema coverage the baseline is 3, but the description adds meaning the schema lacks: the tokenIds list is optional and defaults to a configured set when omitted. That defaulting behavior is real semantic value beyond the schema's 'Optional' label.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Read') and a well-scoped resource (veNFT voting position), then enumerates the exact data returned: voting power, pool allocations, pool weight shares, gauge liveness, and epoch timing. It is clearly distinguishable from siblings like wallet_rewards or protocol_status, though it does not explicitly name or contrast with any sibling tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when the tool applies (checking a veNFT's voting state) but gives no explicit when-to-use guidance or alternatives versus the other aerodrome_* tools. The only actionable direction is the fallback rule about configured token IDs, which is usage-adjacent but not a selection criterion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_wallet_accountingHistorical Aerodrome cash flows and holdingsA
Read-onlyIdempotent

Read a bounded Base block page of wallet escrow deposits/withdrawals, selected veNFT rebases and explicit voting-pool reward receipts. Verify protocol logs against successful receipts and matching ERC-20 transfers. Return per-token page sums, event links, gaps and separate holdings at fixed toBlock. Not lifetime discovery, LP accounting, cost basis or net profit. On PARTIAL retry the same page; otherwise continue with nextFromBlock and unchanged scope/toBlock.

ParametersJSON Schema
NameRequiredDescriptionDefault
poolsNoExplicit historical voting pools. Only fee/bribe reward contracts verified through Voter mappings at the end block are scanned; omitted pools are not zero rewards.
walletNo
toBlockNoFixed inclusive end block; defaults to current Base block. Reuse returned toBlock across pages.
tokenIdsNoSelected veNFT IDs for rebase history and current locks. Defaults to local IDs only for the configured wallet. Historical ownership is verified before rebase totals.
blockSpanNo
fromBlockYesInclusive first Base block to inspect. History is paginated by block, not inferred from snapshots.

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageYes
scopeYes
eventsYes
statusYes
totalsYes
walletYes
chainIdYes
sourcesYes
summaryYes
readOnlyYes
warningsYes
observationYes
reconciliationYes
currentHoldingsYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and non-destructive. The description adds meaningful behavioral context: it verifies protocol logs against receipts and ERC-20 transfers, returns gaps, and follows a specific retry pattern (PARTIAL → retry same page, else nextFromBlock). It also states the scope remains unchanged, which is important for pagination. This goes beyond the annotations and provides transparency about how the tool behaves during a multi-page walk. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is four sentences, each carrying distinct value: scope, verification behavior, outputs, and exclusions/pagination. It is front-loaded with the primary action and immediately states the resource and its boundaries. No filler or repetition; every clause earns its place. This is exemplary conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's scope, verification, outputs, pagination, and exclusions. The output schema and annotations already provide return types and safety profile. However, it does not explicitly explain the wallet parameter (beyond the 'configured wallet' mention in tokenIds schema) or the exact meaning of blockSpan, though these are secondary. For an agent, the description gives enough to call the tool correctly across pages, but a tiny bit more on the wallet override and blockSpan would push it to a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67% (4 of 6 parameters have descriptions). The description adds contextual meaning by tying parameters to the tool's behavior: 'selected veNFT rebases' relates to tokenIds, 'explicit voting-pool reward receipts' to pools, and 'fixed toBlock'/'nextFromBlock' to toBlock/fromBlock. It also clarifies that history is paginated by block (complementing fromBlock's schema description). While it doesn't elaborate on blockSpan or wallet (both lacking schema descriptions), the description does not duplicate schema info and provides a cohesive usage model. Given the high coverage baseline of 3, the added context justifies a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Read a bounded Base block page of wallet escrow deposits/withdrawals, selected veNFT rebases and explicit voting-pool reward receipts.' It further clarifies outputs (per-token page sums, event links, gaps, holdings at fixed toBlock) and explicitly excludes lifetime discovery, LP accounting, cost basis, and net profit, which distinguishes it from sibling tools like aerodrome_wallet_rewards, aerodrome_wallet_snapshot, and aerodrome_wallet_report. This is a precise and unambiguous statement of purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear usage boundaries: it is for a bounded page of history, not lifetime discovery, and explicitly excludes LP accounting, cost basis, and net profit. It also provides pagination guidance: 'On PARTIAL retry the same page; otherwise continue with nextFromBlock and unchanged scope/toBlock.' While it doesn't name specific alternative tools, the exclusions implicitly route the agent to other tools for those tasks, and the pagination instructions are concrete. This is more than minimal guidance, though it stops short of explicitly naming siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_wallet_changesWallet changes since last complete snapshotA
Idempotent

Compare configured voting/rewards plus bounded liquid balances and locks using a caller-generated UUID requestId. Old snapshots without assets initialize the new sections without inferred changes. Reuse the SAME ID for retries: returns the saved report without RPC. A new ID advances the baseline only for a complete snapshot. Report and baseline commit atomically; partial reports are saved without replacing the baseline. This tool writes local history but never changes blockchain state. Missing reward rows are unknown, not zero or proof of claims.

ParametersJSON Schema
NameRequiredDescriptionDefault
requestIdYesGenerate one UUID before capture. Reuse it on every retry; use a new UUID only for a new comparison.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
chainIdYes
changesYes
findingsYes
reportIdYes
warningsYes
observationYes
reportSavedYes
epochChangedYes
baselineSavedYes
blockchainReadOnlyYes
initializedSectionsNo
previousObservationYes
unavailableSectionsYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Although annotations indicate idempotentHint=true and openWorldHint=true, the description adds valuable context beyond these: it explains the atomic commit of report and baseline, partial report saving behavior, and that the tool writes local history but does not mutate blockchain state. This aligns with annotations (idempotent, open world) and adds specific nuances around retries and snapshot baselines.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but highly informative, with each sentence adding key operational detail. It front-loads the core comparison function and then efficiently covers retry semantics, snapshot initialization, atomicity, and interpretational caveats. No filler or redundant content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (state comparison, idempotency, atomic commits) and that it has an output schema, the description covers all necessary operational aspects: how to use requestId, what happens on retries, baseline behavior, local vs blockchain state, and how to interpret missing data. It is complete for an agent to correctly select and invoke the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description significantly enriches the parameter semantics beyond the schema. While the schema specifies 'requestId' as a UUID with format/pattern, the description explains the functional role: generate a new UUID for a new comparison and reuse it for retries to fetch the saved report. This is critical for correct usage and goes far beyond the schema's type/format information.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool's purpose: comparing wallet state (voting/rewards, liquid balances, locks) since the last complete snapshot. It distinguishes itself from siblings by focusing on 'changes since last snapshot' and mentions a caller-generated UUID for idempotent retries, which is unique among the sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance: use the same UUID for retries to avoid re-running RPC calls, and use a new UUID for a new comparison. It also clarifies the behavior for old snapshots without assets and emphasizes that missing reward rows are 'unknown, not zero', which guides interpretation of results.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_wallet_overviewWallet overview from one addressA
Read-onlyIdempotent

Discover up to 16 owned veNFTs directly from the official escrow. Report ETH, escrow-token, USDC and selected token balances, normal locked principal, voting state and bounded rewards at one block. Includes an English brief. No wallet config or manual veNFT IDs needed when wallet is supplied. Preserve partial and managed-position limits; no total net worth or APR.

ParametersJSON Schema
NameRequiredDescriptionDefault
gaugesNoOptional LP reward gauges, at most 16. Gauge discovery and LP principal valuation are not included.
tokensNoAdditional ERC-20 balances, at most 16. ETH, escrow token and configured USDC are included by default.
walletNoPublic wallet address; defaults to local configuration. No veNFT IDs required.

Output Schema

ParametersJSON Schema
NameRequiredDescription
locksYes
statusYes
votingYes
walletYes
chainIdYes
rewardsYes
summaryYes
coverageYes
protocolYes
readOnlyYes
warningsYes
discoveryYes
observationYes
liquidBalancesYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive. The description adds meaningful behavioral context: it reports at one block, includes an English brief, discovers veNFTs from the official escrow, and explicitly excludes total net worth and APR. This goes beyond the annotations and helps the agent understand scope and limitations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with the core purpose front-loaded, followed by scope, features, and exclusions. It is not overly verbose, though it could be tightened. Each sentence adds information about capabilities or limitations, earning its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (3 optional params), the description covers the main behavioral aspects: what it reports, prerequisites, and exclusions. The output schema is present, so return details are not needed. It is complete enough for an agent to decide whether to use it and to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds only marginal value: it mentions 'wallet supplied' and 'no veNFT IDs required,' which is already in the schema's wallet description. It does not elaborate on gauges or tokens beyond what the schema provides. No additional semantics beyond schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description specifies a clear action (discover, report) on a specific resource (wallet overview, veNFTs, balances) and distinguishes it from siblings by explicitly stating exclusions ('no total net worth or APR') and the convenience of not needing config or manual veNFT IDs. An agent can immediately understand this is a one-block wallet snapshot.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states that no wallet config or manual veNFT IDs are needed when a wallet is supplied, indicating when it's appropriate. It also hints at limitations ('Preserve partial and managed-position limits; no total net worth or APR') but does not explicitly name alternative tools or provide when-not-to-use guidance. Clear context but lacks explicit routing to siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_wallet_reportRead a saved wallet change reportA
Read-onlyIdempotent

Retrieve a committed report by reportId (the original requestId) within the configured wallet scope. No RPC, capture or baseline change. Available after restart and while another capture is running.

ParametersJSON Schema
NameRequiredDescriptionDefault
reportIdYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
chainIdYes
changesYes
findingsYes
reportIdYes
warningsYes
observationYes
reportSavedYes
epochChangedYes
baselineSavedYes
blockchainReadOnlyYes
initializedSectionsNo
previousObservationYes
unavailableSectionsYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is known. The description adds valuable context: it clarifies that the operation does not affect RPC, capture, or baseline, and that it is available even during captures and after restart. This goes beyond the annotations and helps an agent understand operational constraints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, with the primary action front-loaded: 'Retrieve a committed report by reportId'. It then adds two concise clarifications (no side effects and availability) without redundancy. Every sentence earns its place, making it an efficiently structured description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with one parameter and an existing output schema, the description covers the essential operational aspects: it retrieves a committed report, is read-only, and is available under specific conditions. It does not mention error handling or return format, but the output schema presumably covers that. The description is sufficiently complete for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explicitly explains that reportId is the original requestId, which is a meaningful semantic clarification beyond the raw schema. While it does not detail the UUID format (already in the pattern), this mapping is crucial for correct usage, giving the description significant added value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves a committed report by reportId, with the specific resource being a saved wallet change report. It distinguishes itself from sibling tools by focusing on reading a previously saved report rather than creating or modifying data, though it does not explicitly name an alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides context on when the tool is available (after restart and during another capture) and states it does not change RPC, capture, or baseline. However, it does not explicitly compare against sibling tools or specify scenarios where this tool is preferred over others, leaving some ambiguity for an agent deciding between tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_wallet_rewardsAerodrome wallet rewardsA
Read-onlyIdempotent

Read claimable voting rewards for configured veNFT current votes and LP rewards for explicitly configured gauges. Historical vote pools are intentionally not scanned.

ParametersJSON Schema
NameRequiredDescriptionDefault
maxItemsNo
includeZeroNo

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, openWorld and non-destructive, so the safety profile is covered. The description adds real behavioral scope beyond that: rewards are claimable, coverage is limited to configured veNFT current votes and explicitly configured gauges, and historical pools are deliberately skipped — a meaningful data-coverage disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler, and the primary scope statement is front-loaded before the exclusion. Every clause carries information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, but the description adequately covers what is returned, so return-value explanation is not required. The gap is parameter behavior: with two undocumented, non-obvious parameters and no annotations covering them, the definition is adequate but not complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and neither parameter is mentioned in the description. maxItems (pagination/limit, 1-200, default 100) and includeZero (whether zero-value rewards are returned) are left entirely unexplained, and the description does nothing to compensate for that gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Read') and two concrete resources (claimable voting rewards for configured veNFT current votes, LP rewards for explicitly configured gauges), so the agent knows exactly what is returned. It does not name or contrast with any sibling such as aerodrome_voting_position or aerodrome_wallet_report, so the 5-level sibling differentiation is missing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The clause 'Historical vote pools are intentionally not scanned' implies a usage boundary and tells the agent this is not a historical/backfill query. However, no alternative tool is named and there is no explicit 'use this when X, use Y when Z' routing, so usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aerodrome_wallet_snapshotAerodrome coherent wallet snapshotA
Read-onlyIdempotent

Read protocol, configured veNFT positions, bounded rewards, ETH/AERO/USDC balances and configured lock principal at one Base block, including token display metadata. Recheck the block hash before returning. Preserve PARTIAL status and historical coverage limits.

ParametersJSON Schema
NameRequiredDescriptionDefault
maxItemsNo
includeZeroNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
assetsNo
statusYes
votingYes
chainIdYes
rewardsYes
coverageYes
protocolYes
readOnlyYes
warningsYes
observationYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context: it rechecks the block hash before returning (consistency guarantee) and preserves PARTIAL status and historical coverage limits, which are non-obvious behaviors an agent needs to know.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense sentence followed by two short imperative clauses. It front-loads the core purpose and packs significant detail (block consistency, metadata, status preservation) without wasted words. The final sentence about PARTIAL status and historical coverage limits is terse but meaningful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has an output schema and annotations covering safety, the description covers the key behavioral guarantees (single-block coherence, block hash recheck, status preservation). It does not explain the two parameters, but they are simple and self-explanatory. The description is complete enough for an agent to select and invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden for parameter meaning, but it does not explain maxItems or includeZero. However, the parameter names are fairly self-explanatory and the description's mention of 'including token display metadata' and 'historical coverage limits' indirectly relates to includeZero and maxItems. Baseline 3 is appropriate because the description adds some context but does not explicitly document the parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('Read') and a clear resource: a coherent wallet snapshot at one Base block, enumerating veNFT positions, rewards, balances, lock principal, and token metadata. It distinguishes itself from siblings by emphasizing coherence at a single block and the inclusion of display metadata, though it does not explicitly name a sibling alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for obtaining a consistent point-in-time snapshot and mentions preserving PARTIAL status and historical coverage limits, which hints at when it is appropriate. However, it does not explicitly state when to use this tool versus siblings like aerodrome_wallet_overview or aerodrome_wallet_report, nor does it state exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.5.2
    • Addedaerodrome_compare_allocations
    • Addedaerodrome_decision_card
  2. 8 tool updatesv0.3.0
    • Addedaerodrome_pool_directory
    • Addedaerodrome_reward_plan
    • Addedaerodrome_voting_incentives
    • Addedaerodrome_wallet_accounting
    • Changedaerodrome_wallet_changes5 fields changed
      • changedOutput schema / properties / changes / items / properties / section / enum
        Previous value: -[
        -  "protocol",
        -  "voting",
        -  "rewards"
        -]New value: +[
        +  "protocol",
        +  "voting",
        +  "rewards",
        +  "balances",
        +  "locks"
        +]
      • addedOutput schema / properties / findings
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "enum": [
        +          "BASELINE_CREATED",
        +          "SECTION_UNAVAILABLE",
        +          "EPOCH_CHANGED",
        +          "OWNER_CHANGED",
        +          "VOTING_POWER_CHANGED",
        +          "REWARD_CHANGED",
        +          "ROW_APPEARED",
        +          "ROW_NO_LONGER_OBSERVED",
        +          "VALUE_CHANGED",
        +          "SECTION_BASELINE_CREATED",
        +          "BALANCE_CHANGED",
        +          "LOCK_CHANGED"
        +        ],
        +        "type": "string"
        +      },
        +      "decimals": {
        +        "anyOf": [
        +          {
        +            "maximum": 36,
        +            "minimum": 0,
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "deltaFormatted": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "fromBlock": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "key": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "level": {
        +        "enum": [
        +          "INFO",
        +          "ATTENTION"
        +        ],
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "section": {
        +        "enum": [
        +          "protocol",
        +          "voting",
        +          "rewards",
        +          "balances",
        +          "locks"
        +        ],
        +        "type": "string"
        +      },
        +      "sources": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "toBlock": {
        +        "type": "string"
        +      },
        +      "token": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "level",
        +      "section",
        +      "key",
        +      "message",
        +      "fromBlock",
        +      "toBlock",
        +      "token",
        +      "decimals",
        +      "deltaFormatted",
        +      "sources"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / initializedSections
        Added value: +{
        +  "items": {
        +    "enum": [
        +      "balances",
        +      "locks"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / unavailableSections / items / enum
        Previous value: -[
        -  "voting",
        -  "rewards"
        -]New value: +[
        +  "voting",
        +  "rewards",
        +  "balances",
        +  "locks"
        +]
      • changedOutput schema / required
        Previous value: -[
        -  "status",
        -  "chainId",
        -  "blockchainReadOnly",
        -  "observation",
        -  "previousObservation",
        -  "reportId",
        -  "reportSaved",
        -  "baselineSaved",
        -  "epochChanged",
        -  "changes",
        -  "unavailableSections",
        -  "warnings"
        -]New value: +[
        +  "status",
        +  "chainId",
        +  "blockchainReadOnly",
        +  "observation",
        +  "previousObservation",
        +  "reportId",
        +  "reportSaved",
        +  "baselineSaved",
        +  "epochChanged",
        +  "changes",
        +  "findings",
        +  "unavailableSections",
        +  "warnings"
        +]
    • Addedaerodrome_wallet_overview
    • Changedaerodrome_wallet_report5 fields changed
      • changedOutput schema / properties / changes / items / properties / section / enum
        Previous value: -[
        -  "protocol",
        -  "voting",
        -  "rewards"
        -]New value: +[
        +  "protocol",
        +  "voting",
        +  "rewards",
        +  "balances",
        +  "locks"
        +]
      • addedOutput schema / properties / findings
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "enum": [
        +          "BASELINE_CREATED",
        +          "SECTION_UNAVAILABLE",
        +          "EPOCH_CHANGED",
        +          "OWNER_CHANGED",
        +          "VOTING_POWER_CHANGED",
        +          "REWARD_CHANGED",
        +          "ROW_APPEARED",
        +          "ROW_NO_LONGER_OBSERVED",
        +          "VALUE_CHANGED",
        +          "SECTION_BASELINE_CREATED",
        +          "BALANCE_CHANGED",
        +          "LOCK_CHANGED"
        +        ],
        +        "type": "string"
        +      },
        +      "decimals": {
        +        "anyOf": [
        +          {
        +            "maximum": 36,
        +            "minimum": 0,
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "deltaFormatted": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "fromBlock": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "key": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "level": {
        +        "enum": [
        +          "INFO",
        +          "ATTENTION"
        +        ],
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "section": {
        +        "enum": [
        +          "protocol",
        +          "voting",
        +          "rewards",
        +          "balances",
        +          "locks"
        +        ],
        +        "type": "string"
        +      },
        +      "sources": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "toBlock": {
        +        "type": "string"
        +      },
        +      "token": {
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "level",
        +      "section",
        +      "key",
        +      "message",
        +      "fromBlock",
        +      "toBlock",
        +      "token",
        +      "decimals",
        +      "deltaFormatted",
        +      "sources"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / initializedSections
        Added value: +{
        +  "items": {
        +    "enum": [
        +      "balances",
        +      "locks"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / unavailableSections / items / enum
        Previous value: -[
        -  "voting",
        -  "rewards"
        -]New value: +[
        +  "voting",
        +  "rewards",
        +  "balances",
        +  "locks"
        +]
      • changedOutput schema / required
        Previous value: -[
        -  "status",
        -  "chainId",
        -  "blockchainReadOnly",
        -  "observation",
        -  "previousObservation",
        -  "reportId",
        -  "reportSaved",
        -  "baselineSaved",
        -  "epochChanged",
        -  "changes",
        -  "unavailableSections",
        -  "warnings"
        -]New value: +[
        +  "status",
        +  "chainId",
        +  "blockchainReadOnly",
        +  "observation",
        +  "previousObservation",
        +  "reportId",
        +  "reportSaved",
        +  "baselineSaved",
        +  "epochChanged",
        +  "changes",
        +  "findings",
        +  "unavailableSections",
        +  "warnings"
        +]
    • Changedaerodrome_wallet_snapshot11 fields changed
      • addedOutput schema / properties / assets
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "balancesStatus": {
        +      "enum": [
        +        "VERIFIED_BOUNDED_SCOPE",
        +        "PARTIAL_BOUNDED_SCOPE"
        +      ],
        +      "type": "string"
        +    },
        +    "liquidBalances": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "amountRaw": {
        +            "anyOf": [
        +              {
        +                "pattern": "^\\d+$",
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "decimals": {
        +            "anyOf": [
        +              {
        +                "maximum": 36,
        +                "minimum": 0,
        +                "type": "integer"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "decimalsSource": {
        +            "enum": [
        +              "ONCHAIN",
        +              "CANONICAL",
        +              "UNKNOWN"
        +            ],
        +            "type": "string"
        +          },
        +          "source": {
        +            "type": "string"
        +          },
        +          "status": {
        +            "enum": [
        +              "VERIFIED_POINT_IN_TIME",
        +              "READ_FAILED"
        +            ],
        +            "type": "string"
        +          },
        +          "symbol": {
        +            "type": "string"
        +          },
        +          "token": {
        +            "anyOf": [
        +              {
        +                "pattern": "^0x[0-9a-fA-F]{40}$",
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          }
        +        },
        +        "required": [
        +          "token",
        +          "symbol",
        +          "status",
        +          "amountRaw",
        +          "decimals",
        +          "decimalsSource",
        +          "source"
        +        ],
        +        "type": "object"
        +      },
        +      "maxItems": 3,
        +      "minItems": 1,
        +      "type": "array"
        +    },
        +    "locks": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "decimals": {
        +            "anyOf": [
        +              {
        +                "maximum": 36,
        +                "minimum": 0,
        +                "type": "integer"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "decimalsSource": {
        +            "enum": [
        +              "ONCHAIN",
        +              "CANONICAL",
        +              "UNKNOWN"
        +            ],
        +            "type": "string"
        +          },
        +          "owner": {
        +            "anyOf": [
        +              {
        +                "pattern": "^0x[0-9a-fA-F]{40}$",
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "permanent": {
        +            "type": [
        +              "boolean",
        +              "null"
        +            ]
        +          },
        +          "principalRaw": {
        +            "anyOf": [
        +              {
        +                "pattern": "^\\d+$",
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "source": {
        +            "type": "string"
        +          },
        +          "status": {
        +            "enum": [
        +              "VERIFIED_POINT_IN_TIME",
        +              "NOT_OWNED",
        +              "UNSUPPORTED_MANAGED",
        +              "READ_FAILED"
        +            ],
        +            "type": "string"
        +          },
        +          "token": {
        +            "anyOf": [
        +              {
        +                "pattern": "^0x[0-9a-fA-F]{40}$",
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "tokenId": {
        +            "pattern": "^\\d+$",
        +            "type": "string"
        +          },
        +          "unlockAt": {
        +            "anyOf": [
        +              {
        +                "format": "date-time",
        +                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          }
        +        },
        +        "required": [
        +          "tokenId",
        +          "owner",
        +          "token",
        +          "status",
        +          "principalRaw",
        +          "decimals",
        +          "decimalsSource",
        +          "permanent",
        +          "unlockAt",
        +          "source"
        +        ],
        +        "type": "object"
        +      },
        +      "maxItems": 16,
        +      "type": "array"
        +    },
        +    "locksStatus": {
        +      "enum": [
        +        "VERIFIED_BOUNDED_SCOPE",
        +        "PARTIAL_BOUNDED_SCOPE"
        +      ],
        +      "type": "string"
        +    },
        +    "observation": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "blockHash": {
        +          "pattern": "^0x[0-9a-fA-F]{64}$",
        +          "type": "string"
        +        },
        +        "blockNumber": {
        +          "pattern": "^\\d+$",
        +          "type": "string"
        +        },
        +        "blockTimestamp": {
        +          "format": "date-time",
        +          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
        +          "type": "string"
        +        },
        +        "observedAt": {
        +          "format": "date-time",
        +          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "observedAt",
        +        "blockNumber",
        +        "blockHash",
        +        "blockTimestamp"
        +      ],
        +      "type": "object"
        +    },
        +    "wallet": {
        +      "pattern": "^0x[0-9a-fA-F]{40}$",
        +      "type": "string"
        +    },
        +    "warnings": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "wallet",
        +    "observation",
        +    "balancesStatus",
        +    "locksStatus",
        +    "liquidBalances",
        +    "locks",
        +    "warnings"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / rewards / properties / gaugeRewards / items / properties / amountFormatted / anyOf
        Added value: +[
        +  {
        +    "pattern": "^\\d+(\\.\\d+)?$",
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / rewards / properties / gaugeRewards / items / properties / amountFormatted / pattern
        Removed value: -"^\\d+(\\.\\d+)?$"
      • removedOutput schema / properties / rewards / properties / gaugeRewards / items / properties / amountFormatted / type
        Removed value: -"string"
      • addedOutput schema / properties / rewards / properties / gaugeRewards / items / properties / decimalsSource
        Added value: +{
        +  "default": "UNKNOWN",
        +  "enum": [
        +    "ONCHAIN",
        +    "CANONICAL",
        +    "ASSUMED",
        +    "UNKNOWN"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / rewards / properties / gaugeRewards / items / required
        Previous value: -[
        -  "gauge",
        -  "token",
        -  "symbol",
        -  "decimals",
        -  "amountRaw",
        -  "amountFormatted"
        -]New value: +[
        +  "gauge",
        +  "token",
        +  "symbol",
        +  "decimals",
        +  "decimalsSource",
        +  "amountRaw",
        +  "amountFormatted"
        +]
      • addedOutput schema / properties / rewards / properties / votingRewards / items / properties / amountFormatted / anyOf
        Added value: +[
        +  {
        +    "pattern": "^\\d+(\\.\\d+)?$",
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / rewards / properties / votingRewards / items / properties / amountFormatted / pattern
        Removed value: -"^\\d+(\\.\\d+)?$"
      • removedOutput schema / properties / rewards / properties / votingRewards / items / properties / amountFormatted / type
        Removed value: -"string"
      • addedOutput schema / properties / rewards / properties / votingRewards / items / properties / decimalsSource
        Added value: +{
        +  "default": "UNKNOWN",
        +  "enum": [
        +    "ONCHAIN",
        +    "CANONICAL",
        +    "ASSUMED",
        +    "UNKNOWN"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / rewards / properties / votingRewards / items / required
        Previous value: -[
        -  "gauge",
        -  "token",
        -  "symbol",
        -  "decimals",
        -  "amountRaw",
        -  "amountFormatted",
        -  "tokenId",
        -  "pool",
        -  "type",
        -  "rewardContract"
        -]New value: +[
        +  "gauge",
        +  "token",
        +  "symbol",
        +  "decimals",
        +  "decimalsSource",
        +  "amountRaw",
        +  "amountFormatted",
        +  "tokenId",
        +  "pool",
        +  "type",
        +  "rewardContract"
        +]
  3. 7 tool updatesv0.1.1
    • First observedaerodrome_compare_pools
    • First observedaerodrome_protocol_status
    • First observedaerodrome_voting_position
    • First observedaerodrome_wallet_changes
    • First observedaerodrome_wallet_report
    • First observedaerodrome_wallet_rewards
    • First observedaerodrome_wallet_snapshot

TDQS

A4.2/5.0

Scored across 14 tools

Disambiguation4/5

Most tools have clearly distinct purposes, but a few pairs could be confused at a glance: wallet_snapshot and wallet_overview both read balances and veNFT positions, and wallet_rewards vs voting_incentives both deal with rewards but for different subjects. The detailed descriptions disambiguate them, but an agent might misselect without careful reading.

Naming Consistency5/5

All tools follow a consistent pattern: the 'aerodrome_' prefix plus descriptive snake_case names. There is no mixing of conventions or vague verbs, and the names clearly hint at the tool's function (wallet_*, compare_*, voting_*, etc.).

Tool Count5/5

14 tools is within the ideal range for a domain-specific server. Each tool covers a distinct aspect of Aerodrome protocol analytics, from pool comparison to wallet accounting to reward planning, and none feel redundant or unnecessary.

Completeness5/5

For a read-only analytics server, the tool surface is remarkably complete: it covers pool data, voting positions, incentives, wallet balances, rewards, historical accounting, snapshots/diffs, reporting, and decision support. There are no obvious dead ends for common analysis workflows, and the tools explicitly note their bounds so agents know what is not included.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Crypto-aware project memory for AI coding agents. Typed entities for Solana Programs/PDAs and EVM Contracts across Base, Optimism, Polygon, Arbitrum, Ethereum — plus chain-agnostic Decisions, Findings, and Integrations. Anchor + Hardhat auto-ingest, SQLite + FTS5 BM25 ranking, append-only versioning, git-aware diffs.
    37 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Analyzes live Uniswap V2/V3, Balancer, and Curve stableswap pools for positions, price moves, pool health, rug signals, slippage, and depeg risk, and builds portable State Twins for offline analysis.
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    A non-custodial USDC wallet on Base exposed as seven tools: address, balance, check, pay, earnings, report and recover. Spending limits (per transaction, per day, per counterparty, plus a destination allowlist) are enforced in code between deciding and signing, and the server runs locally over stdio so the key never leaves the machine.
    1
    Apache 2.0