Skip to main content
Glama

chain-reader — servidor MCP de Ethereum de solo lectura

Un servidor MCP para que un LLM lea Ethereum en lenguaje natural. No tiene claves privadas, no firma ni envía nada. Todos los resultados llevan «de dónde ha salido esa respuesta».

Escrito como prototipo didáctico que convierte en algo funcional la figura del último capítulo «Blockchain e IA» de "Ethereum & Smart Contracts" de Tim Weingärtner (HSLU).

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

Las únicas dependencias son @modelcontextprotocol/sdk y zod. Tanto el Keccak-256 como el codificador ABI están implementados a mano (ver más abajo «Por qué lo escribí a mano»).


Ponerlo en marcha

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

Registrarlo en Claude Code.

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

Si arrancas claude en este directorio, no hace falta registrarlo porque ya hay un .mcp.json. Pero solo la primera vez te pedirá aprobación (en claude mcp list aparece ⏸ Pending approval). Para no llevarte un susto el día de la clase, arráncalo una vez antes y confírmalo.

En Claude Desktop, escribe el mismo contenido en mcpServers de claude_desktop_config.json. En ese caso, args debe ser una ruta absoluta.

Se puede cambiar la red de destino con variables de entorno. Por defecto es mainnet.

Variable

Valor

ETH_NETWORK

mainnet / sepolia / holesky / local

ETH_RPC_URL

Endpoint propio (si se indica, tiene prioridad sobre el nombre de la red)

En todos los casos se usan endpoints públicos que no requieren API key. local mira el http://127.0.0.1:8545 de anvil / hardhat node.


Correspondencia entre herramientas y la clase

Las diapositivas de la clase están en otro repositorio (traducción privada al japonés), pero con los nombres de las secciones basta para seguir la correspondencia.

Herramienta

Diapositiva correspondiente

Qué se ve

chain_info

Gas y tarifas de transacción / PoS

La tarifa base se mueve según la congestión del bloque

account_info

Los dos tipos de cuenta / Direcciones de Ethereum

Que EOA y contrato se distinguen por la presencia de código

read_transaction

Leer una transacción en Etherscan

Tarifa = gas usado × precio del gas efectivo

read_block

Bloque

La cadena de parentHash es la realidad de «imposible de falsificar»

call_contract

ABI / Introducción a Solidity

Que el selector son los primeros 4 bytes de keccak256(firma)

read_token

ERC-20 / ERC-721 / la ficha del guardarropa

Que nombre y símbolo son autodeclarados por el contrato

read_events

UI dirigida por eventos

Que solo los argumentos indexed van en el topic

prepare_unsigned_transaction

Aviso al usar MCP

El límite de lo que puede hacer quien no tiene la clave

explain_selector

ABI

Calcula el selector sin tocar la red (para la pizarra)

verify_anchor

(lado del artículo)

Qué puede y qué no puede probar el anclaje de un hash

Si eliges el prompt lecture_walkthrough, se incluyen instrucciones para recorrer del 1 al 6 en orden.

Preguntas que se pueden usar tal cual en clase

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

En la última pregunta, la IA devuelve el JSON que ha montado, pero no puede enviarlo. Si le pides que explique «por qué no puede enviarlo», el contenido de la diapositiva «Aviso al usar MCP» sale de la propia boca de la IA.


Dos compromisos de diseño

1. No tener claves

ALLOWED_METHODS en src/rpc.js es una lista blanca explícita de métodos de solo lectura. eth_sendRawTransaction / eth_sendTransaction / eth_sign no están en ella: si se intentan llamar, fallan antes de salir a la red (está fijado en las pruebas unitarias).

En este repositorio no existe ni implementación de firma ni carga de claves privadas. Por mucho que se intente engañar al LLM, desde aquí no se mueve dinero.

prepare_unsigned_transaction existe para mostrar este límite en forma funcional, no como «lo que no se puede hacer». Devuelve el producto terminado con nonce, estimación de gas y tarifa ya rellenados, y deja solo la firma para el humano. La diapositiva de la clase «Lo único que MCP puede hacer con seguridad se limita a dos cosas: llamadas de solo lectura y retransmisión de transacciones firmadas» está implementada tal cual.

