Skip to main content
Glama

chain-reader — 只读的 Ethereum MCP 服务器

用于让 LLM 以自然语言读取 Ethereum 的 MCP 服务器。 不持有私钥,不签名也不发送交易。所有结果都附带"这个答案来自哪里"。

这是为 Tim Weingärtner (HSLU)《Ethereum & Smart Contracts》最后一章"区块链与 AI"中的图示编写的教材原型,将其做成了可运行的形式。

  LLM         ← 自然言語(「このアドレスは何者?」)
   ↓
  MCP         ← src/server.js
   ↓          ← コード/構造化言語(ABI エンコード)
  RPC         ← src/rpc.js
   ↓
ブロックチェーン

依赖只有 @modelcontextprotocol/sdkzod 两个。 Keccak-256 和 ABI 编码器都是自行实现的(见后文"为什么自己实现")。


运行

git clone <this repo> && cd chain-reader-mcp
npm ci --ignore-scripts
npm test        # 単体 13 件(ネットワーク不要)
npm run smoke   # 実チェーンに対して全ツールを 1 回ずつ

注册到 Claude Code。

claude mcp add chain-reader -- node "$PWD/src/server.js"

如果在此目录下启动 claude,由于存在 .mcp.json,无需注册。 但第一次需要批准claude mcp list 中会显示 ⏸ Pending approval)。 为避免上课当天手忙脚乱,请提前启动一次并完成批准。

如果使用 Claude Desktop,则在 claude_desktop_config.jsonmcpServers 中写入相同内容。 此时 args 请使用绝对路径。

可以通过环境变量切换目标网络。默认为 mainnet。

变量

ETH_NETWORK

mainnet / sepolia / holesky / local

ETH_RPC_URL

自定义端点(指定后优先于网络名称)

两者均使用无需 API 密钥的公共端点。local 指向 anvil / hardhat nodehttp://127.0.0.1:8545


工具与课程的对应关系

课程幻灯片本身在另一个仓库中(私人翻译的日文版), 这里只列出章节名称,即可对应查找。

工具

对应的幻灯片

可以看到什么

chain_info

Gas 与交易手续费 / PoS

基础手续费随区块拥堵程度变化

account_info

两种账户 / Ethereum 地址

根据代码的有无区分 EOA 和合约

read_transaction

在 Etherscan 中读取交易

手续费 = Gas 使用量 × 有效 Gas 价格

read_block

区块

parentHash 的链条就是"不可篡改"的实体

call_contract

ABI / Solidity 入门

选择器是 keccak256(签名) 的前 4 字节

read_token

ERC-20 / ERC-721 / クロークの引換札

名称和符号都是合约自行申报的

read_events

事件驱动的 UI

只有 indexed 的参数会出现在 topic 中

prepare_unsigned_transaction

使用 MCP 时的注意事项

不持有密钥的一方所能做的极限

explain_selector

ABI

不接触网络即可计算选择器(用于板书)

verify_anchor

(论文侧)

哈希锚定能证明什么、不能证明什么

选择 lecture_walkthrough 提示词后,会包含按顺序执行 1 到 6 的指示。

课堂上可直接使用的提问

このネットワークはいま混んでいますか?
0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 は EOA ですか、コントラクトですか?
USDC の総供給量は? その数字は誰が保証していますか?
transfer(address,uint256) のセレクタはなぜ 0xa9059cbb になるのですか?
私のアドレスから 0.001 ETH を送る取引を組み立ててください

对于最后一个问题,AI 可以返回组装好的 JSON,但无法发送。 此时让它解释"为什么无法发送",幻灯片"MCP 使用时的注意事项"中的内容 就会从 AI 自己口中说出来。


设计上的两个承诺

1. 不持有密钥

src/rpc.js 中的 ALLOWED_METHODS 是只读方法的显式白名单。 eth_sendRawTransaction / eth_sendTransaction / eth_sign 不在其中, 一旦尝试调用,会在发出网络请求之前就失败(已通过单元测试固定)。

