Skip to content

Commit 1664bee

Browse files
Merge remote-tracking branch 'origin/main' into jklondon/caplintypesnotnil
2 parents b9453af + 46e8af5 commit 1664bee

File tree

8 files changed

+434
-19
lines changed

8 files changed

+434
-19
lines changed

db/state/aggregator.go

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ type Aggregator struct {
7676

7777
// To keep DB small - need move data to small files ASAP.
7878
// It means goroutine which creating small files - can't be locked by merge or indexing.
79-
buildingFiles atomic.Bool
80-
mergingFiles atomic.Bool
79+
buildingFiles atomic.Bool
80+
mergingFiles atomic.Bool
81+
rebuildingAccessors atomic.Bool
8182

8283
//warmupWorking atomic.Bool
8384
ctx context.Context
@@ -477,7 +478,7 @@ func (a *Aggregator) LockWorkersEditing() { a.lockWorkersEditing = true }
477478
func (a *Aggregator) UnlockWorkersEditing() { a.lockWorkersEditing = false }
478479

479480
func (a *Aggregator) HasBackgroundFilesBuild2() bool {
480-
return a.buildingFiles.Load() || a.mergingFiles.Load()
481+
return a.buildingFiles.Load() || a.mergingFiles.Load() || a.rebuildingAccessors.Load()
481482
}
482483

483484
func (a *Aggregator) HasBackgroundFilesBuild() bool { return a.ps.Has() }
@@ -539,14 +540,15 @@ func (a *Aggregator) WaitForBuildAndMerge(ctx context.Context) chan struct{} {
539540

540541
chkEvery := time.NewTicker(3 * time.Second)
541542
defer chkEvery.Stop()
542-
for a.buildingFiles.Load() || a.mergingFiles.Load() {
543+
for a.buildingFiles.Load() || a.mergingFiles.Load() || a.rebuildingAccessors.Load() {
543544
select {
544545
case <-ctx.Done():
545546
return
546547
case <-chkEvery.C:
547548
a.logger.Trace("[agg] waiting for files",
548549
"building files", a.buildingFiles.Load(),
549-
"merging files", a.mergingFiles.Load())
550+
"merging files", a.mergingFiles.Load(),
551+
"rebuilding accessors", a.rebuildingAccessors.Load())
550552
}
551553
}
552554
}()
@@ -603,6 +605,39 @@ func (a *Aggregator) BuildMissedAccessors(ctx context.Context, workers int) erro
603605
return nil
604606
}
605607

