以太坊区块链查询服务器

一个基于Rust实现的以太坊区块链操作服务器,支持查询余额、获取代币价格和模拟代币交换功能,适用于AI代理和区块链开发者。

  • by Dannieeth
  • Rust
  • 本地部署
  • 更新于
在 GitHub 查看 Dannieeth/ethereum-mcp-server

使用说明

以太坊MCP服务器

一个用于以太坊区块链操作的Rust语言实现的模型上下文协议(MCP)服务器。该服务器使AI代理能够查询余额、从Chainlink预言机获取代币价格,并在Uniswap V2上模拟代币交换。

支持stdio(MCP标准)和HTTP(REST API)两种模式,实现灵活集成。

特点/功能

MCP 工具

  1. get_balance - 查询以太坊(ETH)和ERC20代币余额

    • 支持原生ETH和任何ERC20代币
    • 返回格式化后的余额,包含正确的小数位数
    • 并发获取代币元数据
  2. get_token_price - 从Chainlink价格数据源获取当前代币价格

    • 从Chainlink预言机获取实时美元价格
    • 计算以太币(ETH)计价的价格
    • 包括数据陈旧性检查
    • 使用moka进行缓存 (默认60秒时间限制)
  3. swap_tokens - 在Uniswap V2上模拟代币交换

    • 构建真实的Uniswap V2交易
    • 模拟使用(某工具/方法)执行 eth_call (无链上执行)
    • 计算价格影响并提供滑点保护
    • 估算燃气费用

建筑学

技术栈

  • Rust(锈) 使用 async/await(Tokio 运行时)
  • ethers-rs(可译为“Ethers-RS”,在中文语境下,通常直接使用英文原名,因其为特定技术或库的名称,不直接翻译) - 以太坊RPC客户端和合约绑定
  • 阿克苏姆(Axum)+ 塔 - HTTP服务器框架(用于HTTP模式)
  • 摩卡 - 内存异步缓存(可替换为Redis以实现分布式部署)
  • 追踪 - 结构化日志记录
  • serde(在中文语境下,可直接保留原名或根据上下文意译为“序列化/反序列化库”,但通常直接使用原名) - 序列化/反序列化
  • rust_decimal(在中文中可直接保留原名,因其是一个特定的库名或项目名,不直接翻译) - 精确的财务计算
  • 鼓掌 - 命令行参数解析

目录结构

ethereum-mcp-server/
├── src/
│   ├── main.rs              # Entry point, mode selection, tokio runtime
│   ├── lib.rs               # Library root
│   ├── config.rs            # Configuration management
│   ├── error.rs             # Unified error types
│   ├── mcp/                 # MCP protocol layer
│   │   ├── server.rs        # JSON-RPC 2.0 server (stdio mode)
│   │   ├── http_server.rs   # HTTP JSON-RPC server (HTTP mode)
│   │   ├── handler.rs       # Tool call routing
│   │   └── schema.rs        # Protocol schemas
│   ├── services/            # Business logic layer
│   │   ├── balance.rs       # Balance query service
│   │   ├── price.rs         # Price query service (Chainlink)
│   │   └── swap.rs          # Swap simulation service
│   ├── providers/           # External provider layer
│   │   ├── ethereum.rs      # Ethereum RPC client
│   │   ├── chainlink.rs     # Chainlink oracle with moka cache
│   │   └── uniswap.rs       # Uniswap V2 interaction
│   ├── contracts/           # Smart contract ABIs
│   │   ├── erc20.rs
│   │   ├── chainlink_feed.rs
│   │   └── uniswap_router.rs
│   └── utils/               # Utilities
│       ├── decimal.rs       # Precision handling
│       ├── validation.rs    # Input validation
│       └── wallet.rs        # Wallet management
└── tests/
    └── integration/         # Integration tests

设置