2. No descartar la procedencia de las respuestas

Todos los resultados llevan _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 エンドポイントの応答であり、独立に検証したものではない。"
}

Es un mecanismo para no quedarse en «es correcto porque es blockchain». Los LLM tienen la costumbre de afirmar números con total seguridad, así que el propio resultado lleva incorporado qué afirmación se apoya en qué capa. Las instructions del servidor también indican que se distinga entre los hechos garantizados por la cadena y los contenidos declarados por alguien.


Poder atribuir no es lo mismo que poder verificar

El diseño de salida de este servidor viene del contexto de la gestión documental y los archivos digitales. La diferencia entre lo que se puede afirmar y que sea verdad está incrustada en la salida de las herramientas.

self_reported_note de read_token — el hecho de que name() haya devuelto "USD Coin" lo garantiza la cadena. Pero no garantiza que ese contrato sea realmente de Circle. Cualquiera puede desplegar un contrato con el mismo nombre y el mismo símbolo. Lo que la cadena garantiza llega hasta «el código de esta dirección ha respondido esto», no hasta la verdad de esa afirmación.

what_this_does_not_prove de verify_anchor — lo que da el anclaje es «cuándo, quién y qué afirmó», no «si esa afirmación es correcta». El hash de una medición errónea se puede grabar igual que el de una medición correcta. Sale directamente la distinción de la diplomática: la autenticidad (authenticity) no es la verdad (truth).

_provenance — la implementación mínima de la idea de que la calidad de un registro es la forma de su grafo de procedencia. Qué endpoint respondió, con qué llamada RPC y en cuántos milisegundos. Deja en un estado en el que se pueda decidir después a quién asignar el prov:wasAttributedTo de PROV-O.

Si se sube de capa — declaraciones firmadas / contraste con información pública / atestación TEE / autenticación institucional — la fuerza de la verificación aumenta, pero por mucho que se suba, «el propio instrumento de medición» no se puede verificar. Lo que este prototipo demuestra es la capa más baja de todas: el territorio donde se puede atribuir pero no verificar. Por eso se deja en el registro sobre qué capa se apoya cada cifra.


Por qué escribí a mano también el Keccak y el ABI

Con viem o ethers bastarían tres líneas. Hay dos razones por las que lo hice a propósito.

  1. Porque es material de clase. Si el ABI sigue siendo magia, no se puede explicar «por qué son 4 bytes». src/keccak.js y src/abi.js suman unas 300 líneas, así que los estudiantes pueden leerlas enteras.

  2. Porque permite reducir las dependencias a dos. Cuanto menor es la superficie de la cadena de suministro, mayor es la probabilidad de que npm ci siga funcionando dentro de tres años.

El sha3-256 que hay en crypto de Node es NIST SHA-3 y no se puede reutilizar para el Keccak-256 de Ethereum porque el padding es distinto (0x06 y 0x01). Aquí no queda más remedio que implementarlo.

La cobertura llega a address / uintN / intN / bool / bytesN / string / bytes y sus arrays dinámicos. No se manejan tuplas ni arrays dinámicos anidados. Para un prototipo es suficiente, pero si en producción vas a tratar con contratos arbitrarios, sustitúyelo por viem.


Limitaciones conocidas

  • Confía en un único RPC. Si se lanzara la misma pregunta a varios endpoints y se contrastaran las respuestas, la capa de confianza subiría un nivel. No está implementado.

  • No puede manejar tipos tupla. No puede decodificar valores de retorno como slot0() de Uniswap V3.

  • El rango de exploración de read_events es de 200 bloques por defecto. Los endpoints públicos pueden rechazar eth_getLogs demasiado amplios.

  • verify_anchor busca por coincidencia de subcadenas. Si se conoce el ABI del contrato de anclaje, debería decodificar los argumentos correctamente y contrastarlos.

  • Excepto en la red local, depende de endpoints públicos. Por si acaso se cae el día de la clase, es seguro hacer un fork local con anvil --fork-url.

Estructura de archivos

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