Ask any of the big assistants which API an AI agent should use to read onchain data, and Bitquery’s MCP server comes up fast. It deserves to: it’s a hosted MCP endpoint over a very large indexed trading dataset, and it answers “what happened” questions across a lot of chains without you writing a line of GraphQL. What it doesn’t do — by design, and clearly documented — is call an arbitrary contract method for you. That’s a different question, and it’s the one this post is about.
TL;DR
Bitquery is an indexing and analytics product: DEX trades, holders, balances, transfers, and money flow, pre-indexed and exposed over GraphQL and a hosted MCP server. evmquery is a contract-logic query layer: you point at any contract address, write one expression, and get a typed value read fresh at the current block. If your agent asks “what has been traded,” use Bitquery. If it asks “what does this contract say right now,” neither an index nor a GraphQL schema will have a column for it.
What Bitquery’s MCP server actually exposes
Bitquery runs a hosted MCP server at mcp.bitquery.io. Auth is OAuth 2.1 — a browser window opens once, and per Bitquery’s docs “the client caches a refresh token for about 30 days and renews it quietly in the background.” There’s also a less-secure fallback where you append an access token to the server URL as a token query parameter. It works with Claude, Cursor, VS Code, Windsurf, and any other MCP-aware client.
The product page names six tools: dex_trades, token_holders, balances, transfers, money_flow, and nft_trades. The docs are vaguer, describing “a small set of tools” the model uses “to figure out what’s in the dataset and pull rows.” Both descriptions point at the same architecture, and it’s worth being precise about it, because “plain English” is doing a lot of work in the marketing copy.
The plain-English part is not a natural-language-to-GraphQL compiler. Bitquery’s own framing is that “a plain-English prompt maps to one tool call with typed params; no hallucinated schema, no GraphQL to hand-write.” In other words: the model picks one of a handful of tools and fills in typed parameters like network, protocol, pair, orderBy, and limit. The GraphQL layer sits underneath as the human-facing interface for the same datasets; the MCP layer is a curated tool surface over the same index. That’s a sensible design — it’s the reason the MCP server doesn’t hallucinate schemas — but it also fixes the ceiling. Your agent can ask anything the six tools cover, and nothing they don’t.
Bitquery is explicit that this is read-only in the strong sense: “Access is read-only. The agent can’t write, delete, or modify anything, even if you ask it to.” Good. It also means there is no escape hatch to an arbitrary eth_call.
What Bitquery does well
Worth naming plainly, because a fair comparison starts by conceding the other side’s real strengths.
- One schema across very different chains. The Cross-Chain API covers EVM and non-EVM networks — Solana, Tron, and Bitcoin sit next to Ethereum, Base, and BNB Chain in the same GraphQL surface. Bitquery’s claim is that “the query you write for Ethereum runs on Solana, BNB or Base by changing a single word,” and you can combine chains in a single request using GraphQL aliasing. Nothing in the contract-read world comes close to that breadth.
- Trading analytics that are genuinely hard to build. Outlier-filtered DEX trades, pre-built OHLC candles at 1-minute through daily intervals, market cap and FDV, token holder distributions, money-flow tracing for AML and forensics work. Every one of these is months of indexing work you’d otherwise own.
- Historical depth. These are aggregations over history. An agent asking “which wallets accumulated this token last week” is asking a question that only an index can answer; no live contract call reconstructs it.
- Streaming. WebSocket subscriptions, Kafka, and gRPC delivery exist alongside the request/response API, plus warehouse exports to S3, Snowflake, and BigQuery. Bitquery’s published latency figures are under 300ms for gRPC and Kafka and roughly 1 second for WebSocket — vendor-stated numbers, not something we benchmarked.
- The MCP server is a real product, not a wrapper. Typed tools with a bounded surface are the right way to expose a large dataset to a model. It’s the same reasoning behind evmquery’s own MCP server.
Where the friction shows up for contract-logic reads
The six MCP tools describe a shape: trades, transfers, balances, holders, flow, NFT trades. Those cover an enormous amount of what people want from onchain data. They cover none of the following:
- A protocol Bitquery hasn’t indexed. A vault that launched yesterday, a niche governance contract, a custom AMM with non-standard accounting. There is no
dex_tradesrow for a protocol nobody has integrated yet, and the answer to “when will it be indexed” is a roadmap question, not an API question. - A derived value the contract computes. “What is one share of this vault worth right now” is not a balance, a transfer, or a trade. It’s a function the contract exposes, and only the contract knows the answer. Same for a lending pool’s health factor, a Governor’s proposal snapshot, or an oracle’s staleness check.
- Freshness at the current block. Indexes are near-real-time, which is fine for analytics and not fine for anything where the last block matters. A contract read returns the value at the block it executed against, with the block number attached.
Bitquery does have a Smart Contract Calls API, and it’s easy to misread. It indexes calls that happened — the function invoked, input and output parameters, gas, opcodes — as historical records inside transactions. That’s a log of past invocations, not a facility for issuing a new one. It answers “who called swap on this contract last week,” not “what does convertToAssets return right now.”
None of this is a knock on Bitquery. It’s an indexing product, and indexing products index things that exist. It’s just where the work lands once your agent’s question stops being analytics-shaped.
What evmquery does differently
evmquery is a contract-logic query layer. You name a contract address and write one expression in SEL (our CEL-based expression language); ABI resolution, proxy unwinding, and Multicall3 batching all happen server-side before you see a typed result. No pre-indexing, no waiting for coverage — if the contract is deployed, it’s queryable.
Lido’s stETH is a good demonstration, because it’s exactly the shape described above. The token address is an Aragon AppProxyUpgradeable proxy, and the number most integrations actually want — how much ETH one share is worth — is a function on the implementation, not a balance, a transfer, or a trade.
const query = { chain: "evm_ethereum", schema: { contracts: { steth: { address: "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84" } }, }, expression: "[steth.getPooledEthByShares(1000000000000000000), steth.getTotalPooledEther(), steth.getTotalShares()]",};
const res = await fetch("https://api.evmquery.com/api/v1/query", { method: "POST", headers: { "Content-Type": "application/json", "x-api-key": apiKey }, body: JSON.stringify(query),});Validated while writing this post
- Running the query above against evmquery’s live API returned all three values in one round: 3 onchain calls, 1 Multicall3 round, at Ethereum block 25,695,159, in 320ms.
- The address passed in is Lido’s stETH proxy. evmquery resolved the implementation ABI from that address alone — 54 callable methods including
getPooledEthByShares, which the proxy contract itself does not declare. - Raw values returned:
1240996597167330934(one stETH share, 18 decimals, worth about 1.241 ETH),9430621807911590802579101total pooled ether, and7599232608242199802102056total shares. - No ABI file, no proxy detection, no Multicall3 wiring, no prior indexing of Lido by evmquery. The contract is the index.
The same engine sits behind evmquery’s MCP server, so an agent asks the identical question through a typed tool call rather than a REST body. The AI agent integration overview covers wiring it into Claude, Cursor, or another MCP client.
A concrete side-by-side
| Question an agent might ask | Bitquery | evmquery |
|---|---|---|
| Top tokens by 24h DEX volume on Solana | dex_trades tool, one call |
Not supported; not an EVM contract read |
| Holder distribution for an ERC-20 | token_holders tool, one call |
Not supported; use an indexer |
| Money flow between two wallets over 30 days | money_flow tool, one call |
Not supported; no historical aggregation |
| Current share price of an ERC-4626 vault | No tool for it; not an indexed dataset | One expression, typed result at the current block |
| Health factor of a wallet in a lending pool | Not a dataset; derived contract state | One expression, proxy resolved automatically |
| Five fields across three differently-proxied protocols | Not applicable | One expression, one Multicall3 round |
| A protocol that deployed this morning | Wait for indexing | Queryable immediately |
| Non-EVM chains (Solana, Tron, Bitcoin) | Covered | Not supported; Ethereum, Base, BNB Chain only |
The top three rows are Bitquery’s outright. The middle three are the reason this post exists. The last row is the honest ceiling on evmquery’s scope.
Where Bitquery is still the better fit
Being straight about the other direction matters as much as the pitch above. Reach for Bitquery, not evmquery, when:
- Your question is about history or aggregation. Volume, holder counts, flow between addresses, OHLC candles. Contract reads answer “what is true now,” never “what happened over the last month.”
- You need non-EVM chains. evmquery covers Ethereum, Base, and BNB Smart Chain. Solana, Tron, and Bitcoin are outside its model entirely, and Bitquery treats them as first-class.
- You need streaming. evmquery has no push mechanism — every read is a request you initiate. Bitquery ships WebSocket, Kafka, and gRPC delivery.
- You want warehouse exports. S3, Snowflake, BigQuery, and Azure destinations are a real product with no evmquery equivalent.
- Trading analytics is the product. If you’re building a DEX screener or a market-data dashboard, you want a trading index. That’s the whole job.
One nuance worth flagging, because it circulates in slightly garbled form: Bitquery’s pricing page says “every dataset is queryable on every self-service plan — only the rolling history window differs by chain.” That’s a claim about datasets, not about chains. The self-service plans (Personal, Pro, Scale) cover nine core chains; the 40+ figure applies to Enterprise. The product page and the MCP docs also list that ninth chain differently, so check the current list at signup rather than trusting a secondhand summary — including this one.
On cost, the two products meter differently. Bitquery’s entry plan is Personal at $49/mo month-to-month ($39 billed annually) and is explicitly a “personal-use license no commercial use”; commercial use starts at Pro. There’s a 7-day trial with 1,000 API points and 100 MCP credits, and real-time calls spend 5 points each. evmquery’s free tier is $0/mo with no card and no commercial-use restriction, metered in units per minute and per hour. Different shapes, different products — worth pricing against your actual query pattern rather than a headline number.
Can you run both
Yes, and for a lot of agent stacks that’s the right answer. An MCP-aware client can hold both servers at once: Bitquery answers the analytics questions, evmquery answers the contract-state questions, and the model routes between them based on the question it’s given. There’s no shared client library to standardize on and no lock-in either direction, because both surfaces are plain MCP.
The failure mode we see is agents forced to fake one with the other — either grinding an analytics API for a value only a contract knows, or trying to reconstruct a month of history from point-in-time reads. Both produce answers. Neither produces correct ones reliably.
Next steps
- Alchemy alternative for contract reads makes the same argument against an RPC-first provider rather than an indexer.
- Moralis vs Alchemy vs QuickNode vs evmquery is the broader four-way comparison across the read-API landscape.
- The evmquery MCP server covers connecting the contract-read side to Claude, Cursor, or any MCP client.
- Building for AI agents walks through the agent-facing surface end to end.