先决条件

  • Rust 1.70+(从 https://rustup.rs 安装)
  • 以太坊RPC端点(Infura、Alchemy或公共端点)

安装

  1. 克隆仓库:
git clone <repository-url>
cd ethereum-mcp-server
  1. 复制环境配置:
cp .env.example .env
  1. 编辑 .env 根据您的配置:
# Required
RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY
PRIVATE_KEY=0x0000000000000000000000000000000000000000000000000000000000000001

# Optional
LOG_LEVEL=info
PRICE_CACHE_TTL_SECS=60
CACHE_MAX_CAPACITY=1000

⚠️ 安全警告永远不要把自己的 .env 文件中包含真实的私钥!

  1. 构建项目:
cargo build --release

跑步

服务器支持两种模式:

1. stdio 模式(默认 - MCP 标准)

cargo run --release

服务器通过(某种方式)进行通信 标准输入/标准输出 使用JSON-RPC 2.0协议。

📝(记事本/笔记) 注当通过命令行发送请求时,JSON 必须位于(某处,此处根据上下文可能需要具体说明是“作为参数传递”或“在请求体中”等) 单行. 查看 JSON格式指南.md 和 QUICKSTART.md 翻译为中文是:“快速入门指南.md” 以实际例子说明。

2. HTTP模式(REST API)

# Start HTTP server on default port (3000)
cargo run --release -- --mode http

# Or specify custom host and port
cargo run --release -- --mode http --host 0.0.0.0 --port 8080

服务器提供HTTP JSON-RPC端点:

  • POST /rpc - 所有工具调用的JSON-RPC 2.0端点
  • GET /health - 健康检查端点

📡(天线/卫星天线) 见 根据上面的信息,执行如下指令: 如需详细的HTTP API文档、curl/Python/JavaScript示例以及部署指南,请参考以下内容:。

CLI 选项

OPTIONS:
  -m, --mode <MODE>    Server mode [default: stdio] [possible values: stdio, http]
      --host <HOST>    HTTP server host [default: 127.0.0.1]
  -p, --port <PORT>    HTTP server port [default: 3000]
  -h, --help           Print help
  -V, --version        Print version

使用示例

MCP工具调用示例

ⓘ 下面的JSON示例已格式化以便阅读。在实际命令行使用时,请将其压缩为单行格式(参见 QUICKSTART.md 翻译为中文是:“快速入门指南.md”(其中,“.md”通常表示该文件是Markdown格式的文档))。

1. 列出可用工具

请求:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}

回答:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "get_balance",
        "description": "Query ETH and ERC20 token balances...",
        "input_schema": { ... }
      },
      {
        "name": "get_token_price",
        "description": "Get current token price...",
        "input_schema": { ... }
      },
      {
        "name": "swap_tokens",
        "description": "Simulate a token swap...",
        "input_schema": { ... }
      }
    ]
  }
}

2. 查询以太坊余额

请求:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "get_balance",
    "arguments": {
      "wallet_address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
    }
  }
}

回应:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{
          \"wallet_address\": \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",
          \"token_symbol\": \"ETH\",
          \"token_name\": \"Ethereum\",
          \"decimals\": 18,
          \"balance\": \"1500000000000000000\",
          \"balance_formatted\": \"1.5 ETH\",
          \"balance_decimal\": \"1.5\"
        }"
      }
    ]
  }
}

3. 查询ERC20代币余额

请求:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "get_balance",
    "arguments": {
      "wallet_address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
      "token_address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
    }
  }
}

4. 获取代币价格

请求:

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "get_token_price",
    "arguments": {
      "token": "ETH"
    }
  }
}

回应:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{
          \"token\": \"ETH\",
          \"usd_price\": 2450.75,
          \"decimals\": 8,
          \"round_id\": 12345,
          \"updated_at\": \"2024-01-15T10:30:00Z\",
          \"is_stale\": false
        }"
      }
    ]
  }
}

5. 模拟代币交换

请求:

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "swap_tokens",
    "arguments": {
      "from_token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      "to_token": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
      "amount": "100",
      "slippage_tolerance": 0.5
    }
  }
}

回应:

{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{
          \"from_token\": \"0xA0b8...\",
          \"to_token\": \"0x6B17...\",
          \"from_symbol\": \"USDC\",
          \"to_symbol\": \"DAI\",
          \"amount_in\": \"100000000\",
          \"amount_in_formatted\": \"100 USDC\",
          \"amount_out\": \"99500000000000000000\",
          \"amount_out_formatted\": \"99.5 DAI\",
          \"min_amount_out\": \"99002500000000000000\",
          \"min_amount_out_formatted\": \"99.0025 DAI\",
          \"price_impact\": 0.12,
          \"slippage_tolerance\": 0.5,
          \"path\": [\"0xA0b8...\", \"0xC02a...\", \"0x6B17...\"],
          \"estimated_gas\": \"150000\",
          \"gas_price\": \"30000000000\",
          \"gas_cost\": \"4500000000000000\",
          \"gas_cost_eth\": \"0.0045\",
          \"simulation_successful\": true
        }"
      }
    ]
  }
}

