chain-reader
Provides read-only access to the Ethereum blockchain, including tools for checking network status, account and transaction details, reading contract state via ABI-encoded calls, examining token information, and scanning event logs.
Provides tools that demonstrate Solidity concepts such as ABI encoding and function selectors, enabling interaction with and understanding of Solidity smart contracts on the Ethereum blockchain.
Click on "Deploy 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., "@chain-reader What's the current gas price on Ethereum?"
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.
chain-reader — Read-only Ethereum MCP server
An MCP server that lets an LLM read Ethereum in natural language. It holds no private keys, signs nothing, and sends nothing. Every result comes with "where that answer came from."
Written as a working teaching prototype of the diagram in the final chapter "Blockchain and AI" of Tim Weingärtner (HSLU)'s Ethereum & Smart Contracts.
LLM ← 自然言語(「このアドレスは何者?」)
↓
MCP ← src/server.js
↓ ← コード/構造化言語(ABI エンコード)
RPC ← src/rpc.js
↓
ブロックチェーンThe only dependencies are @modelcontextprotocol/sdk and zod.
The Keccak-256 and the ABI encoder are both hand-written (see "Why I wrote it by hand" below).
Running it
git clone <this repo> && cd chain-reader-mcp
npm ci --ignore-scripts
npm test # 単体 13 件(ネットワーク不要)
npm run smoke # 実チェーンに対して全ツールを 1 回ずつRegister it with Claude Code.
claude mcp add chain-reader -- node "$PWD/src/server.js"If you launch claude from this directory, the .mcp.json is already there, so no registration is needed.
However, approval is requested the first time only (claude mcp list will show ⏸ Pending approval).
To avoid scrambling on the day of the lecture, launch it once beforehand and approve it.
For Claude Desktop, write the same content in the mcpServers section of claude_desktop_config.json.
In that case, make args an absolute path.
The target network can be switched with environment variables. The default is mainnet.
Variable | Value |
|
|
| Custom endpoint (takes precedence over the network name when specified) |
Both use public endpoints that require no API key. local looks at http://127.0.0.1:8545 from anvil / hardhat node.
Related MCP server: MCP Etherscan Server
Tools and their correspondence to the lecture
The lecture slides themselves live in a separate repository (a private Japanese translation), but listing the section names should be enough to trace the correspondence.
Tool | Corresponding slide | What you can see |
| Gas and transaction fees / PoS | The base fee moves with how congested the block is |
| Two kinds of accounts / Ethereum addresses | EOA vs. contract is distinguished by the presence of code |
| Reading a transaction on Etherscan | Fee = gas used × effective gas price |
| Blocks | The |
| ABI / Solidity introduction | The selector is the first 4 bytes of keccak256(signature) |
| ERC-20 / ERC-721 / cloak exchange token | Both the name and the symbol are self-reported by the contract |
| Event-driven UI | Only |
| Cautions when using MCP | The limits of what a side without keys can do |
| ABI | Computes the selector without touching the network (for the blackboard) |
| (paper side) | What hash anchoring can and cannot prove |
Selecting the lecture_walkthrough prompt inserts instructions to walk through items 1–6 in order.
Questions you can use directly in the lecture
このネットワークはいま混んでいますか?
0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 は EOA ですか、コントラクトですか?
USDC の総供給量は? その数字は誰が保証していますか?
transfer(address,uint256) のセレクタはなぜ 0xa9059cbb になるのですか?
私のアドレスから 0.001 ETH を送る取引を組み立ててくださいFor the last question, the AI returns the assembled JSON but cannot send it. Having it explain "why it cannot send it" makes the content of the slide "Cautions when using MCP" come out of the AI's own mouth.
Two design commitments
1. No keys
ALLOWED_METHODS in src/rpc.js is an explicit whitelist of read-only methods.
eth_sendRawTransaction / eth_sendTransaction / eth_sign are not in it, and
calling them fails before anything reaches the network (pinned down by unit tests).
Neither a signing implementation nor private-key loading exists anywhere in this repository. No matter how the LLM is steered, no funds can move from here.
prepare_unsigned_transaction exists to show this boundary as something that works, not as "something you can't do." It returns a finished transaction with the nonce, gas estimate, and fee all filled in, leaving only the signature to the human. The lecture slide's
"An MCP can safely do only two things: read-only calls and relaying signed transactions"
is implemented exactly as stated.
2. Never throw away where an answer came from
Every result carries _provenance.
"_provenance": {
"endpoint": "https://ethereum-rpc.publicnode.com",
"network": "mainnet (Ethereum Mainnet)",
"rpc_calls": ["eth_blockNumber (1309ms)", "eth_gasPrice (1416ms)", "eth_chainId (1769ms)", "eth_getBlockByNumber (1023ms)"],
"note": "これは単一の RPC エンドポイントの応答であり、独立に検証したものではない。"
}This is a mechanism to keep from stopping at "it's a blockchain, so it's correct."
LLMs have a habit of stating numbers with total confidence, so the result itself carries which claim stands on which layer. The server's instructions also direct the model to distinguish between facts guaranteed by the chain and content someone has self-reported.
Being attributable and being verifiable are different things
This server's output design comes from the context of records management and digital archives. The difference between what can be said and whether it is true is embedded in the tool outputs.
read_token's self_reported_note — the fact that name() returned "USD Coin" is guaranteed by the chain. But it does not guarantee that the contract is really Circle's.
Anyone can deploy a contract with the same name and symbol.
What the chain guarantees is only "the code at this address answered this way," not the truth of that claim.
verify_anchor's what_this_does_not_prove — what anchoring provides is
"when, who, and what was claimed," not "whether the claim is correct."
A hash of a wrong measurement can be anchored just as easily as a hash of a correct one.
The diplomatics distinction that authenticity is not truth comes out exactly as is.
_provenance — a minimal implementation of the idea that the quality of a record is the shape of its provenance graph.
Which endpoint answered, via which RPC call, in how many milliseconds.
It leaves open the decision of who to make the prov:wasAttributedTo in PROV-O terms.
Layering on signed attestations / cross-checking against public information / TEE attestation / institutional authentication increases the strength of verification, but no matter how far you go, "the measuring instrument itself" cannot be verified. What this prototype demonstrates is the bottom layer of that stack — the realm where attribution is possible but verification is not. That is precisely why the record itself must note which layer a number stands on.
Why I wrote Keccak and ABI by hand
Installing viem or ethers would have done it in three lines. There are two reasons I deliberately didn't.
Because it's lecture material. If the ABI stays magic, you can't explain "why 4 bytes."
src/keccak.jsandsrc/abi.jstogether are about 300 lines, short enough for students to read through.Because it keeps dependencies down to two. The smaller the supply-chain surface, the higher the odds that
npm cistill works three years from now.
Node's crypto provides sha3-256, which is NIST SHA-3, and its padding differs from Ethereum's Keccak-256 (0x06 vs. 0x01), so it can't be reused. This one had to be implemented.
The supported range is address / uintN / intN / bool / bytesN / string / bytes and their dynamic arrays. Tuples and nested dynamic arrays are not handled. That's sufficient for a prototype, but if you're going to deal with arbitrary contracts in production, replace it with viem.
Known limitations
It trusts a single RPC. Sending the same query to multiple endpoints and cross-checking would add one layer of trust. Not implemented.
It cannot handle tuple types. Return values like Uniswap V3's
slot0()cannot be decoded.read_eventsscans 200 blocks by default. Public endpoints may reject broadeth_getLogsqueries.verify_anchorsearches by substring match. If the anchor contract's ABI is known, it should decode the arguments properly and match against them.Everything except the
localnetwork depends on public endpoints. To be safe against an outage on the day of the lecture, fork locally withanvil --fork-url.
File structure
src/keccak.js Keccak-256(既知ベクタで固定)
src/abi.js ABI エンコード/デコード
src/rpc.js JSON-RPC クライアント + 読み取り専用ホワイトリスト
src/tools.js ツール 10 個の実体。MCP から独立していて単体で呼べる
src/server.js MCP サーバ(stdio)
test/unit.test.js ネットワーク不要の単体テスト
test/smoke.mjs 実チェーンに対する疎通確認
test/mcp-handshake.mjs MCP プロトコルの往復確認Available Tools
10 toolsaccount_infoアカウントを調べるARead-only
アドレスの残高・送信済みトランザクション数 (nonce)・コードの有無を返す。コードの有無で EOA(秘密鍵で操作するアカウント)とコントラクトを判別する。
Inputs: address (required), block, network.
call_contractコントラクトの読み取り関数を呼ぶARead-only
任意のコントラクトの view / pure 関数を eth_call で呼ぶ。関数署名から keccak256 でセレクタを計算し、引数を ABI エンコードして送り、戻り値をデコードして返す。状態は変わらず、ガスもかからない。
Inputs: address (required), signature (required), args, block, +2 more.
chain_infoチェーンの現況ARead-only
チェーン ID、最新ブロック、基本手数料 (base fee)、ブロックの混み具合を返す。「いまネットワークはどうなっているか」を最初に見るためのツール。
Inputs: network.
explain_selector関数セレクタ/イベント topic を計算するARead-only
関数署名やイベント署名から keccak256 を計算し、セレクタ(先頭 4 バイト)や topic0 を示す。ネットワークには一切アクセスしない。ABI がどこから来るのかを黒板で説明するためのツール。
Inputs: signature (required).
prepare_unsigned_transaction未署名トランザクションを組み立てるARead-only
nonce・ガス見積もり・手数料を埋めた EIP-1559 形式のトランザクションを組み立てて返す。【重要】このサーバは署名も送信もしない。返るのは人間が MetaMask やハードウェアウォレットで内容を確認してから署名するための JSON。LLM に鍵を渡さないという境界を、実際に動く形で示すためのツール。
Inputs: to (required), from (required), args, network, +2 more.
read_blockブロックを読むARead-only
ブロックのヘッダ情報(親ハッシュ、時刻、ガス使用量、収録トランザクション数)を返す。
Inputs: block, network, include_transactions.
read_eventsイベントログを読むARead-only
コントラクトが発火したイベントを取得してデコードする。イベント署名の keccak256 が topic0 になり、indexed の引数だけが topic に載る、という仕組みがそのまま見える。dApp の画面更新はこれを購読している。
Inputs: event_signature (required), limit, address, network, +2 more.
read_tokenトークンを調べるARead-only
ERC-20 / ERC-721 / ERC-1155 を判別し、名称・記号・小数桁・総供給量を読む。holder を渡せば残高、token_id を渡せば NFT の所有者と tokenURI も読む。
Inputs: address (required), holder, network, token_id.
read_transactionトランザクションを読むBRead-only
トランザクションと領収書 (receipt) を突き合わせて、送信者・宛先・送金額・ガス・実際に払った手数料・成否・calldata の関数セレクタを人間が読める形で返す。Etherscan の画面を読むのと同じ作業。
Inputs: hash (required), network.
verify_anchorチェーンに刻まれたハッシュと手元のファイルを突き合わせるARead-only
手元のファイル(またはテキスト)の keccak256 を計算し、指定したトランザクションの calldata やイベントログにその値が現れるかを確認する。存在証明とタイムスタンプの検証。結果には「これで何が証明できて、何が証明できないか」を必ず併記する。
Inputs: tx_hash (required), text, network, file_path, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 10 tools
Each tool addresses a distinct blockchain data aspect: network info, account info, transaction details, block details, contract calls, token data, event logs, unsigned tx preparation, anchor verification, and selector computation. Even call_contract and read_token serve different levels of abstraction, avoiding functional overlap.
Most tools follow a verb_noun pattern (read_transaction, call_contract, prepare_unsigned_transaction), but chain_info and account_info are noun_noun, creating a minor inconsistency. All names are descriptive and underscore-separated, which helps clarity.
With 10 tools, the server provides comprehensive coverage of blockchain reading and related utilities without unnecessary redundancy. The count is well-balanced for its stated purpose.
The server covers core read operations (chain, account, transactions, blocks, contracts, tokens, events) and adjacent utilities (tx preparation, hashing). Missing features like batch transaction listing or account history are minor gaps that agents can work around.
Maintenance
Related MCP Connectors
Self-hosted MCP server: 26 deterministic dev, security, and EVM tools.
An MCP server that provides read access to your cloud storage providers, bank accounts and more.
Read-only MCP server for The Quiet Protocol's engines, benchmarks, proof, and business data.
Free OpenAI-compatible inference with signed provenance receipts and 3 focused MCP tools.
Related MCP Servers
- AlicenseBqualityDmaintenanceAn MCP server that provides access to Etherscan blockchain data APIs, allowing users to query Ethereum blockchain information through natural language.655 npm18MIT
- AlicenseBqualityDmaintenanceAn MCP server providing comprehensive access to Ethereum blockchain data across 72+ networks via Etherscan's V2 API. It enables users to check balances, track transactions, analyze smart contracts, and monitor gas prices through natural language.2415 npm1MIT
- AlicenseNot gradedqualityBmaintenanceAn MCP server that bridges AI models with Ethereum blockchains via all JSON-RPC calls, enabling natural language queries for block numbers, balances, transactions, and smart contract data.7 npm21MIT
- AlicenseAqualityCmaintenanceA read-only MCP server that queries multichain EVM on-chain data through Blockscout REST API, providing tools for address info, transactions, logs, and more.1625 npmMIT