Ethereum-Trading-MCP-Server

HONGJICAI/Ethereum-Trading-MCP-Server

3.1

If you are the rightful owner of Ethereum-Trading-MCP-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 henry@mcphub.com.

The Ethereum Trading MCP Server is a Rust-based server designed to facilitate AI agents in querying balances and executing token swaps on the Ethereum blockchain.

Ethereum Trading MCP Server

Overview

This is a Model Context Protocol (MCP) server in Rust that are able to query balances and execute token swaps on Ethereum.

Features

  • get_balance - Query ETH and ERC20 token balances with proper decimal handling
  • get_token_price - Get current token prices in USD or ETH using Uniswap V2
  • swap_tokens - Simulate token swaps on Uniswap V2 (returns estimates without executing)

Setup

Prerequisites

  • Rust 1.70+ (rustup recommended)
  • Python 3.11+ (if test mcp server automatically)
  • An Ethereum RPC endpoint (Infura, Alchemy, or public endpoint)
  • A private key for transaction signing (for simulation only)

Installation

  1. Clone the repository

  2. Copy the example environment file:

cp .env.example .env
  1. Edit .env with your configuration, or use below testing configuration:
# Using free public endpoint (may be slower than paid services)
ETH_RPC_URL=https://eth.llamarpc.com
PRIVATE_KEY=0000000000000000000000000000000000000000000000000000000000000001
CHAIN_ID=1

⚠️ Security Warning: Never commit your real private key! The .env file is gitignored for safety.

  1. Build the project:
cargo build --release
  1. Run the server:
cargo run --release

The server reads JSON-RPC requests from stdin and writes responses to stdout.

Testing

Unit Tests

Run the unit test suite:

cargo test

Integration Tests

Run integration tests (requires internet connection to query Ethereum mainnet):

cargo test --test integration_tests -- --ignored --nocapture

These tests verify real blockchain interactions including:

  • Querying actual ETH/token balances
  • Fetching real Uniswap prices
  • Simulating swaps on mainnet

Coverage Report

Generate a code coverage report:

cargo tarpaulin --out Html --output-dir coverage --exclude-files "target/*"

Client Examples

See the directory for client implementations that demonstrate how to use the MCP server:

  • Python MCP Client () - Full-featured example showing all available tools

To run the Python example:

cd examples
pip install -r ../requirements.txt
python python_mcp_client.py

See for more details.

Manual Test

You can either test on console app or web UI.

Console

Check below example MCP tppl calls, then copy & paste request to stdin and check the response from MCP server.

Web UI

Need to install node.js first.

npx @modelcontextprotocol/inspector cargo run --release

And then click connect, list tools, tool buttons to test.

Example MCP Tool Calls

You need to minify the json before paste to stdin.

Useful tool to minify: JSON Monifier

Initialize

Request:

{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"example-client","version":"1.0.0"}}}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "serverInfo": {
      "name": "Ethereum Trading MCP Server",
      "version": "0.1.0"
    },
    "capabilities": {
      "tools": {}
    }
  }
}

Initialized Notification

IMPORTANT: After receiving the initialize response, you MUST send this notification:

{"jsonrpc":"2.0","method":"notifications/initialized"}

This notification has no response. It signals that the client is ready to begin normal operations.

List Tools

Request:

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

Response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "get_balance",
        "description": "Query ETH or ERC20 token balance for a given wallet address",
        "inputSchema": {
          "type": "object",
          "properties": {
            "address": {
              "type": "string",
              "description": "The wallet address to query"
            },
            "token_address": {
              "type": "string",
              "description": "Optional ERC20 token contract address. If omitted, returns ETH balance"
            }
          },
          "required": ["address"]
        }
      }
    ]
  }
}

Call get_balance

Etherscan url

Request:

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

Response:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\n  \"address\": \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\n  \"balance\": \"3.7\",\n  \"symbol\": \"ETH\",\n  \"decimals\": 18\n}"
      }
    ]
  }
}

Call get_token_price

Get the price of UNI token in USD.

Request:

{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"get_token_price","arguments":{"token_address":"0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984","quote_currency":"USD"}}}

Response:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\n  \"token_address\": \"0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984\",\n  \"price\": \"8.50\",\n  \"quote_currency\": \"USD\"\n}"
      }
    ]
  }
}

Get the price of UNI token in ETH.

Request:

{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"get_token_price","arguments":{"token_address":"0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984","quote_currency":"ETH"}}}

Response:

{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\n  \"token_address\": \"0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984\",\n  \"price\": \"0.00243\",\n  \"quote_currency\": \"ETH\"\n}"
      }
    ]
  }
}

Call swap_tokens (Simulation)

Request:

{"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"swap_tokens","arguments":{"from_token":"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2","to_token":"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48","amount":"1.0","slippage_tolerance":0.5}}}

Response:

{
  "jsonrpc": "2.0",
  "id": 6,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\n  \"from_token\": \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\",\n  \"to_token\": \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n  \"amount_in\": \"1.0\",\n  \"estimated_amount_out\": \"3500.0\",\n  \"minimum_amount_out\": \"3482.5\",\n  \"gas_estimate\": \"150000\",\n  \"gas_price_gwei\": \"30\",\n  \"estimated_gas_cost_eth\": \"0.0045\"\n}"
      }
    ]
  }
}

Design Decisions

Architecture: The system is built with a modular architecture separating concerns into distinct modules: Ethereum client operations, MCP server protocol handling, and individual tool implementations. This makes the codebase maintainable and testable.

Ethereum Library: We use ethers-rs for Ethereum interactions due to its mature ecosystem, strong type safety, and comprehensive ABI encoding/decoding capabilities. The library provides excellent support for contract interactions and RPC operations.

Uniswap Integration: The implementation uses Uniswap V2 Router for price queries and swap simulations. Swaps are simulated using getAmountsOut for price estimation and gas estimation without executing transactions on-chain. This provides safe, read-only operations.

Financial Precision: All financial calculations use rust_decimal to avoid floating-point precision issues. Token amounts are properly converted between human-readable decimals and blockchain wei/token units.

MCP Protocol: The server implements the JSON-RPC 2.0 specification manually for the MCP protocol, communicating via stdin/stdout. This provides maximum compatibility with MCP clients and tools.

Known Limitations & Assumptions

  1. Decimals Assumption: The swap simulation assumes 18 decimals for input amounts. Production code should query each token's decimals() function.

  2. Uniswap V2 Only: Currently only supports Uniswap V2. V3 has different mechanics (concentrated liquidity) that would require separate implementation.

  3. Mainnet Focus: Configuration is optimized for Ethereum mainnet. Other networks (L2s, testnets) would need different contract addresses.

  4. No Transaction Execution: The swap_tokens tool only simulates swaps and estimates gas. It does not execute real transactions, providing safety for exploratory use.

  5. Price Oracle: Token prices use Uniswap V2 liquidity pools. For low-liquidity tokens, prices may not be accurate. Production systems should aggregate multiple price sources.

  6. Error Handling: While comprehensive, some edge cases (network failures, invalid tokens) may not have perfect user-facing error messages.

  7. Rate Limiting: No built-in rate limiting for RPC calls. Heavy usage may hit provider limits.