Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,3 @@
go.work

# End of https://www.toptal.com/developers/gitignore/api/go,direnv,dotenv

// Custom
go.work.sum
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
golang 1.24.4
golang 1.25.4
golangci-lint 2.4.0
pre-commit 4.2.0
python 3.10.4
25 changes: 0 additions & 25 deletions gen/go.mod

This file was deleted.

37 changes: 0 additions & 37 deletions gen/go.sum

This file was deleted.

80 changes: 80 additions & 0 deletions gen/internal/openrpc/data/trace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
- name: debug_storageRangeAt
summary: Returns the storage range at a given block hash and transaction index
params:
- name: blockHash
schema:
$ref: '../../schemas.yaml#/components/schemas/BLOCK_HASH'
- name: txIndex
schema:
type: integer
- name: address
schema:
$ref: '../../schemas.yaml#/components/schemas/ADDRESS'
- name: startKey
schema:
$ref: '../../schemas.yaml#/components/schemas/HASH'
- name: maxResult
schema:
type: integer
result:
name: storage
schema:
$ref: '../../schemas.yaml#/components/schemas/StorageRange'
- name: debug_traceBlock
summary: The traceBlock method returns the full trace of a block.
params:
- name: blockRlp
schema:
$ref: '../../schemas.yaml#/components/schemas/BYTES'
- name: options
schema:
$ref: '../../schemas.yaml#/components/schemas/TraceOptions'
result:
name: trace
schema:
type: array
items:
$ref: '../../schemas.yaml#/components/schemas/BlockTrace'
- name: debug_traceBlockByHash
summary: The traceBlockByHash method returns the full trace of a block.
params:
- name: blockHash
schema:
$ref: '../../schemas.yaml#/components/schemas/BLOCK_HASH'
- name: options
schema:
$ref: '../../schemas.yaml#/components/schemas/TraceOptions'
result:
name: trace
schema:
type: array
items:
$ref: '../../schemas.yaml#/components/schemas/BlockTrace'
- name: debug_traceBlockByNumber
summary: The traceBlockByNumber method returns the full trace of a block.
params:
- name: blockNumber
schema:
$ref: '../../schemas.yaml#/components/schemas/BLOCK_NUMBER'
- name: options
schema:
$ref: '../../schemas.yaml#/components/schemas/TraceOptions'
result:
name: trace
schema:
type: array
items:
$ref: '../../schemas.yaml#/components/schemas/BlockTrace'
- name: debug_traceTransaction
summary: The traceTransaction method returns the full trace of a transaction.
params:
- name: txHash
schema:
$ref: '../../schemas.yaml#/components/schemas/TX_HASH'
- name: options
schema:
$ref: '../../schemas.yaml#/components/schemas/TraceOptions'
result:
name: trace
schema:
$ref: '../../schemas.yaml#/components/schemas/TransactionTrace'
23 changes: 23 additions & 0 deletions gen/internal/openrpc/data/trace_schemas.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
components:
schemas:
TraceOptions:
type: object
properties:
disableStorage:
type: boolean
description: 'Setting this to true will disable storage capture (default: false).'
disableStack:
type: boolean
description: 'Setting this to true will disable stack capture (default: false).'
enableMemory:
type: boolean
description: 'Setting this to true will enable memory capture (default: false).'
enableReturnData:
type: boolean
description: 'Setting this to true will enable return data capture (default: false).'
tracer:
type: string
description: 'The name of the tracer to use (e.g. "callTracer").'
timeout:
type: string
description: 'The timeout for the tracer (e.g. "5s").'
81 changes: 81 additions & 0 deletions gen/internal/scraper/scraper.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"context"
"log/slog"
"os"
"path/filepath"

"github.com/google/go-github/v74/github"

Expand Down Expand Up @@ -46,10 +47,90 @@ func (s *Scraper) Run(ctx context.Context) ([]openrpc.Method, error) {
return nil, err
}

localMethodSrc, err := s.LocalSource(ctx, "_schemas.yaml")
if err != nil {
return nil, err
}
s.log.InfoContext(ctx, "Local method files retrieved", "methods", len(localMethodSrc))
methodSrc = append(methodSrc, localMethodSrc...)

