TORPC: token-efficient JSON-RPC
TORPC is a response-compression layer on top of ordinary JSON-RPC. You ask for it with one request header, and the answer comes back decoded: event logs as named arguments, hex numbers as decimals, and the fields nothing reads dropped.
It is the layer underneath Agent RPC MCP, but it is not tied to it. Any HTTP client can use it, including curl, so you do not need an MCP server or an AI agent to benefit: you need one header.
The normative document is the specification repository, w3tech/torpc, released under CC0-1.0 so anyone may implement it; this page is the narrative version of it. The reference decoder, the typed rules and the benchmark harness are in w3tech/torpc-js under Apache-2.0. The EVM tier-1 and tier-2 rules are normative today, while the conformance suite is still a scaffold, so no implementation, Ankr's included, calls itself TORPC conformant yet.
Why it exists
A model that reads raw JSON-RPC pays twice: once for hex it cannot interpret, and again for the reasoning it spends turning that hex into meaning. A transfer log arrives as an address, three topics and a data blob, and the model has to know the ABI, know that topics[0] is the event signature hash, and do the arithmetic, for every log, on every call.
TORPC does that decode once, on the way out.
Negotiation
| Request header | Accept-Token-Tier: 0 | 1 | 2 |
| Response header | Token-Tier: <the tier actually applied> |
| Endpoint | https://rpc.ankr.com/<chain>/<key> |
| Tier | What you get |
|---|---|
0 | passthrough, standard JSON-RPC unchanged |
1 | hex converted to decimal, plus field renaming |
2 | full: ABI decode of functions and events into named arguments, log collapse, logsBloom dropped, hex to decimal |
The tier is negotiated per call and is not guaranteed. The proxy applies what you asked for only while the response stays inside its compression budget. A response above that budget comes back at tier 0, raw and undecoded, whatever the request said. Always read the Token-Tier response header before looking for decoded fields: it reports what was actually applied, not what was requested.
A real request, and a real answer
Measured against production. Same transaction receipt, same chain, one header apart.
# Tier 0: ordinary JSON-RPC
curl -s https://rpc.ankr.com/eth/$ANKR_API_KEY \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["0x3fe1022b421843ffa01e84de3eac55250884632c8bee8223e8046a53cab52dc1"]}'
One of its three logs, as it arrives:
{
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000e0554a476a092703abdb3ef35c80e0d76d32939f",
"0x00000000000000000000000051c72848c68a965f66fa7a88855f9f7784502a7f"
],
"data": "0x0000000000000000000000000000000000000000000000004a68c830d8576f68",
"blockHash": "0xb691f4dfb600f43e585cb859366eda914967b2c59a54fa28789c1420d409825c",
"blockNumber": "0x188c3aa",
"blockTimestamp": "0x6a7ca35f",
"logIndex": "0x0",
"removed": false
}
# Tier 2: one header added
curl -s https://rpc.ankr.com/eth/$ANKR_API_KEY \
-H 'Content-Type: application/json' \
-H 'Accept-Token-Tier: 2' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["0x3fe1022b421843ffa01e84de3eac55250884632c8bee8223e8046a53cab52dc1"]}'
The same log, decoded:
{
"event": "Transfer",
"contract": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"args": {
"from": "0xE0554a476A092703abdB3Ef35c80e0D76d32939F",
"to": "0x51C72848c68a965f66FA7a88855F9f7784502a7F",
"value": "5361755468498169704"
}
}
The receipt's own fields are renamed and de-hexed the same way (block, block_hash, gas_used, gas_price, tx, tx_index), and logsBloom, 514 characters of it, is gone because nothing downstream reads it.
The whole response went from 3,182 bytes to 1,177, a 63% reduction, and the response carried Token-Tier: 2.
:::note Amounts are raw base units
"value": "5361755468498169704" is 5.36 WETH, not 5.36 × 10¹⁸ of anything. TORPC decodes the ABI; it does not apply token decimals, because that needs a second call to the contract. Read decimals() before showing a human number.
:::
Which methods reach which tier
Twenty-three methods transform today, ten at tier 2 and thirteen at tier 1, probed against Ankr's production Ethereum endpoint on 2026-08-14. Coverage is a property of a deployment rather than of the protocol, so re-probe before quoting it: send the header and read Token-Tier back.
Tier 2, full ABI decode. The methods that carry logs and transactions:
eth_getTransactionByHash, eth_getTransactionReceipt, eth_getBlockByHash, eth_getBlockByNumber, eth_getBlockReceipts, eth_getLogs, eth_getTransactionByBlockHashAndIndex, eth_getTransactionByBlockNumberAndIndex, eth_getUncleByBlockHashAndIndex, eth_getUncleByBlockNumberAndIndex.
The two uncle-by-index methods answer at tier 2 but return null on post-merge mainnet, so they carry no saving to measure.
Tier 1, hex to decimal and field renaming. The scalar and count reads, where there is less to give up and the measured saving runs from roughly 9% to 22%:
eth_blockNumber, eth_chainId, eth_gasPrice, eth_maxPriorityFeePerGas, eth_blobBaseFee, eth_getBalance, eth_getTransactionCount, eth_getBlockTransactionCountByHash, eth_getBlockTransactionCountByNumber, eth_getUncleCountByBlockHash, eth_getUncleCountByBlockNumber, eth_estimateGas, eth_feeHistory.
Sending Accept-Token-Tier: 2 on these is not wasted: the proxy applies the highest tier it has a ruleset for, which is tier 1 here, and says so in the response header.
Tier 0, passthrough. eth_call, eth_getCode and eth_getStorageAt return opaque bytes whose meaning depends on an ABI the proxy has no way to know, so they are never transformed. Every other method still works as ordinary JSON-RPC and answers at tier 0.
The per-method token figures behind these tiers are published in bench/results/live-token-savings-2026-07-17.md.
Discovery
A machine-readable descriptor of all of the above (protocol version, negotiation headers, tier meanings and the method lists) ships as .well-known/torpc.json in the server's public repository. It is a file, not a served endpoint: do not fetch it from rpc.ankr.com or mcp.ankr.com, neither of which serves it.
There is also a legacy request-header alias, Rpc-Compress, accepted for clients written before the header was renamed. New clients should send Accept-Token-Tier.
Using it from an agent
If you are pointing an AI agent at chain data, Agent RPC MCP asks for tier 2 on every read for you, reports the applied tier in each result, and adds paging, display caps and a real token count per response. TORPC is what makes those responses small; the MCP server is what makes them convenient.
Next
- Agent RPC MCP: the hosted MCP server built on this protocol.
- Management MCP: accounts, keys and usage for agents.
- Chains list: where to point
<chain>. - w3tech/torpc: the specification, the per-method mappings and the conformance vectors.
- w3tech/torpc-js: the reference decoder and the benchmark harness.