使用说明
以太坊交易MCP服务器
一个用Rust实现的模型上下文协议(MCP)服务器,使AI代理能够与以太坊区块链进行交互,执行余额查询、价格查询以及代币交换模拟。
特点/功能
get_balance- 查询任意钱包地址的以太坊(ETH)和ERC20代币余额get_token_price- 从CoinGecko获取实时代币价格(以美元或以太坊计)swap_tokens- 模拟Uniswap V2代币交换并估算燃气费用(不实际执行)
先决条件
- Rust 1.70+(从[来源]安装 rustup.rs(可直接作为项目名或域名等,无需翻译))
- 一个以太坊RPC端点(Infura、Alchemy或公共节点)
设置
1. 克隆仓库
git clone <your-repo-url>
cd ethereum-mcp-server
2. 配置环境变量
复制示例环境文件:
# Linux/Mac
cp env.example .env
# Windows PowerShell
Copy-Item env.example .env
编辑 .env 并配置您的RPC端点和私钥:
RPC 端点(必需):
选项A:使用Infura(推荐)
ETH_RPC_URL=https://mainnet.infura.io/v3/YOUR_API_KEY
获取免费API密钥,请访问 infura.io(通常不直接翻译,保持原样,若需说明可译为“Infura网站”或“Infura.io平台”)
选项B:使用炼金术
ETH_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY
在原文内容处填写:在获取免费API密钥 alchemy.com 翻译成中文可以是“炼金术.com”或者根据语境简化为“炼金.com”,但通常网址翻译时会保留原样,因为网址本身是一个专有名词,直接用于网络地址标识。不过,如果非要给出一个中文解释性的翻译,上述翻译是可行的。在实际应用中,网址一般还是直接使用原英文形式
选项C:使用公共RPC
ETH_RPC_URL=https://eth.llamarpc.com
无需API密钥,但可能会有限速。
私钥(交换模拟必需):
⚠️(警告符号,无具体文字含义,仅表示警告或注意) 重要仅使用测试钱包!切勿使用装有真实资金的钱包!
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
其中的私钥 env.example 这是Hardhat中的一个知名测试密钥。它在开发环境中是安全的,但没有任何资金。如果由于余额不足导致交换模拟失败,这是预期行为——模拟仍然展示了交易签名和验证的流程。
3. 构建项目
cargo build --release
4. 运行测试
cargo test
运行服务器
启动MCP服务器:
cargo run --release
服务器监听在 标准输入/标准输出 遵循MCP协议规范。
使用示例
MCP协议通信
服务器使用JSON-RPC 2.0格式。所有请求/响应均通过标准输入/标准输出进行交换。
1. 初始化服务器
请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
}
}
回应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {}
},
"serverInfo": {
"name": "ethereum-mcp-server",
"version": "0.1.0"
}
}
}
2. 列出可用工具
请求:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}
回应:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "get_balance",
"description": "Query ETH and ERC20 token balances for a wallet address",
"inputSchema": { ... }
},
{
"name": "get_token_price",
"description": "Get current token price in USD or ETH",
"inputSchema": { ... }
},
{
"name": "swap_tokens",
"description": "Simulate a token swap on Uniswap V2",
"inputSchema": { ... }
}
]
}
}
3. 获取以太坊余额
请求:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "get_balance",
"arguments": {
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}
}
}
回应:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "{\"address\":\"0x742d35cc6634c0532925a3b844bc9e7595f0beb\",\"balance\":\"1234567890123456789\",\"decimals\":18,\"symbol\":\"ETH\",\"formatted_balance\":\"1.234567890123456789\"}"
}
]
}
}
4. 获取ERC20代币余额
请求:
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "get_balance",
"arguments": {
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"token_address": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
}
}
}
5. 获取代币价格
请求:
{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "get_token_price",
"arguments": {
"token": "USDT",
"currency": "usd"
}
}
}
回答:
{
"jsonrpc": "2.0",
"id": 5,
"result": {
"content": [
{
"type": "text",
"text": "{\"token\":\"USDT\",\"price\":1.0,\"currency\":\"usd\",\"source\":\"CoinGecko\"}"
}
]
}
}
6. 模拟代币交换
请求:
{
"jsonrpc": "2.0",
"id": 6,
"method": "tools/call",
"params": {
"name": "swap_tokens",
"arguments": {
"from_token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"to_token": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"amount": "1000000000000000000",
"slippage": 0.5
}
}
}
回答:
{
"jsonrpc": "2.0",
"id": 6,
"result": {
"content": [
{
"type": "text",
"text": "{\"from_token\":\"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\",\"to_token\":\"0xdac17f958d2ee523a2206206994597c13d831ec7\",\"amount_in\":\"1000000000000000000\",\"estimated_amount_out\":\"3456789012\",\"minimum_amount_out\":\"3439505127\",\"slippage\":0.5,\"price_impact\":\"< 1%\",\"gas_estimate\":\"150000\",\"path\":[\"0xc02...\",\"0xdac...\"]}"
}
]
}
}
设计决策
-
MCP协议实现手动实现了JSON-RPC 2.0,以便对协议流程拥有完全控制权。这使得错误处理和日志记录比使用更高层次的SDK更为完善。服务器遵循MCP规范,通过stdin/stdout进行通信。
-
异步架构使用Tokio作为异步运行时,以高效处理并发区块链查询。以太坊RPC调用可能会很慢,而async/await机制可避免阻塞。所有区块链交互均为非阻塞的。
-
用于交换模拟的真实交易签名这个
swap_tokens工具构建 真实的、已签名的Uniswap交易 使用环境中的私钥,然后通过(某种方式)模拟它们eth_call或者estimate_gas这种方法:- 创建包含所有必要参数(发件人地址、随机数、燃气费等)的真实交易对象
- 使用钱包的私钥签署交易
SignerMiddleware - 在不广播的情况下模拟区块链上的执行
- 提供准确的气体消耗估计,并验证交易将成功执行
- 这满足了“构建一个真实的Uniswap交易并将其提交到区块链上进行模拟”的要求
-
钱包管理私钥从(某个地方)加载
PRIVATE_KEY环境变量。系统使用 ethers-rs 的LocalWallet和SignerMiddleware收件人:- 解析并验证私钥
- 派生钱包地址
- 使用正确的链ID签署交易(主网 = 1)
- 如果未配置私钥,则存在一种备用估计方法,但更推荐使用签名模拟
-
Uniswap V2 用于交换选择Uniswap V2而非V3,因为其更简洁可靠。V2具有以下特点:
- 直接的路由机制(直接交换或通过WETH交换)
- 更广泛的货币对可用性和流动性
- 更简洁的ABI(应用程序二进制接口)和更可预测的行为
- 交换路径会自动使用WETH作为代币间交换的中介
-
金融精确度所有代币数量在API中均作为字符串处理,以防止浮点精度错误。在内部,我们使用
U256来自ethers-rs,用于实现精确的任意精度计算。滑点计算保持精度,仅在最终转换时使用浮点数。 -
价格数据来源CoinGecko API为大多数代币提供免费、可靠的价格数据,无需API密钥。为方便起见,代币符号和地址已映射到CoinGecko ID。
已知的限制与假设
-
测试网支持当前配置为以太坊主网。如需使用测试网,请更改RPC URL以及(其他相关设置,此处原文未完整,假设需更改的是与RPC URL相关的配置项)
.env并更新链IDethereum.rs(第25行)。 -
仅限Uniswap V2交换模拟仅支持Uniswap V2。V3具有集中流动性功能和多跳路由,这需要更复杂的计算和不同的应用二进制接口(ABIs)。
-
有限的代币配对某些异域代币对在Uniswap V2上可能没有流动性。如果不存在相应的代币对,交换操作将失败并显示错误信息。常见代币对(WETH、USDT、USDC、DAI)得到了良好的支持。
-
气体估算准确性“Gas estimates(燃气估算)是基于当前区块链状态的近似值。实际燃气使用量可能会因以下情况而有所不同:”
- 在模拟和执行之间,网络条件会发生变化
- 代币合约具有动态行为(例如,费用会变化)
- 钱包中ERC20代币的余额不足以进行授权
-
价格影响价格影响计算已简化(显示“< 1%”占位符)。如需准确计算影响,您需要:
- 查询兑换前后的池子储备量
- 计算有效价格与池子的现货价格之差
- 考虑通过WETH进行多跳交换
-
无交易执行该
swap_tokens该工具构建并签署真实的交易,但仅限于 模拟 它们。交易永远不会广播到区块链上。要实际执行:- 已签名的交易需要通过
eth_sendRawTransaction - 需要钱包中有足够的以太币(ETH)作为手续费以及用于兑换的代币
- 对于多笔交易,需要适当的随机数(nonce)管理
- 已签名的交易需要通过
-
私钥安全测试私钥在
env.example是公开已知的,并且应该 永远 使用真实资金。在生产中:- 使用硬件钱包或安全密钥管理系统
- 永远不要将私钥提交到版本控制系统中
- 使用
.gitignore排除.env文件
-
速率限制公共RPC端点(如LlamaRPC)和CoinGecko的免费API都有速率限制。对于生产环境使用:
- 使用限额更高的付费RPC提供商(Infura、Alchemy)
- 实现请求缓存和速率限制
- 考虑运行你自己的以太坊节点
-
错误处理一些边缘情况(网络故障、无效地址、流动性不足)会返回基本错误信息。生产代码需要:
- 更细粒度的错误类型和代码
- 针对瞬时网络故障的重试逻辑
- 提供更好的面向用户的错误信息,并附上修复建议
项目结构
ethereum-mcp-server/
├── src/
│ ├── main.rs # Entry point
│ ├── config.rs # Configuration from environment
│ ├── mcp.rs # MCP protocol server implementation
│ ├── ethereum.rs # Ethereum provider and contract ABIs
│ └── tools/ # MCP tool implementations
│ ├── mod.rs
│ ├── get_balance.rs
│ ├── get_token_price.rs
│ └── swap_tokens.rs
├── tests/
│ └── integration_test.rs
├── examples/
│ └── test_requests.json
├── Cargo.toml
├── env.example
├── SETUP_GUIDE.md # Detailed Chinese setup guide
├── ARCHITECTURE.md # Technical architecture documentation
└── README.md
测试
运行测试套件:
# Run all tests
cargo test
# Run tests with output
cargo test -- --nocapture
# Run specific test
cargo test test_json_rpc_request_parsing
测试内容包括:
- JSON-RPC 请求/响应解析
- 地址和金额验证
- 示例MCP协议交互
常见代币地址(以太坊主网)
- WETH(Wrapped Ethereum,以太坊封装币):
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 - USDT(泰达币):
0xdAC17F958D2ee523a2206206994597C13D831ec7 - USDC(美元稳定币):
0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 - DAI(戴伊/大额可转让存单/去中心化自治组织等,具体含义需根据上下文确定):
0x6B175474E89094C44Da98b954EedeAC495271d0F
故障排除
Windows:“链接器 link.exe 在构建过程中出现“not found”
- 您需要带有C++支持的Visual Studio构建工具
- 下载地址:https://visualstudio.microsoft.com/downloads/
- 安装“使用 C++ 进行桌面开发”
- 安装完成后重启您的电脑
- 重新打开 PowerShell 并尝试
cargo build再次
“无法创建以太坊提供者”
- 检查一下你的
ETH_RPC_URL在.env是正确的 - 检查您的网络连接
- 尝试使用不同的RPC端点
- 确保使用Infura/Alchemy时API密钥有效
“私钥格式无效”
- 确保私钥以以下内容开头
0x - 总长度应为66个字符(0x + 64个十六进制字符)
- 永远不要使用真实钱包的私钥——请使用来自(此处应补充来源,但原文未给出具体来源)的测试密钥
env.example
“无法估算交换所需的气体(费用)”
- 该钱包可能缺少足够的代币余额(测试钱包预期如此)
- 该代币对可能在Uniswap V2上不存在
- 尝试使用像WETH/USDT这样的知名币对
- 检查代币地址是否有效
“请求速率超过限制”
- 如果使用公共RPC,请切换到Infura/Alchemy
- 在请求之间添加延迟
- 减少并发请求数量
“兑换时配对不存在”
- 该代币对在Uniswap V2上可能没有流动性
- 验证代币地址是否正确(应使用校验和)
- 尝试使用不同的代币对(见下文常见代币地址)
发展
要启用调试日志记录:
# Unix/Linux/Mac
RUST_LOG=debug cargo run
# Windows PowerShell
$env:RUST_LOG="debug"; cargo run
# Windows CMD
set RUST_LOG=debug && cargo run
格式化代码:
cargo fmt
运行代码检查工具:
cargo clippy
附加文件
- QUICK_START_CN.md 翻译为中文是:“快速入门指南(中文版).md” - 🇨🇳 快速入门指南(中文版)- Quick start guide in Chinese
- 示例/测试请求.json - 用于测试的示例MCP请求
- `env.example` 翻译成中文是:“环境配置示例” 或 “环境变量示例文件” - 环境配置模板
许可证
麻省理工学院(MIT)
联系
关于此实现的任何问题,请参阅代码注释或提交一个问题。
