rpc/mcp: dedupe embedded and standalone servers; implement in-process resource handlers#22169
Merged
Conversation
The embedded server's resource handlers were placeholders: the network-status resource hardcoded syncing=false, and the three template handlers (address summary, block summary, transaction analysis) used the raw resource URI as the address/number/hash instead of extracting the template parameter, so they returned garbage or errored. Transaction analysis also hardcoded status=success. Mirror the standalone server's semantics: extract template parameters via extractURIParam (moved to utils.go), report the real eth_syncing result, and derive success/reverted/unknown from the receipt status field.
The embedded and standalone MCP servers each carried their own copies of the tool catalog (~330 lines each), the prompts, the resource registration, and the log-file handlers. Move the tool specs to a shared table consumed via per-server handler maps, make prompt/resource registration free functions over per-server handler sets, and fold the four log handlers into a logTools struct embedded by both servers. registerTools panics on any catalog/handler mismatch and TestEmbeddedAndStandaloneCatalogsMatch pins the two servers to the same tool, prompt, and resource catalogs (embedded additionally exposes eth_getStorageValues).
Contributor
There was a problem hiding this comment.
Pull request overview
This PR deduplicates the embedded and standalone MCP server implementations in rpc/mcp and brings the embedded (in-process) resource handlers up to parity with the standalone (JSON-RPC proxy) behavior, with tests to prevent future drift.
Changes:
- Implement real in-process MCP resource handling for address/block/tx resources (URI param extraction,
eth_syncing, receipt status derivation). - Centralize shared MCP registration surfaces: shared tool specs + per-server handler maps, shared prompt/resource registration, and shared log tool handlers via an embedded
logTools. - Add tests that pin embedded vs standalone tool/prompt/resource catalogs and validate resource behavior.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| rpc/mcp/utils.go | Adds shared extractURIParam helper. |
| rpc/mcp/tools.go | Introduces shared tool catalog (toolSpecs) and registerTools with handler/spec consistency checks. |
| rpc/mcp/standalone.go | Switches standalone server to shared registration and shared logTools; introduces toolHandlers/resourceHandlers. |
| rpc/mcp/resources.go | Refactors resource registration into a shared function and implements real embedded resource handlers (syncing + URI param extraction + receipt status). |
| rpc/mcp/resources_test.go | Adds TDD-style unit tests for embedded resource handlers and URI param extraction. |
| rpc/mcp/prompts.go | Refactors prompt registration into a shared function used by both servers. |
| rpc/mcp/mcp.go | Switches embedded server to shared registration and shared logTools; adds toolHandlers and embedded-only storage-values tool registration. |
| rpc/mcp/mcp_test.go | Adds catalog drift test comparing embedded vs standalone tools/prompts/resources/templates. |
| rpc/mcp/handlers_logs.go | Deduplicates log tool handlers into reusable logTools with shared log-file resolution. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…Keys A nil resourceHandlerSet field registered silently and only failed on resources/read of the affected resource (unrecovered: WithRecovery only covers tool handlers). Mirror the registerTools guard by panicking at registration time. sortedKeys did not sort; ElementsMatch does not need it to.
TrimPrefix/TrimSuffix passed non-conforming URIs through as if they were valid parameters; CutPrefix/CutSuffix return "" instead, which callers already treat as a missing parameter.
AskAlexSharov
approved these changes
Jul 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The package carried two parallel MCP servers —
ErigonMCPServer(in-process typed APIs) andStandaloneMCPServer(JSON-RPC proxy) — with independently maintained copies of the tool catalog (~330 lines each, 264 of 270 non-blank registration lines identical), the prompts (136 lines byte-identical), the resource registration, and the log-file handlers. The copies had already drifted the worst way possible: the in-process resource handlers were still placeholders (raw URI used as the address, hardcoded"syncing": falseand"status": "success") while the standalone copies had the real logic.Two commits:
extractURIParam, realeth_syncing, receipt-status derivation, mirroring the standalone behavior through the typed APIs.toolSpecs()table consumed via per-servertoolHandlers()maps (registerToolspanics on any catalog/handler mismatch);registerPrompts/registerResourcesas free functions over per-server handler sets; the four log handlers folded into alogToolsstruct embedded by both servers (also deduping the log-file-resolution switch that was inlined 4×).eth_getStorageValuesstays embedded-only.TestEmbeddedAndStandaloneCatalogsMatchpins both servers to identical tool/prompt/resource catalogs so they cannot drift silently again.Net: −248 lines despite +~130 of new tests; standalone.go alone went 1724 → 1129 lines. Verified: package tests, scoped
golangci-lintclean (×2),make erigon.Part of a dedup series; siblings #22165–#22168.