schemaSrc, err := s.SchemaSource(ctx)
if err != nil {
return nil, err
}

localSchemaSrc, err := s.LocalSource(ctx, "trace.yaml")
if err != nil {
return nil, err
}
s.log.InfoContext(ctx, "Local schema files retrieved", "schemas", len(localSchemaSrc))
schemaSrc = append(schemaSrc, localSchemaSrc...)

return s.MergeMethodsAndDefinitions(ctx, methodSrc, schemaSrc)
}

// LocalSource returns the OpenRPC source for all methods defined by the
// local OpenRPC specifications.
func (s *Scraper) LocalSource(ctx context.Context, filter string) ([]string, error) {
root, err := s.findProjectRoot()
if err != nil {
return nil, err
}

dir := filepath.Join(root, "gen", "internal", "openrpc", "data")
files, err := os.ReadDir(dir)
if err != nil {
return nil, err
}

var sources []string
for _, file := range files {
if file.IsDir() {
continue
}

if filepath.Ext(file.Name()) != ".yaml" {
continue
}

if filter == "trace.yaml" && file.Name() == "trace.yaml" {
continue
}

if filter == "_schemas.yaml" && file.Name() != "trace.yaml" {
continue
}

path := filepath.Join(dir, file.Name())
path = filepath.Clean(path)
s.log.DebugContext(ctx, "Reading local method file", "path", path)

data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
s.log.DebugContext(ctx, "Read local method file", "path", path)
sources = append(sources, string(data))
}

return sources, nil
}

func (s *Scraper) findProjectRoot() (string, error) {
dir, err := os.Getwd()
if err != nil {
return "", err
}

for {
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
return dir, nil
}

if dir == filepath.Dir(dir) {
return "", os.ErrNotExist
}

dir = filepath.Dir(dir)
}
}
28 changes: 17 additions & 11 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
module github.com/selesy/ethereum-mcp

go 1.24.4
go 1.24

toolchain go1.25.4

tool (
github.com/selesy/ethereum-mcp/gen
golang.org/x/vuln/cmd/govulncheck
)

require github.com/mark3labs/mcp-go v0.39.0
require (
github.com/dave/jennifer v1.7.1
github.com/google/go-github/v74 v74.0.0
github.com/invopop/yaml v0.3.1
github.com/lmittmann/tint v1.1.2
github.com/mark3labs/mcp-go v0.39.0
github.com/selesy/jsonschema v0.14.0-rc1
github.com/stretchr/testify v1.11.0
github.com/wk8/go-ordered-map/v2 v2.1.8
gotest.tools/v3 v3.5.2
)

require (
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/dave/jennifer v1.7.1 // indirect
github.com/google/go-github/v74 v74.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/invopop/jsonschema v0.13.0 // indirect
github.com/invopop/yaml v0.3.1 // indirect
github.com/lmittmann/tint v1.1.2 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/selesy/ethereum-mcp/gen v0.4.0 // indirect
github.com/selesy/jsonschema v0.14.0-rc1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/sync v0.10.0 // indirect
Expand All @@ -32,5 +40,3 @@ require (
golang.org/x/vuln v1.1.4 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace github.com/selesy/ethereum-mcp/gen => ./gen
2 changes: 1 addition & 1 deletion pkg/doc.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
////go:generate go tool gen
//go:generate go tool gen

package pkg
22 changes: 22 additions & 0 deletions pkg/proxy/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package proxy

// ParamsSpec contains the "specification" needed to service each JSON-RPC
// method.
type ParamsSpec struct {
order []string
required map[string]struct{}
}

// Order returns an ordered list of parameter names which can be used to
// convert a JSON-RPC "params" value from named parameters to positional
// parameters.
func (p *ParamsSpec) Order() []string {
return p.order
}

// Required returns a set of which parameters are required. For positional
// parameters, the parameters in this set should be those that are first
// in the list returned by Order.
func (p *ParamsSpec) Required() map[string]struct{} {
return p.required
}
Loading