This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
npm run build # compile TypeScript → dist/
npm run dev # run directly with tsx (no build needed, for development)
npm start # run compiled server (requires build first)There is no test suite yet. Type-check only:
npx tsc --noEmitThis is a stdio MCP server — it communicates over stdin/stdout using the MCP protocol, not HTTP. It is meant to be registered in a Claude client config (Claude Code or Claude Desktop), not run as a long-lived service.
Claude client → MCP stdio transport → McpServer (index.ts)
↓
register*Tools() modules
↓
rpcCall() → Rootstock JSON-RPC endpoint
| File | Role |
|---|---|
src/index.ts |
Entry point: validates env vars, creates McpServer, registers all tool groups, connects stdio transport |
src/rpc-client.ts |
rpcCall<T>(network, method, params) — the single function all tools use to talk to the node |
src/types.ts |
Network type ("mainnet" | "testnet") and JSON-RPC envelope types |
src/utils.ts |
Shared formatters (formatBlock, formatTransaction, weiToRbtc, satoshisToRbtc) and MCP response helpers (toolResult, toolError) |
src/utils/bridge-abi.ts |
Bridge-specific: topic hash maps, decodeBridgeLog, callBridgeFn, fetchLogsChunked |
src/utils/block-range.ts |
getFromBlockForDays — converts a day count to a fromBlock hex value using 30s RSK block time |
Each domain module exports a single register*Tools(server: McpServer) function. All tool inputs are validated with Zod. Every tool returns toolResult(data) on success or toolError(e) on failure — both return the MCP content array shape.
server.tool("tool_name", "description", { /* zod schema */ }, async (args) => {
try {
const data = await rpcCall(args.network, "eth_someMethod", [...]);
return toolResult(data);
} catch (e) {
return toolError(e);
}
});The bridge module (src/tools/bridge.ts) is more complex than the others:
- Log-based tools (
bridge_get_pegins,bridge_get_pegouts): usefetchLogsChunkedwhich splits the block range into 1000-block chunks (10 in parallel) to avoid RPC result-size limits. - Call-based tool (
bridge_get_state,bridge_get_federation): usecallBridgeFnwhich ABI-encodes a call to the bridge precompile at its fixed address (BRIDGE_ADDRESSfrom@rsksmart/rsk-precompiled-abis). - Parser-based tool (
bridge_get_transaction): uses@rsksmart/bridge-transaction-parserwith anethersJsonRpcProvider. This is the only tool that creates a provider directly — all others go throughrpcCall. @rsksmart/rsk-precompiled-abisis a CJS module, loaded viacreateRequireto interop with the ESM project.
- Add a
register*Tools(server)function to an existing domain file insrc/tools/(or create a new one for a new domain). - Import and call it in
src/index.ts. - Use
rpcCallfor JSON-RPC calls; usecallBridgeFnfor bridge precompile calls; usefetchLogsChunkedfor event log queries over wide block ranges. - All monetary values from the bridge are in satoshis (use
satoshisToRbtc); EVM balances are in wei hex (useweiToRbtc).