本仓库中不存在签名实现,也不存在私钥加载逻辑。 无论 LLM 被如何诱导,资金都不会从这里流出。

prepare_unsigned_transaction 的目的不是展示"做不到的事",而是 以可运行的形式展示这个边界。它返回一个填好了 nonce、Gas 估算和手续费的完整交易, 只把签名留给人类。课程幻灯片中的 "MCP 能安全执行的只有两件事:只读调用和已签名交易的中继" 正是这个实现。

2. 不丢弃答案的来源

所有结果都附带 _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 エンドポイントの応答であり、独立に検証したものではない。"
}

这是为了不把"因为是区块链所以正确"当作结论而设计的机制。 LLM 有自信满满地断言数字的倾向,因此让结果本身携带每个主张基于哪一层。 服务器的 instructions 中也指示要区分链保证的事实和 某人申报的内容进行说明。


可归属与可验证是两回事

该服务器的输出设计源自记录管理、数字档案的语境。 能说的事它是真的之间的差异,被嵌入到工具的输出中。

read_tokenself_reported_notename() 返回 "USD Coin" 这一事实 由链保证。但该合约是否真的是 Circle 的合约,则无法保证。 任何人都可以部署同名的合约。 链保证的只是"该地址的代码这样回应了",而非该主张的真伪。

verify_anchorwhat_this_does_not_prove — 锚定提供的是 "何时、谁、主张了什么",而非"该主张是否正确"。 错误测量值的哈希和正确测量值的哈希一样可以被刻入。 真实性的英文是 authenticity,真理性是 truth,这两者的区别直接体现在这里。

_provenance — 记录的质量就是其来源图的形态,这是这一思想的最小实现。 哪个端点、通过哪个 RPC 调用、在多少毫秒内返回了结果。 将 PROV-O 中 prov:wasAttributedTo 的归属者留到之后决定。

从签名声明 / 与公开信息比对 / TEE 证明 / 机构认证,逐层提升 验证强度,但无论到哪一层,"测量仪器本身"都无法被验证。 这个原型演示的正是最底层——可归属但不可验证的领域。 正因如此,才要在记录中保留该数值基于哪一层。


为什么连 Keccak 和 ABI 都自己实现

安装 viemethers 三行就能解决。特意自己实现有两个理由。

  1. 因为这是教学素材。 如果 ABI 是黑盒,就无法解释"为什么是 4 字节"。 src/keccak.jssrc/abi.js 合计约 300 行,学员可以通读。

  2. 因为可以将依赖控制在 2 个。 供应链面积越小, 3 年后执行 npm ci 能跑起来的概率就越高。

Node 的 crypto 中的 sha3-256 是 NIST SHA-3,与 Ethereum 的 Keccak-256 填充方式不同(0x060x01),因此无法复用。这里只能自己实现。

支持范围包括 address / uintN / intN / bool / bytesN / string / bytes 及 其动态数组。不处理元组和嵌套动态数组。作为原型来说已经足够, 但如果要在生产环境中处理任意合约,请替换为 viem


已知限制

  • 信任单一的 RPC。 向多个端点发送相同查询并进行比对, 信任层级就能提升一层。尚未实现

  • 无法处理元组类型。 无法解码类似 Uniswap V3 的 slot0() 的返回值

  • read_events 的扫描范围默认为 200 个区块。 公共端点 可能会拒绝范围过大的 eth_getLogs

  • verify_anchor 使用子字符串匹配进行查找。 如果知道锚定合约的 ABI,应该正确解码参数并进行比对

  • local 网络外,依赖公共端点。考虑到上课当天可能宕机, 使用 anvil --fork-url 在本地进行分叉会更安全

文件结构

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 プロトコルの往復確認
-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Free OpenAI-compatible inference with signed provenance receipts and 3 focused MCP tools.

  • Read-only MCP server for Robinhood Chain token discovery, research, and due diligence via GMGN.

  • MCP server for Blockscout

View all MCP Connectors

Latest Blog Posts

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/nakamura196/chain-reader-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server