mcp-eth-server

0xByteLeon/mcp-eth-server

3.2

If you are the rightful owner of mcp-eth-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.

MCP (Model Context Protocol) server for Ethereum built with Rust and `rmcp` SDK, offering tools for querying balances, token prices, and simulating token swaps.

Tools
3
Resources
0
Prompts
0

mcp-eth-server

MCP (Model Context Protocol) server for Ethereum built with Rust and rmcp SDK (Streamable-http).

Features

Tools

  • get_balance – Query ETH/ERC20 token balances for any address
  • get_token_price – Get on-chain token prices via Uniswap V3 QuoterV2 (using quoteExactInputSingle for accurate single-pool quotes, base USDC or ETH)
  • swap_tokens – Simulate token swaps on Uniswap V3 (constructs real transactions and uses eth_call - no on-chain execution)

Architecture

  • McpServer - Main server wrapper supporting multiple transports
  • EthServer - Tool router implementation with #[tool_router] macro
  • Built with official rmcp Rust SDK
  • Type-safe parameter extraction with JSON Schema generation
  • Supports stdio and HTTP transports
  • Async/await with Tokio runtime
  • Structured logging with tracing

Quick Start

Prerequisites

  • Rust 1.90.0 or later
  • Ethereum RPC endpoint (Infura, Alchemy, or local node)
  • Private key for transaction simulation

Setup

# Set Rust version
rustup override set 1.90.0

# Copy example config
cp config.example.yaml config.yaml

# Edit config.yaml with your settings

Get Sepolia ETH from faucets:

Build and Run

# Build
cargo build

# Run with default config (config.yaml)
cargo run

# Run with specific config
cargo run config.testnet.yaml
cargo run /path/to/custom-config.yaml

# Run tests
cargo test

Usage with Cursor

Add to your Cursor configuration:

{
  "mcpServers": {
    "eth-mcp-server": {
      "url": "http://localhost:8080/mcp"
    }
  }
}

Usage with MCP Inspector

# Install MCP Inspector
npx @modelcontextprotocol/inspector

# Run server
cargo run

# Connect Inspector to Streamable HTTP transport

Tool Examples

Example 1: Get Balance

MCP Request:

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

MCP Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Balance: 1234.567890123456 ETH"
      }
    ]
  }
}

With Token Address (USDC):

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

Example 2: Get Token Price

MCP Request:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "get_token_price",
    "arguments": {
      "token": "WETH",
      "base": "USD"
    }
  }
}

MCP Response:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "WETH Price: $2,450.00 USD\nSource: Uniswap V3 QuoterV2 (WETH/USDC pool)\nMethod: quoteExactInputSingle"
      }
    ]
  }
}

Example 3: Swap Tokens (Simulation)

MCP Request:

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "swap_tokens",
    "arguments": {
      "from_token": "WETH",
      "to_token": "USDC",
      "amount_in": "1.0",
      "slippage_bps": 50
    }
  }
}

MCP Response:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Swap Simulation (Uniswap V3)\n\nInput: 1.0 WETH\nExpected Output: 2,438.25 USDC\nMinimum Output: 2,426.05 USDC (0.5% slippage)\n\nFee Tier: 0.05% (500)\nPrice Impact: ~0.02%\n\nGas Estimate: 150,000 units\nEstimated Gas Cost: 0.0045 ETH (~$11.00)\n\n⚠️ SIMULATION ONLY - Transaction not executed\n✓ Token approval may be required"
      }
    ]
  }
}

Testing

# Run all tests,Before running 

cp config.example.yaml config.testnet.yaml # update to your private key, and ensuer your wallet have eth on sepolia network

cargo test

Design Decisions

Architectural Approach

  1. MCP Protocol Compliance: Built with official rmcp Rust SDK ensuring full compatibility with MCP specification and Claude Desktop integration

  2. Layered Architecture:

    • McpServer: Transport layer (HTTP) management
    • EthServer: Tool routing with #[tool_router] macro
    • Business logic: Pure functions for balance, price, and swap operations
    • Enables independent testing and easy addition of new tools/transports
  3. Type Safety & Automation:

    • #[tool_router] macro auto-generates tool registration and routing
    • JSON Schema derived from Rust types via schemars
    • Compile-time parameter validation with Parameters<T>
    • Zero boilerplate for new tool additions
  4. Simulation-First Safety:

    • All swap operations use eth_call for simulation
    • Constructs real Uniswap V3 transactions but never broadcasts
    • Provides accurate gas estimates without on-chain execution
    • Safe for production use with real private keys
  5. Financial Precision:

    • Uses rust_decimal for all token calculations
    • Handles token decimals correctly (6 for USDC, 18 for ETH)
    • Prevents floating-point errors in financial operations

Known Limitations

Current Scope

  • Network: Primarily Ethereum mainnet focused (configurable via CHAIN_ID, also supports Sepolia testnet)
  • DEX: Uniswap V3 only, single-hop swaps (multi-hop support planned)
  • Token Resolution: Built-in symbols for WETH, USDC, USDT, DAI; other tokens require full contract address
  • Price Oracles: Uses Uniswap V3 QuoterV2 with quoteExactInputSingle for accurate on-chain prices via USDC pools

Assumptions

  • RPC endpoint is reliable and returns accurate data
  • Private key is only used for transaction simulation (never broadcasts)
  • Sufficient RPC rate limits for production usage
  • Token contracts follow standard ERC20 interface

Project Structure

src/
├── main.rs              # Entry point - creates McpServer
├── mcp.rs               # McpServer - handles stdio/HTTP transports
├── lib.rs               # Module definitions
├── config.rs            # Configuration management
├── types.rs             # Input/Output types with JsonSchema
├── tools/
│   ├── router.rs        # EthServer with #[tool_router]
│   ├── balance.rs       # Balance query implementation
│   ├── price.rs         # Price query via Uniswap V3 QuoterV2
│   └── swap.rs          # Swap simulation implementation
├── uniswap/             # Uniswap V2/V3 integrations

Architecture Flow

main.rs
  └─> McpServer::new(config)
       └─> EthServer::new(config)  [has #[tool_router]]
            ├─> get_balance (tool)
            ├─> get_token_price (tool)
            └─> swap_tokens (tool)
       └─> run_http()
            └─> Uses rmcp transports