Agent RPC MCP
Agent RPC MCP is a hosted Model Context Protocol server that gives an AI agent read access to every chain Ankr serves. You point your coding agent at one URL, give it your Ankr API key, and it gets seventeen tools that return chain data already decoded and compressed for a context window, instead of raw hex the model has to spend tokens parsing.
It is a data plane only. Every tool reads. Nothing in it can sign, broadcast, or change chain state, on any chain family. Account and key management lives in a separate server, the Management MCP.
Why it is not just an RPC endpoint
An agent that calls JSON-RPC directly pays twice: once for the hex it cannot read, and again for the reasoning it spends turning that hex into meaning. Each tool here calls rpc.ankr.com asking for TORPC tier 2, so a response comes back with contract calls and event logs ABI-decoded into named arguments, hex numbers turned into decimals, and bulky fields such as logsBloom and header roots dropped. On decode-heavy reads (transactions, receipts, logs) that is typically 25% to 58% fewer tokens for the same information.
Every tool result also carries a real token count for the text it emitted, so an agent can budget its own context rather than guess at it.
Connect it
You need an Ankr API key. Create a project and copy its key from the Web3 API platform; see Premium: basics if you have not made one yet.
The server speaks Streamable HTTP at:
https://mcp.ankr.com/rpc
Authenticate with your key in the x-ankr-api-key header, or as Authorization: Bearer <YOUR_KEY>. A request with no key is refused. Your key is passed straight through to Ankr RPC, so the rate limits and charging of your plan apply exactly as they do to your own calls. The MCP server adds no quota of its own and has no keyless trial.
Claude Code
claude mcp add --transport http ankr-agent-rpc https://mcp.ankr.com/rpc \
--header "x-ankr-api-key: <YOUR_KEY>"
Then run /mcp inside Claude Code to confirm the server is connected and see the tools it advertises.
Cursor
Add the server to .cursor/mcp.json in your project, or to ~/.cursor/mcp.json for every project:
{
"mcpServers": {
"ankr-agent-rpc": {
"url": "https://mcp.ankr.com/rpc",
"headers": { "x-ankr-api-key": "<YOUR_KEY>" }
}
}
}
VS Code
Add it to .vscode/mcp.json (workspace) or your user MCP configuration, and keep the key out of the file by prompting for it:
{
"servers": {
"ankr-agent-rpc": {
"type": "http",
"url": "https://mcp.ankr.com/rpc",
"headers": { "x-ankr-api-key": "${input:ankr-api-key}" }
}
},
"inputs": [
{
"id": "ankr-api-key",
"type": "promptString",
"description": "Ankr API key",
"password": true
}
]
}
A session is bound to the key it was opened with, and every later request on that session has to present the same key. To switch keys, start a new session (in most clients, reconnect the server).
The seventeen tools
Chain reads, compressed
These three request TORPC tier 2 and are the reason the server exists.
getTransaction: a transaction plus, by default, its receipt, with calldata and logs ABI-decoded.getLogs: event logs decoded to contract, event, and named arguments. A wide block range is scanned in ascending chunks and paged with a cursor, rather than fetched whole and mostly discarded.getBlock: a block by number, hash, or tag (latest,finalized,safe,earliest,pending), optionally with decoded transactions.
Wallet, token, and NFT data
Indexer-backed reads through the Advanced API. These are not TORPC-compressed.
getBalances: native balance plus ERC-20 balances with USD value. The asset list is bounded and value-ordered, with a cursor to the tail; assets the indexer has no price for are reported as unknown value, never as zero.getAccountBalance: balances across several chains at once, in prose form.getWalletActivity: an address's recent transaction history, newest first, paged.getNFTs: NFTs held by an address, with collection, token id, standard, and image.getTokenHolders: holders of an ERC-20 contract, with balances and a total count.getTokenPrice: USD price, with the block and timestamp the quote is as of.getTokenPriceHistory: a historical USD price series for a token.getInteractions: which chains an address has used, as a first step before per-chain queries.
Contract and identifier lookups
resolveContract: whether an address is a contract, best-effort ERC-20 metadata, and EIP-1967 proxy detection.searchChain: resolves an on-chain identifier: a 32-byte hash to a transaction (or block), a 20-byte address to an account, digits to a block number. It is not a name lookup: tickers, contract names, and ENS names are reported as unresolved rather than guessed.
Discovery and paging
listChains: the live capability matrix of which chains have Advanced API coverage, and where tier-2 compression is verified.describeMethods: for any JSON-RPC method, the positional parameter shape and a worked example, plus whether your key may actually call it on that chain. Passprobe:truewith an explicitmethodslist to ask the node, so the answer reflects your key, your tenant, and the chain's schema rather than a guess; a method the escape hatch refuses is never sent.expandResult: continues a paged result fromgetLogs,getWalletActivity, orgetBalancesusing the opaque cursor the previous call returned.
The escape hatch
rpcCall: any read method on any chain Ankr serves, for the cases the routed tools do not cover (eth_call,eth_estimateGas,eth_getStorageAt,eth_getCode,eth_feeHistory,trace_*,debug_trace*, and the equivalent reads on non-EVM families). Prefer a routed tool where one fits: those are tuned and decoded.
Compression is negotiated per call, and can degrade
Tier 2 is what a tool asks for, not what it is promised. The proxy applies the requested tier only while the response stays inside its compression budget; a response above that budget comes back at tier 0, raw and undecoded, no matter what was requested.
| Tier | What you get |
|---|---|
| 0 | Passthrough. Standard JSON-RPC, raw hex, no decoding. |
| 1 | Hex converted to decimal, plus field renaming. |
| 2 | Full: ABI decode of functions and events with named arguments, log collapse, logsBloom dropped. |
_meta.tier carries the tier actually applied and is present on every successful result, so check it before looking for decoded fields such as args. A downgrade to tier 0 happens when a response is over the proxy's compression budget, and also on methods the proxy does not compress at all, such as eth_call, eth_getCode and eth_getStorageAt.
Some tools additionally put tier_degraded: true in the body when they asked for tier 2 on your behalf and got less, alongside tier_applied and a note on how to narrow the request. Not all of them do, so _meta.tier is the field to rely on. Treat a degradation as "ask for less data" (a narrower block range, fewer transactions) rather than as an error. An error result carries _meta.error_code and no tier at all.
Decoded amounts are raw base units, with no decimals applied. An args.value of 41695680 on a 6-decimal token is 41.69568, not 41 million. Fetch the token's decimals (with resolveContract) before reporting a human-readable amount.
Reads only, and broadcast is refused
rpcCall is a data escape hatch, not a wallet. The server closes write paths itself, before the request leaves it:
- It is a write denylist, not a read allowlist. The server refuses an enumerated set of write paths on every chain family and forwards everything else. It keeps no list of permitted reads, so a read it does not recognize is forwarded rather than refused.
- Broadcast and signing are refused on every chain family, with no exceptions. That covers
eth_sendRawTransaction, MEV bundle and private-transaction variants,personal_*andeth_sign*, SolanasendTransactionandrequestAirdrop, Bitcoinsendrawtransaction, Suisui_executeTransactionBlock, XRPLsubmit, Tronbroadcasttransactionandcreatetransaction, Cosmosbroadcast_tx_*, and Starknetadd*Transaction. - Node administration, dev-node state, and consensus-layer namespaces are refused too:
admin_*,miner_*,personal_*,hardhat_*,anvil_*,evm_*,engine_*, any mutating verb (set*,write*,start*,stop*,compact*), and the node-operation half of geth'sdebug_*namespace such as profilers and chaindb compaction. - Transaction building is refused where it is namespaced as such, even though it broadcasts nothing: Sui's
unsafe_*namespace returns an unsigned transaction, and that is a wallet's job. This is scoped to that namespace, not a general rule about builders. - Simulation still works. Read-only simulation is not broadcasting, so
eth_call,eth_estimateGas, SolanasimulateTransaction, and Sui's dry-run methods are permitted.
Sign and send with your own wallet or signer. To keep the guarantee independent of this server as well, point the agent at a read-only key.
What this does and does not decide. The refusal of broadcast, signing and node administration is enforced here and holds on every chain. Which reads you may call is not decided here at all: a forwarded read is answered or refused by the chain's blockchain schema and by your tenant, and that refusal (Method disabled, reason: restricted by blockchain schema) is the authoritative answer. Call describeMethods with probe:true to ask the endpoint what your key may actually call, rather than inferring it from this list.
Supported chains
- Raw-RPC tools and
rpcCallreach any chain Ankr serves. Pass the chain slug as it appears inrpc.ankr.com/<chain>: 200+ EVM mainnets and testnets, plus non-EVM families such as Solana, Bitcoin, Sui, XRP, TON, NEAR, Aptos, and Cosmos chains. See the chains list for the full set. - Tier-2 compression is verified on the common EVM chains (Ethereum, BSC, Polygon, Arbitrum, Optimism, Base, Avalanche, Fantom, Gnosis, Linea, Scroll, zkSync Era, and others). Elsewhere the call still works and passes through at tier 0.
- Indexer tools need Advanced API coverage, which is a smaller set than "everything Ankr serves".
Call listChains rather than hardcoding any of this: it returns the Advanced API set and the tier-2 examples as they are today, and it is the surface we keep current.
Good to know
- Tool inputs are strict. A misspelled argument is reported as a validation error instead of being silently dropped, so an agent finds out it got the name wrong.
- Pass block numbers above 2^53 as strings. A JSON number that large is not exact.
- Results are bounded on purpose. Large lists are capped, and the response says what it withheld and how to reach the rest through
expandResult. A truncated list always admits it is truncated.
Related
- Management MCP: the control plane for keys, per-key security, usage, balance, and notifications.
- Advanced API: the indexed data the wallet and token tools read.
- Service plans and Charging policy: what your key's calls cost.
- Error reference: what an error from the underlying endpoint means.