aero-vote-radar
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@aero-vote-radarrecommend vote allocation for 25000 veAERO"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
aero-vote-radar
An MCP server + CLI that reads live on-chain data from Aerodrome Finance (Base) to rank pools by veAERO vote efficiency, and recommends a vote allocation that accounts for self-dilution — the fact that adding more of your own votes to a pool measurably lowers your own $-per-vote there, which naive "just vote where APR looks highest" approaches ignore.
No API keys, no backend, no database. Every number comes from Aerodrome's own official on-chain "Sugar" contracts and the Voter contract, read live off Base mainnet, plus DefiLlama's free price API to convert bribe/fee tokens to USD.
This tool never touches a wallet or private key. It outputs a recommendation — weights and expected USD — and you vote it yourself on aerodrome.finance.
No install needed: there's a hosted version at aero.deftools.xyz — enter your veAERO amount and it gives you vote-ready percentages. See Web app for how it stays current.
Why
Aerodrome pools receive weekly bribes + trading fees, split pro-rata among everyone who voted for that pool with their veAERO. Two things make "just vote for the highest-APR pool" a bad strategy:
Self-dilution. The moment you add votes to a pool, you've changed its vote total, and your own share (and everyone else's) goes down. A pool that looks great before your vote can look mediocre after it, especially if you have a large veAERO balance relative to the pool's existing votes.
Lag. The leaderboard everyone looks at is last epoch's result. Pools where incentives are trending up faster than votes have caught up are where the actual opportunity is — by the time it's obvious, the vote weight has already caught up too.
One-off bribes masquerading as opportunities. A pool that got a single $600 bribe five weeks ago and nothing since has the same trailing average as one that pays $100 like clockwork — but voting into the first is a bet that a one-week event repeats.
aero-vote-radar addresses all three: it ranks pools using a trailing-average trend estimate instead of just the latest epoch, scores how steady each pool's incentives have actually been, and allocates using a greedy marginal-value algorithm that models dilution explicitly. It also ships a backtest command that replays past epochs so the claim "this beats naive APR-chasing" can be checked rather than taken on faith.
Related MCP server: recon-crypto-mcp
How it works
Data | Source | Contract (Base mainnet) |
Which pools can receive votes, which gauges are alive |
|
|
Pool token/symbol metadata | the pool contracts themselves (ERC20-like) | (per-pool) |
Weekly epoch history — votes, bribes, fees |
|
|
Your veAERO locks & voting power |
|
|
USD pricing for bribe/fee tokens | DefiLlama | — |
All addresses are pulled from Aerodrome/Velodrome's own official Sugar deployment file and cross-checked against verified contract names on Basescan.
Two things worth calling out honestly, so the tool isn't oversold:
"Predicted" is a trailing average, not machine learning.
predictedValuePerVote= mean(last 6 epochs' USD value) ÷ current votes. It's a simple, transparent heuristic for "which pools are trending," not a forecast model.The allocator assumes other voters' votes stay put. The greedy marginal algorithm optimizes your allocation against the current snapshot of everyone else's votes. It doesn't (and can't) predict how other voters will react to your vote.
consistencyis a description of the past, not a promise about the future. It's1 / (1 + coefficient of variation)over the observed epochs: 1.00 means the pool paid the same every epoch, lower means spikier. A pool with only one observed epoch scores 0 rather than 1 — a single data point can't demonstrate steadiness, and scoring it as perfect would flatter brand-new pools exactly where the tool should be most cautious. UseepochsObservedto tell "unproven" apart from "genuinely erratic".The backtest is a small sample with survivorship bias. It only sees pools whose gauge is still alive today, and it assumes your votes wouldn't have changed anyone else's behaviour. Treat a handful of epochs as a sanity check, not a track record.
Voter.pools()currently lists ~1,830 pools that have ever had a gauge; ~110–220 pass a minimum trailing-value floor (pools below ~$10/epoch trailing value are excluded — at that size a single small one-off bribe swings the "edge" percentage wildly without being a meaningful signal). A few hundred Voter-registered entries fail basic ERC20 calls (non-standard/likely cross-chain relay entries) and are skipped with a warning rather than failing the whole run.
Web app
aero.deftools.xyz is the same ranking and the same allocator, without installing anything.
It exists because the two halves of this tool have very different costs. The scan is heavy — one epoch-history call per live-gauge pool, several hundred of them — which a visitor's browser cannot do against a public RPC without being rate-limited into uselessness. The allocation is just arithmetic over an already-scanned list, and is instant.
So they're split:
A scheduled job (
.github/workflows/snapshot.yml, every 6 hours) runsnpm run snapshot, which performs the full live scan and writesdocs/data/snapshot.json. If the file changed, the job commits it. A scan that returns zero pools throws instead of publishing, so a rate-limited run can't blank out yesterday's perfectly good data.docs/index.htmlfetches that JSON and runsallocateAcrossCandidates+toWholePercentWeights— ported verbatim fromsrc/allocator.ts— in the browser, per keystroke.
Nothing is sent anywhere: the page is a static file plus a JSON file, with no backend and no analytics. Because the personalised half runs client-side, changing your veAERO amount doesn't trigger a re-scan, and the snapshot can be shared by every visitor.
The page also:
Reads your voting power from an address. Paste a wallet and it sums your locks' live voting power. This is read-only — the page never requests a wallet connection or a signature.
Copies the weights as
93% sAMM-WETH/msETHlines, so they can go straight into Aerodrome's UI instead of being retyped from the screen.Labels each pool
vAMMorsAMM— volatile (x·y=k, for tokens whose prices move independently) versus stable (a flatter curve for pairs meant to hold the same value). Each row links to the pool contract on Basescan.
Why the wallet lookup does not use VeSugar.byAccount like the CLI's --address does: that method returns one large struct per lock, including every vote each lock has cast, and on a public RPC it reverts for wallets holding many locks — 0xbde0…ea5a, with 22 locks, fails outright. The page instead makes three plain calls against the VotingEscrow contract (balanceOf → ownerToNFTokenIdList → balanceOfNFT), all of which return single integers. Verified equal to the VeSugar path where VeSugar works (0xde86…ee31: both report 81.50845401781879), and working on the 22-lock wallet where it doesn't. The contract address is read from Voter.ve() rather than copied from documentation. Note that voting power decays continuously toward a lock's expiry, so two reads seconds apart legitimately differ.
The site is served by GitHub Pages from the docs/ folder on main. To regenerate the snapshot by hand:
npm run snapshot # writes docs/data/snapshot.json
npm run snapshot -- some/other.json # or somewhere elseVerified parity: for 25,000 veAERO with no consistency filter, the page and npm run cli -- recommend --veaero 25000 --vote-ready produce the same weights (76/20/2/1/1) and the same expected total, to the cent.
Install
Requires Node.js 18.18 or newer (the test suite's node --import tsx invocation depends on the --import flag, added in 18.18).
git clone https://github.com/araxis33/aero-vote-radar
cd aero-vote-radar
npm install
npm run buildOptionally set your own Base RPC for a much higher rate-limit ceiling than the shared public endpoints:
export BASE_RPC_URL="https://your-rpc-provider.example/..."CLI usage
npx tsx src/cli.ts pools --top 10
npx tsx src/cli.ts pools --top 10 --min-consistency 0.5
npx tsx src/cli.ts recommend --veaero 25000
npx tsx src/cli.ts recommend --address 0xYourAddress --vote-ready
npx tsx src/cli.ts backtest --veaero 25000 --epochs 5
npx tsx src/cli.ts my-veaero 0xYourAddress
npx tsx src/cli.ts my-veaero 0xYourAddress --jsonPass --json to any command for machine-readable output instead of a table — useful for piping into other scripts or tools.
recommend and backtest take either --veaero <amount> or --address <0x...>; with an address they read your live voting power off-chain so you don't have to look it up and retype it.
Real output from live runs (Base mainnet, no mocking):
$ npx tsx src/cli.ts pools --top 8
Top 8 Aerodrome pools by predicted $/veAERO vote (of 101 live-gauge pools with votes):
Symbol Votes(veAERO) Latest $/vote Predicted $/vote Edge Consistency
vAMM-cbBTC/CHAMP 7,681 $0.000963 $0.1 10440.0% 0.35
vAMM-1000X/WETH 893 $0.003128 $0.02 478.0% 0.54
vAMM-WETH/FAI 1,242 $0.01 $0.01 -3.6% 0.54
sAMM-WETH/msETH 494,716 $0.007752 $0.01 33.7% 0.68
vAMM-USDC/SEND 1,344 $0.009698 $0.01 5.0% 0.60
vAMM-cbBTC/EDGE 67,411 $0.002594 $0.009726 275.0% 0.41
vAMM-WETH/EURC 6,197 $0.000258 $0.006274 2334.5% 0.57
vAMM-YFI/wstETH 146,052 $0.002505 $0.006189 147.1% 0.44That top row is exactly why consistency exists: a 10,440% "edge" on 0.35 consistency is one big one-off bribe, not a repeatable weekly opportunity. --min-consistency 0.5 filters that class of pool out entirely.
--vote-ready prints whole percentages that sum to exactly 100, which is what Aerodrome's voting UI accepts — rounding each weight independently tends to total 101% or 102% and leaves you fudging the last row by hand:
$ npx tsx src/cli.ts recommend --address 0x28aa...0108 --vote-ready --min-consistency 0.5
Using 11,491,441.934 veAERO of live voting power from 0x28aa...0108 (2 lock(s)).
Vote-ready weights for 11,491,442 veAERO — whole percentages, summing to exactly 100:
51% vAMM-VIRTUAL/WETH
25% sAMM-WETH/msETH
18% vAMM-WETH/MET
2% vAMM-WETH/DRV
2% vAMM-wBLT/BMX
1% vAMM-WETH/GHST
1% vAMM-Anon/USDC
Enter these directly on aerodrome.finance. Expected next epoch: $11,013.66.$ npx tsx src/cli.ts backtest --veaero 25000 --epochs 5
Backtest over the last 5 epoch(s) with 25,000 veAERO:
EpochsAgo Radar $ Naive $ Naive picked
0 $137.3 $2.7 vAMM-1000X/WETH
1 $12.82 $13.32 vAMM-WETH/RWAX
2 $16.84 $3.34 vAMM-WETH/AIXCB
3 $17.02 $5.17 vAMM-WETH/FAI
4 $16.28 $6.39 vAMM-USDC/SQD
Total: radar $200.26 vs naive $30.91 — uplift 547.8%
Radar earned more in 4 of 5 epoch(s).Read that with the caveats above in mind: 4-of-5 epochs is encouraging, but one epoch (0) supplies most of the total, and five weekly epochs is a small sample. The point of the command is that you can re-run it yourself rather than trust the claim.
$ npx tsx src/cli.ts my-veaero 0x28aa4F9ffe21365473B64C161b566C3CdeAD0108
veAERO locks for 0x28aa4F9ffe21365473B64C161b566C3CdeAD0108:
NFT #6: 11,362,738.622 veAERO voting power, expires never (permanent lock)
NFT #17324: 107,871.726 veAERO voting power, expires never (permanent lock)
Total voting power: 11,470,610.348 veAEROAs an MCP server
npx tsx src/mcp-server.tsor, after npm run build and npm link / publishing, point any MCP-capable agent (Claude, etc.) at the aero-vote-radar-mcp binary. It exposes four tools:
list_pool_efficiency— ranked pools with current + predicted $/vote, predictive edge, and consistency. OptionalminConsistencyfilter.recommend_allocation— given a veAERO amount or a walletaddressto read it from, returns weights, whole-percent vote weights, and expected USD per pool.backtest_strategy— replays past epochs and compares this strategy against naive APR-chasing.get_my_veaero— looks up an account's veAERO locks and total voting power.
Example agent prompts:
"Using aero-vote-radar, recommend an allocation for my 25,000 veAERO."
"Work out my veAERO from 0xMyAddress and give me vote weights I can type straight into Aerodrome, skipping pools with consistency below 0.5."
"Backtest the aero-vote-radar strategy over the last 6 epochs with 25,000 veAERO."
Project layout
src/
constants.ts verified Base mainnet contract addresses
abi.ts minimal ABIs (only the methods this project calls)
chain.ts viem public client (Base RPC, retry/batch configured)
prices.ts DefiLlama USD price lookup + cache
pools.ts pool discovery (Voter) + epoch history (RewardsSugar)
efficiency.ts current & trend-predicted $/vote ranking + consistency scoring
allocator.ts greedy marginal ("water-filling") allocation + whole-percent vote weights
backtest.ts replays past epochs to score this strategy against naive APR-chasing
veAero.ts VeSugar wrapper for a user's voting power
util.ts address/concurrency helpers + shared error-message formatting
snapshot.ts builds the JSON snapshot the web app reads
mcp-server.ts MCP stdio server entrypoint
cli.ts CLI entrypoint
snapshot-cli.ts entrypoint for the scheduled snapshot job
docs/ the web app, served by GitHub Pages
index.html static page: reads the snapshot, runs the allocator client-side
data/
snapshot.json latest scan, refreshed every 6 hours by CI
test/
allocator.test.ts unit tests for the greedy marginal-allocation algorithm and percentage rounding
backtest.test.ts unit tests for the backtester, including that it never peeks at the epoch under test
efficiency.test.ts unit tests for per-pool efficiency math (trailing average, $/vote, predictive edge, consistency)
prices.test.ts unit tests for DefiLlama price lookup, batching, and USD conversion
veAero.test.ts unit tests for the veAERO NFT summary mapping (toVeNftSummary)
util.test.ts unit tests for isValidAddress, mapWithConcurrency, and formatError
cli.test.ts unit tests for CLI flag parsing
snapshot.test.ts unit tests for the published snapshot shapeTesting
npm testTests cover the allocator (recommendAllocation) with synthetic pool data — budget conservation, that a single candidate gets 100% of the allocation, that topK is actually respected, and specifically that self-dilution works: two pools with identical incentives and existing votes get split roughly evenly under a large budget instead of an APR-only optimizer dumping everything into one. toWholePercentWeights is tested to always total exactly 100 (six equal weights land on 4x17 + 2x16, not six 17s summing to 102), including on real recommendAllocation output. The backtester (runBacktest) is tested for the property that matters most in a backtest — no lookahead: a pool that pays a $10,000 jackpot in the epoch under test but was worth $0 in every epoch before it must not be picked, and its jackpot must not appear in the result. It's also checked against the dilution maths directly (budget equal to a pool's existing votes earns exactly half the pot), for beating the naive all-in baseline when the budget is large relative to pool votes, and for returning null uplift rather than dividing by a zero baseline. The pure per-pool efficiency math (computePoolEfficiency/epochUsd/computeConsistency in efficiency.ts) is covered the same way — trailing-average computation, the MIN_TRAILING_USD cutoff, the zero-votes exclusion, the predictiveEdge divide-by-zero guard, and that a $600-then-nothing pool scores far below a steady $100/epoch pool with the same average — plus DefiLlama pricing/batching (prices.ts), the veAERO NFT summary mapping (toVeNftSummary in veAero.ts, including permanent-lock and large-id precision handling), CLI flag parsing (cli.ts), and the address/concurrency/error-formatting helpers (util.ts), all with synthetic inputs and no network access. formatError (in util.ts) reduces a thrown error to a single clean line — preferring viem's concise .shortMessage over its multi-paragraph .message — and is shared by both the CLI's top-level error output and every MCP tool handler's error result, so a failed RPC call surfaces the same readable message however the tool is invoked. The remaining on-chain data-fetching code (fetchActivePools/fetchPoolEpochs in pools.ts, fetchVeAeroPositions in veAero.ts) is exercised live against Base mainnet via the CLI instead — see the real example output above.
CI (.github/workflows/ci.yml) runs the typecheck, build, and test suite on every push.
License
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceMCP (Model Context Protocol) server for the MAIN DEX on Base. Provides AI agents (Claude, Cursor, etc.) with tools to interact with the protocol: swap tokens, manage liquidity, enter/exit ALM strategies(10% APY), and more.MIT
- AlicenseAqualityAmaintenanceSelf-custodial crypto portfolio and DeFi MCP server. Read balances and positions (Aave, Compound, Morpho, Uniswap V3, Lido, EigenLayer) across Ethereum, Arbitrum, Polygon, and Base, and prepare transactions for approval on a Ledger via WalletConnect.100744Business Source 1.1
- Flicense-qualityDmaintenanceAutonomous MCP server for DeFi yield optimization, enabling yield opportunity discovery, treasury snapshots, market signals, and portfolio rebalancing.
- FlicenseAqualityBmaintenanceMCP server that forecasts next-epoch demand for Aerodrome pools on Base and turns it into concrete incentive-allocation recommendations.66
Related MCP Connectors
Concentrated liquidity on Uniswap/Aerodrome (rebalance, compound, leverage) or single-sided lending.
Multi-aggregator swap router for AI agents on Base. 10 bps fee. MCP-native, non-custodial.
7-factor stock scoring MCP server. US/HK/CN, 74 stocks. Free + Premium (USDC/Base). x402 ready.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/araxis33/aero-vote-radar'
If you have feedback or need assistance with the MCP directory API, please join our Discord server