设计决策

1. 使用Tokio的异步架构

  • 所有输入/输出操作(RPC调用、文件I/O)均为完全异步的
  • Tokio的多线程运行时高效处理并发请求
  • tokio::join! 并且 tokio::try_join! 启用并行RPC调用(例如,同时获取代币信息和余额)

2. Chainlink用于价格数据

  • 选择Chainlink预言机以获取去中心化、防篡改的价格数据
  • 为主要代币(ETH、BTC、USDC等)预配置的主网价格数据源地址
  • 支持基于符号的查询(“ETH”)和基于地址的查询

3. Moka Cache(可升级至Redis)

  • 用途 moka 用于内存中的异步缓存,支持可配置的TTL(默认60秒)
  • 价格数据被缓存以减少RPC调用并提高性能
  • 该架构支持轻松替换为 Redis 对于分布式部署:
    • 缓存层被抽象出来 ChainlinkProvider
    • 注释中包含的Redis实现模板
    • 只需交换即可 Cache<String, PriceData> 与;和;带着 redis::aio::ConnectionManager

4. 使用Uniswap V2进行交换模拟

  • 实现了Uniswap V2路由器的集成(比V3更简单)
  • 构建真实的掉期交易,但仅通过模拟进行 eth_call
  • 通过比较池储备与执行价格来计算价格影响
  • 可以添加V3支持作为扩展

5. 错误处理和验证

  • 使用全面的错误类型 thiserror
  • 对地址、金额和滑点进行输入验证
  • 将错误映射到相应的 JSON-RPC 错误代码

已知的限制和假设

  1. 网络支持目前仅配置为以太坊主网

    • Chainlink的价格数据源和Uniswap的地址是特定于主网的
    • 可以扩展以支持测试网或其他EVM(以太坊虚拟机)链
  2. Uniswap 版本仅实现V2版本

    • V3版本需要支持更复杂的时钟(tick)和流动性范围逻辑
    • V2版本足以满足价格发现和基本互换需求
  3. 私钥管理使用环境变量来指定私钥

    • 适用于开发和测试
    • 生产环境的部署应使用安全的密钥管理系统(HSM,KMS)
  4. RPC速率限制没有内置的速率限制

    • 公共RPC端点可能会限制请求速率
    • 建议在生产环境中使用付费提供商(Alchemy、Infura)
  5. 缓存分布Moka缓存是基于内存的(单实例)

    • 对于水平扩展,建议使用 Redis(已提供实现模板)
    • 缓存失效仅基于TTL(生存时间)(不支持基于事件的失效)
  6. 价格数据覆盖范围仅限于预配置的令牌

    • Feed 注册表支持是可选的(需要配置)
    • 没有 Chainlink 数据源的代币将返回“未找到”错误
  7. 交易模拟用途 eth_call 用于交换模拟

    • 未考虑最大提取价值(MEV)或三明治攻击
    • 实际链上执行可能与模拟结果不同
  8. 气体估算仅进行基本气体估算

    • 未考虑网络拥塞情况
    • 不支持EIP-1559(使用传统燃气定价)

测试

运行单元测试

cargo test --lib

运行集成测试

cargo test --test '*'

使用特定RPC运行(集成测试)

RPC_URL=https://eth.llamarpc.com cargo test --test '*' -- --ignored

发展

启用调试日志记录

RUST_LOG=debug cargo run

格式代码

cargo fmt

Lint(在编程和软件开发中,通常指代码中的错误、警告或未使用的代码等,也可泛指杂质或不需要的元素)

cargo clippy -- -D warnings

未来改进方向

  • [ ] 支持分布式部署的Redis缓存
  • [ ] Uniswap V3 集成
  • [ ] 支持多链(Polygon、Arbitrum 等)
  • [ ] EIP-1559 气体费用估算
  • [ ] WebSocket RPC 支持
  • [ ] 历史价格数据查询
  • [ ] 投资组合追踪功能

许可证

MIT 许可证 - 详见 LICENSE 文件

做出贡献

欢迎贡献!请提出问题或提交拉取请求。