608+
// BuildMissedAccessorsInBackground starts a background goroutine to rebuild
609+
// any missing E3 state accessors. Returns true if the rebuild was started,
610+
// false if one is already running.
611+
// This mirrors RetireBlocksInBackground (which calls BuildMissedIndicesIfNeed)
612+
// for E2 block indices.
613+
func (a *Aggregator) BuildMissedAccessorsInBackground(workers int) bool {
614+
if !a.rebuildingAccessors.CompareAndSwap(false, true) {
615+
return false
616+
}
617+
a.wg.Add(1)
618+
go func() {
619+
defer a.wg.Done()
620+
defer a.rebuildingAccessors.Store(false)
621+
622+
if a.snapshotBuildSema != nil {
623+
// We are inside our own goroutine — it's fine to block here.
624+
if err := a.snapshotBuildSema.Acquire(a.ctx, 1); err != nil {
625+
a.logger.Warn("[snapshots] BuildMissedAccessors background: sema", "err", err)
626+
return
627+
}
628+
defer a.snapshotBuildSema.Release(1)
629+
}
630+
631+
if err := a.BuildMissedAccessors(a.ctx, workers); err != nil {
632+
if errors.Is(err, context.Canceled) || errors.Is(err, common.ErrStopped) {
633+
return
634+
}
635+
a.logger.Warn("[snapshots] BuildMissedAccessors background", "err", err)
636+
}
637+
}()
638+
return true
639+
}
640+
606641
type AggV3StaticFiles struct {
607642
d [kv.DomainLen]StaticFiles
608643
ivfs []InvertedFiles

docs/gitbook/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
* [TxPool](fundamentals/modules/txpool.md)
3838
* [Sentry](fundamentals/modules/sentry.md)
3939
* [Downloader](fundamentals/modules/downloader.md)
40+
* [MCP Server](fundamentals/mcp.md)
4041
* [Creating a dashboard](fundamentals/creating-a-dashboard.md)
4142
* [Docker Compose](fundamentals/docker-compose.md)
4243
* [Otterscan](fundamentals/otterscan.md)
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
---
2+
description: >-
3+
Using Erigon's Model Context Protocol (MCP) server to interact with
4+
blockchain data through AI assistants
5+
metaLinks:
6+
alternates:
7+
- https://app.gitbook.com/s/3DGBf2RdbfoitX1XMgq0/fundamentals/mcp
8+
---
9+
10+
# MCP Server
11+
12+
The **Model Context Protocol (MCP)** is an open standard developed by Anthropic that allows AI assistants (such as Claude Desktop) to securely connect to external data sources and tools. MCP defines a uniform interface through which an AI model can discover, read, and invoke capabilities provided by a server — without needing any custom integration code.
13+
14+
Erigon ships a full MCP server implementation. Once connected, an AI assistant gains structured, read-only access to Ethereum blockchain data, Erigon logs, and internal metrics — turning natural-language questions into precise on-chain lookups.
15+
16+
{% hint style="success" %}
17+
MCP is a read-only interface: the server exposes query tools only. No write operations (sending transactions, changing state) are available.
18+
{% endhint %}
19+
20+
## Two Server Variants
21+
22+
Erigon provides two ways to run the MCP server:
23+
24+
### Embedded (inside Erigon)
25+
26+
The MCP server runs inside the main `erigon` process, with direct access to internal APIs and Prometheus metrics. Enable it with `--mcp.addr` and `--mcp.port`:
27+
28+
```bash
29+
./build/bin/erigon --datadir=./data --mcp.addr=127.0.0.1 --mcp.port=8553
30+
```
31+
32+
This mode uses **SSE (Server-Sent Events)** transport over HTTP and is the simplest option when you are already running a full Erigon node.
33+
34+
### Standalone (`mcp` binary)
35+
36+
A separate `mcp` binary that connects to an existing Erigon node either via its JSON-RPC endpoint or directly via the MDBX database. Supports both **stdio** (for Claude Desktop) and **SSE** transports.
37+
38+
```bash
39+
make mcp
40+
./build/bin/mcp --help
41+
```
42+
43+
## Configuration
44+
45+
### Flags (embedded mode)
46+
47+
| Flag | Default | Description |
48+
|------|---------|-------------|
49+
| `--mcp.addr` | `127.0.0.1` | Listening address for the embedded MCP server |
50+
| `--mcp.port` | `8553` | Listening port for the embedded MCP server |
51+
52+
### Flags (standalone `mcp` binary)
53+
54+
| Flag | Default | Description |
55+
|------|---------|-------------|
56+
| `--rpc.url` | `http://127.0.0.1:8545` | Erigon JSON-RPC endpoint to proxy |
57+
| `--port` || Shorthand for `--rpc.url http://127.0.0.1:<port>` |
58+
| `--datadir` || Erigon data directory (enables direct DB access mode) |
59+
| `--private.api.addr` | `127.0.0.1:9090` | gRPC private API address (used with `--datadir`) |
60+
| `--transport` | `stdio` | Transport type: `stdio` or `sse` |
61+
| `--sse.addr` | `127.0.0.1:8553` | SSE listen address (when `--transport sse`) |
62+
| `--log.dir` || Path to Erigon log directory (enables log analysis tools) |
63+
64+
## Connection Modes (standalone)
65+
66+
The standalone `mcp` binary supports three connection modes, tried in priority order:
67+
68+
### 1. JSON-RPC Proxy (recommended)
69+
70+
Forwards tool calls to a running Erigon node's HTTP JSON-RPC endpoint. Works with any Erigon instance that has the RPC server enabled.
71+
72+
```bash
73+
# Explicit URL
74+
./build/bin/mcp --rpc.url http://127.0.0.1:8545
75+
76+
# Port shorthand
77+
./build/bin/mcp --port 8545
78+
79+
# With log analysis enabled
80+
./build/bin/mcp --port 8545 --log.dir /data/erigon/logs
81+
```
82+
83+
### 2. Direct Datadir Access
84+
85+
Opens Erigon's MDBX database directly — similar to an external `rpcdaemon`. Requires either a running Erigon instance with the gRPC private API, or read-only local disk access.
86+
87+
```bash
88+
# gRPC + direct DB
89+
./build/bin/mcp --datadir /data/erigon --private.api.addr 127.0.0.1:9090
90+
91+
# Default private.api.addr (127.0.0.1:9090)
92+
./build/bin/mcp --datadir /data/erigon
93+
```
94+
95+
### 3. Auto-Discovery
96+
97+
When started without flags, the binary probes `localhost:8545`, `8546`, and `8547` for a running JSON-RPC endpoint:
98+
99+
```bash
100+
./build/bin/mcp
101+
```
102+
103+
## Use Cases
104+
105+
### Interactive Blockchain Analysis
106+
107+
Connect your AI assistant to a running Erigon node and ask natural-language questions about on-chain data without writing a single line of code.
108+
109+
> **"What is the ETH balance of vitalik.eth right now, and how many transactions has it sent?"**
110+
>
111+
> The assistant calls `eth_getBalance` and `eth_getTransactionCount` on the address, formats the results in human-readable form, and summarises the answer.
112+
113+
> **"Show me all ERC-20 Transfer events emitted in the last 100 blocks from contract 0xA0b…"**
114+
>
115+
> The assistant calls `eth_getLogs` with the appropriate filter, decodes the ABI-encoded topics, and presents a table of transfers with amounts and counterparties.
116+
117+
> **"Which transactions in block 21,000,000 consumed the most gas?"**
118+
>
119+
> The assistant calls `eth_getBlockByNumber` and `eth_getBlockReceipts`, sorts by gas used, and returns the top offenders with links to the relevant hashes.
120+
121+
### Node Debugging and Monitoring
122+
123+
When something looks wrong with your node, ask the assistant to sift through logs and metrics for you.
124+
125+
> **"My node seems stuck. Check the sync status and the last 50 log lines for any errors."**
126+
>
127+
> The assistant calls `eth_syncing` to get the current sync progress, then uses `logs_tail` and `logs_grep` to search for `ERROR` or `WARN` entries — surfacing actionable information without requiring you to SSH into the server.
128+
129+
> **"Are there any unusual patterns in the torrent download stats over the last hour?"**
130+
>
131+
> Using the `torrent_status` prompt and `logs_stats`, the assistant analyses download throughput, stall events, and peer connectivity in a single conversational turn.
132+
133+
## Setting Up with Claude Desktop
134+
135+
Add the following to your Claude Desktop configuration file (`~/.config/claude-desktop/config.json` on Linux/macOS, `%APPDATA%\claude-desktop\config.json` on Windows):
136+
137+
{% tabs %}
138+
{% tab title="JSON-RPC mode" %}
139+
```json
140+
{
141+
"mcpServers": {
142+
"erigon": {
143+
"command": "/path/to/build/bin/mcp",
144+
"args": ["--port", "8545", "--log.dir", "/data/erigon/logs"]
145+
}
146+
}
147+
}
148+
```
149+
{% endtab %}
150+
{% tab title="Datadir mode" %}
151+
```json
152+
{
153+
"mcpServers": {
154+
"erigon": {
155+
"command": "/path/to/build/bin/mcp",
156+
"args": ["--datadir", "/data/erigon"]
157+
}
158+
}
159+
}
160+
```
161+
{% endtab %}
162+
{% tab title="Embedded (SSE)" %}
163+
```json
164+
{
165+
"mcpServers": {
166+
"erigon": {
167+
"type": "sse",
168+
"url": "http://127.0.0.1:8553/sse"
169+
}
170+
}
171+
}
172+
```
173+
174+
Start Erigon with `--mcp.addr=127.0.0.1 --mcp.port=8553` to enable the embedded SSE endpoint.
175+
{% endtab %}
176+
{% endtabs %}
177+
178+
After saving, restart Claude Desktop. The Erigon tools will appear in the tool panel under **erigon**.
179+
180+
## Available Tools
181+
182+
The MCP server exposes over 40 tools grouped by namespace:
183+
184+
### Ethereum Standard (`eth_*`)
185+
186+
Standard JSON-RPC methods exposed as MCP tools: `eth_blockNumber`, `eth_getBlockByNumber`, `eth_getBlockByHash`, `eth_getBalance`, `eth_getTransactionByHash`, `eth_getTransactionReceipt`, `eth_getBlockReceipts`, `eth_getLogs`, `eth_getCode`, `eth_getStorageAt`, `eth_getTransactionCount`, `eth_call`, `eth_estimateGas`, `eth_gasPrice`, `eth_chainId`, `eth_syncing`, `eth_getProof`, and more.
187+
188+
### Erigon-Specific (`erigon_*`)
189+
190+
`erigon_nodeInfo`, `erigon_forks`, `erigon_getBlockByTimestamp`, `erigon_getBalanceChangesInBlock`, `erigon_getLogsByHash`, `erigon_getBlockReceiptsByBlockHash`, and more.
191+
192+
### Otterscan (`ots_*`)
193+
194+
`ots_getInternalOperations`, `ots_searchTransactionsBefore`, `ots_searchTransactionsAfter`, `ots_getBlockDetails`, `ots_traceTransaction`, `ots_getTransactionError`, `ots_getContractCreator`, and more.
195+
196+
### Log Analysis (`logs_*`)
197+
198+
`logs_tail`, `logs_head`, `logs_grep`, `logs_stats` — require `--log.dir` or `--datadir` to locate Erigon log files.
199+
200+
### Metrics (`metrics_*`)
201+
202+
`metrics_list`, `metrics_get` — available in **embedded mode only**. In standalone mode these return a descriptive message.
203+
204+
## Resources and Prompts
205+
206+
In addition to tools, the MCP server exposes structured **resources** and **prompts**:
207+
208+
**Resources** (addressable by URI):
209+
210+
| Resource | Description |
211+
|----------|-------------|
212+
| `erigon://node/info` | Node version, chain, capabilities |
213+
| `erigon://chain/config` | Full chain configuration |
214+
| `erigon://blocks/recent` | Last 10 blocks summary |
215+
| `erigon://network/status` | Sync state and peer count |
216+
| `erigon://gas/current` | Current gas price |
217+
| `erigon://address/{address}/summary` | Balance, nonce, contract status |
218+
| `erigon://block/{number}/summary` | Block summary |
219+
| `erigon://transaction/{hash}/analysis` | Transaction analysis |
220+
221+
**Prompts** (pre-built analysis templates):
222+
223+
| Prompt | Description |
224+
|--------|-------------|
225+
| `analyze_transaction` | Deep-dive into a transaction |
226+
| `investigate_address` | Profile an address (balance, history, code) |
227+
| `analyze_block` | Summarise a block and its transactions |
228+
| `gas_analysis` | Current and historical gas price analysis |
229+
| `debug_logs` | Triage node issues from recent log output |
230+
| `torrent_status` | Snapshot download health check |
231+
| `sync_analysis` | Node sync progress and performance |

docs/gitbook/src/interacting-with-erigon/grpc.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ metaLinks:
99

1010
Erigon provides gRPC APIs that allow users to access blockchain data and services directly through protocol buffer interfaces. These APIs offer high-performance, strongly-typed access to Erigon's internal services and are particularly useful for applications requiring efficient data access or integration with other gRPC-based systems.
1111

12-
The gRPC server must be explicitly enabled using the `--grpc` flag when starting the RPC daemon, and can be configured with custom listening addresses, ports, and TLS settings.
12+
The gRPC server can be explicitly enabled using the `--grpc` flag when running the **standalone `rpcdaemon`** binary. This flag is **not available** on the main `erigon` binary — internal gRPC services for components like txpool, downloader, and sentry start automatically on the `--private.api.addr` endpoint and do not require any additional flag.
1313

1414
### Performance Considerations
1515

@@ -33,7 +33,7 @@ Erigon provides Go, Rust, and C++ implementations of the RoKV (read-only key-val
3333

3434
### Availability
3535

36-
* gRPC services are available when enabled with the `--grpc` flag
36+
* gRPC services are available when enabled with the `--grpc` flag on the **standalone `rpcdaemon`** binary
3737
* Default listening address is configurable via `--grpc.addr` and `--grpc.port`
3838
* Services require the main Erigon node to be running and accessible
3939

0 commit comments

Comments
 (0)