MCP铁砧工具
模型上下文协议(MCP)服务器为AI代理提供以太坊开发和测试工具。基于Anvil(Foundry的本地以太坊节点)和viem构建,用于强大的区块链交互。
概述
MCP Anvil Tools使AI代理能够:
- 阅读Solidity源代码和合约存储
- 在本地Anvil或测试网上模拟和执行交易
- 通过快照和模拟来操纵区块链状态
- 查询事件并解码字节码
- 在隔离环境中测试智能合约
非常适合人工智能驱动的智能合约审计、测试工作流程和区块链开发自动化。
主要特点
- 双重运输模式:通过无状态HTTP
/mcp用于CLI/桌面集成的端点或stdio - 阅读工具(4):源代码、存储、字节码和事件日志访问
- 执行工具(5):事务模拟、发送和状态操纵
- 追踪工具(2):具有多种跟踪器类型的事务和呼叫跟踪
- Anvil集成:自动Anvil流程管理,支持快照/还原
- 状态持久性:SQLite支持的部署和会话跟踪
- 类型安全:通过Zod验证完全支持TypeScript
快速开始
安装
# Clone the repository
git clone https://github.com/yourusername/mcp-anvil-tools.git
cd mcp-anvil-tools
# Install dependencies
npm install
# Build the project
npm run build配置
# Copy example environment file
cp .env.example .env
# Edit .env with your configuration
nano .env所需的环境变量:
AUDIT_MCP_PORT-服务器端口(默认值:3000)MAINNET_RPC_URL-用于主网交互的RPC端点ETHERSCAN_API_KEY-可选,用于源代码验证
运行服务器
HTTP/SSE模式 (对于web客户端、多代理系统):
npm start
# Server runs on http://localhost:3000stdio模式 (适用于Claude Desktop、CLI工具):
npm run start:stdio
# Communicates via stdin/stdout发展模式 (热重新加载):
npm run dev运输方式
HTTP模式
使用HTTP模式:
- 基于Web的AI客户端
- 多代理架构
- 无状态MCP连接
- RESTful API交互
终点:
GET /health-健康检查(未经验证)GET /metrics-部署和实例统计POST /mcp-MCP协议端点(StreamableHTTPServerTransport)
连接示例:
# Health check
curl http://localhost:3000/health
# Metrics
curl http://localhost:3000/metrics
# MCP protocol request
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "test-client",
"version": "1.0.0"
}
}
}'stdio模式
使用stdio:
- Claude桌面集成
- 命令行MCP客户端
- 程序化测试
- Shell脚本自动化
示例测试:
# Simple echo test
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}' | npm run start:stdio
# Automated test suite
npx tsx test-stdio.ts
# Manual test script
./test-stdio-manual.sh可用工具
阅读工具
1. read_source
从v4核心存储库中读取Solidity源代码文件。
输入:
path(string):相对路径lib/v4-core/src/(例如。,PoolManager.sol)
输出:
content(string):完整源代码lines(number):总行数path(string):绝对文件路径size(number):文件大小(字节)lastModified(字符串):ISO时间戳
例子:
{
"path": "PoolManager.sol"
}2. read_storage
读取合约存储槽(仅限持久存储,非临时存储)。
输入:
address(string):合约地址slot(string):存储槽(十六进制,例如。,0x0)blockTag(可选):latest,earliest,pending、块编号或块哈希rpc(可选):RPC URL(默认值:http://localhost:8545)
输出:
value(string):原始32字节十六进制值decoded(可选):尽力解释(uint256,address,bool,bytes32)
例子:
{
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"slot": "0x0",
"blockTag": "latest"
}3. read_bytecode
从合约地址检索已部署的字节码。
输入:
address(string):合约地址blockTag(可选):块标识符rpc(可选):RPC URL
输出:
bytecode(string):十六进制编码的字节码size(number):字节码大小(以字节为单位)codeHash(字符串):keccak 256哈希isEmpty(boolean):如果没有部署代码(EOA),则为True
例子:
{
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}4. read_events
查询和解码合同事件日志。
输入:
address(string):合约地址eventSignature(可选):事件签名(例如。,Transfer(address,address,uint256))topics(可选):索引主题过滤器fromBlock(可选):起始块(默认值:earliest)toBlock(可选):结束块(默认值:latest)rpc(可选):RPC URL
输出:
events(数组):包含块信息的事件日志count(number):返回的事件总数fromBlock(string):实际起始块toBlock(string):实际结束块
例子:
{
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"eventSignature": "Transfer(address,address,uint256)",
"fromBlock": 1000000,
"toBlock": 1000100
}执行工具
5. simulate_tx
模拟交易,而不将其发送到网络。
输入:
to(string):目标合约地址data(字符串):调用数据(十六进制)from(可选):发件人地址gasLimit(可选):气体限制value(可选):ETH值(十六进制)abi(可选):用于解码的合约ABIfunctionName(可选):解码函数名称blockNumber(可选):要模拟的块stateOverrides(可选):通过地址覆盖州rpc(可选):RPC端点
输出:
result(string):返回数据(十六进制)decoded(可选):解码返回值reverted(boolean):调用是否已恢复revertReason(可选):解码还原原因revertData(可选):原始还原数据
例子:
{
"to": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"data": "0x70a08231000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266",
"abi": [...],
"functionName": "balanceOf"
}6. send_tx
将实际交易发送到网络。
输入:
to(可选):目标地址(部署时省略)data(string):事务数据/字节码from(可选):发件人地址value(可选):ETH值(十六进制)gasLimit(可选):气体限制(自动估算)gasPrice(可选):传统天然气价格maxFeePerGas(可选):EIP-1559最高费用maxPriorityFeePerGas(可选):EIP-1559优先费nonce(可选):交易随机数privateKey(可选):用于签名的私钥confirmations(可选):等待确认(默认值:1)rpc(可选):RPC端点
输出:
txHash(string):交易哈希blockNumber(string):区块编号blockHash(string):块哈希gasUsed(string):消耗的气体effectiveGasPrice(string):实际天然气价格status(枚举):success或revertedlogs(数组):事件日志contractAddress(可选):已部署的合约地址from(string):发件人地址to(可选):收件人地址
例子:
{
"to": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"data": "0xa9059cbb...",
"value": "0x0",
"privateKey": "0x..."
}7. impersonate
模拟Anvil上的任何地址(仅用于测试)。
输入:
address(string):要模拟的地址stopImpersonating(可选):停止模拟(默认值:false)rpc(可选):RPC端点(必须是Anvil)
输出:
success(boolean):操作是否成功address(string):模拟地址active(boolean):当前模拟状态balance(可选):当前余额
例子:
{
"address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
}8. create_snapshot
创建Anvil状态快照以供以后还原。
输入:
name(可选):人类可读的快照名称description(可选):快照描述rpc(可选):RPC端点(必须是Anvil)
输出:
snapshotId(string):唯一快照标识符name(可选):快照名称blockNumber(数字):快照时的块blockHash(string):块哈希timestamp(数字):块时间戳created(number):创建的Unix时间戳
例子:
{
"name": "before-attack-simulation",
"description": "State before testing exploit scenario"
}9. revert_snapshot
将区块链状态恢复到以前的快照。
输入:
snapshotId(string):快照ID或名称rpc(可选):RPC端点(必须是Anvil)
输出:
success(boolean):还原是否成功snapshotId(string):还原快照IDblockNumber(数字):还原后阻止blockHash(string):还原后的块哈希timestamp(数字):块时间戳reverted(boolean):状态恢复确认
例子:
{
"snapshotId": "before-attack-simulation"
}跟踪工具
10. trace_transaction
使用debug_traceTransaction通过哈希跟踪现有事务。
输入:
txHash(字符串):要跟踪的事务哈希(64个十六进制字符)tracer(可选):示踪剂类型-callTracer,prestateTracer,4byteTracer,或省略原始操作码跟踪tracerConfig(可选):特定于跟踪器的配置对象
- 对于 callTracer: { onlyTopCall: true } 排除子呼叫
rpc(可选):RPC URL(默认值:http://localhost:8545)
输出:
result:跟踪结果(格式取决于跟踪程序类型)
- callTracer:调用树 type, from, to, value, gas, input, output - prestateTracer:所有被触及账户的执行前状态 - 4比特赛车:函数选择器到调用计数的映射 - 无示踪剂:完整的操作码跟踪 structLogs 数组
txHash(string):跟踪的交易哈希
例子:
{
"txHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"tracer": "callTracer",
"tracerConfig": {
"onlyTopCall": true
}
}使用案例:
- 调试失败的事务
- 分析天然气使用模式
- 了解合同互动
- 检测可重入性或复杂的呼叫路径
11. trace_call
使用debug_traceCall跟踪调用而不发送事务。
输入:
to(string):目标合约地址data(字符串):调用数据(十六进制编码)from(可选):发件人地址value(可选):ETH值(十六进制)blockTag(可选):要跟踪的块-latest,earliest,pending,safe,finalized,或块编号tracer(可选):示踪剂类型(与trace_transaction)tracerConfig(可选):跟踪器配置rpc(可选):RPC URL
输出:
result:跟踪结果(格式取决于跟踪程序类型,与trace_transaction)
例子:
{
"to": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"data": "0xa9059cbb000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000de0b6b3a7640000",
"from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"tracer": "callTracer"
}使用案例:
- 在发送实际事务之前进行调试
- 分析特定区块的呼叫行为
- 测试状态覆盖场景
- 安全调查潜在漏洞
Claude桌面集成
添加到您的Claude Desktop配置(~/Library/Application Support/Claude/claude_desktop_config.json 在macOS上):
{
"mcpServers": {
"anvil-tools": {
"command": "node",
"args": [
"/absolute/path/to/mcp-anvil-tools/dist/index.js",
"--stdio"
],
"env": {
"AUDIT_MCP_PORT": "3000",
"MAINNET_RPC_URL": "https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY",
"ETHERSCAN_API_KEY": "your_etherscan_api_key"
}
}
}
}重要:使用绝对路径 command args。配置更改后重新启动Claude Desktop。
配置
Alchemy多网络支持
集 ALCHEMY_API_KEY 无需额外配置即可访问任何Alchemy支持的网络:
ALCHEMY_API_KEY=your_alchemy_api_key使用任何 炼金网蛞蝓 直接:
| 网络 | Slug |
|---|---|
| 以太坊 | eth-mainnet, eth-sepolia |
| 仲裁 | arb-mainnet, arb-sepolia |
| 乐观主义 | opt-mainnet, opt-sepolia |
| 多边形 | polygon-mainnet, polygon-amoy |
| 基地 | base-mainnet, base-sepolia |
Alchemy添加新网络时会自动支持它们,无需更改代码。
环境变量
| 变量 | 描述 | 默认值 |
|---|---|---|
AUDIT_MCP_PORT | HTTP服务器端口 | 3000 |
AUDIT_MCP_HOST | HTTP服务器主机 | 0.0.0.0 |
AUDIT_MCP_DB_PATH | SQLite数据库路径 | ./audit-mcp.db |
ANVIL_PORT_START | Anvil端口范围开始 | 8545 |
ANVIL_PORT_END | Anvil端口范围结束 | 8555 |
ANVIL_DEFAULT_CHAIN_ID | 默认链ID | 31337 |
ALCHEMY_API_KEY | Alchemy API密钥(启用多网络) | - |
MAINNET_RPC_URL | 主网RPC(覆盖炼金术) | - |
SEPOLIA_RPC_URL | Sepolia RPC(覆盖炼金术) | - |
ETHERSCAN_API_KEY | Etherscan API密钥 | - |
ARBISCAN_API_KEY | Arbiscan API密钥 | - |
LOG_LEVEL | 日志记录级别 | info |
LOG_FILE | 日志文件路径 | ./audit-mcp.log |
SLITHER_PATH | Slither二进制文件的路径 | /usr/local/bin/slither |
SOLC_PATH | Solc二进制文件的路径 | /usr/local/bin/solc |
建筑
项目结构
src/
├── index.ts # Entry point (HTTP/stdio mode detection)
├── server.ts # Express app + McpServer setup
├── config.ts # Configuration management
├── anvil/
│ ├── manager.ts # Anvil process lifecycle
│ └── types.ts # Anvil-related types
├── state/
│ └── manager.ts # SQLite state management
├── tools/
│ ├── index.ts # Tool registration with McpServer.registerTool()
│ ├── reading.ts # Reading tools (4): source, storage, bytecode, events
│ ├── execution.ts # Execution tools (5): simulate, send, impersonate, snapshots
│ └── tracing.ts # Tracing tools (2): trace_transaction, trace_call
└── utils/
├── errors.ts # Error handling
└── validation.ts # Zod schemas数据库模式
用于状态持久化的SQLite表:
- 部署 -合同部署记录
- 铁砧_立场 -正在运行Anvil实例
- 审核会话 -审核会话元数据
- 审计设计 -发现漏洞
- audit_notes -会议记录
交通建筑
┌─────────────────┐
│ AI Agent/User │
└────────┬────────┘
│
┌────┴────┐
│ HTTP │ stdio
│ /mcp │ (stdin/stdout)
└────┬────┘
│
┌────┴──────────────────┐
│ McpServer (stateless)│
│ + registerTool API │
└────┬──────────────────┘
│
┌────┴────────┐
│ 11 Tools │
│ Reading: 4 │
│ Execution: 5│
│ Tracing: 2 │
└────┬────────┘
│
┌────┴────────┐
│ viem + │
│ Anvil │
└─────────────┘测试
自动化测试
# Run stdio transport tests
npx tsx test-stdio.ts
# Run all tool tests
npm test手动测试
# Test stdio transport
./test-stdio-manual.sh
# Test specific tools
npm run test:tools示例工作流
1.阅读并分析合同:
# Read source
read_source { "path": "PoolManager.sol" }
# Get bytecode
read_bytecode { "address": "0x..." }
# Read storage
read_storage { "address": "0x...", "slot": "0x0" }2.模拟并执行交易:
# Simulate first
simulate_tx {
"to": "0x...",
"data": "0x...",
"abi": [...]
}
# If successful, send
send_tx {
"to": "0x...",
"data": "0x...",
"privateKey": "0x..."
}3.使用快照进行测试:
# Create snapshot
create_snapshot { "name": "clean-state" }
# Run test transactions
send_tx { ... }
# Revert to clean state
revert_snapshot { "snapshotId": "clean-state" }发展
建筑
# Build TypeScript
npm run build
# Watch mode
npm run dev代码检查
# Run ESLint
npm run lint
# Format code
npm run format添加新工具
- 在Zod中定义输入/输出模式
src/tools/ - 实现处理程序功能
- 在工具对象中导出工具
- 注册
src/tools/index.ts - 将文档添加到TOOLS.md
安全考虑
- 冒充:仅适用于Anvil,不适用于生产网络
- 私钥:切勿记录或公开私钥
- RPC访问:使用具有身份验证的安全RPC终结点
- 州覆盖:仔细验证以防止意外行为
- 气体限制:始终设置合理的气体限制以防止DoS
- 输入验证:所有输入均已Zod模式验证
故障排除
常见问题
服务器无法启动:
- 检查端口可用性:
lsof -i :3000 - 验证中的环境变量
.env - 检查数据库权限
AUDIT_MCP_DB_PATH
Anvil连接失败:
- 确保Anvil已安装:
which anvil - 检查端口范围配置
- 验证无端口冲突
工具执行错误:
- 检查RPC终结点可用性
- 验证合同地址是否存在
- 确保交易有足够的天然气
- 检查模拟仅用于Anvil
stdio模式问题:
- 确保每行一条JSON-RPC消息
- 检查stderr以获取日志消息(stdout用于响应)
- 验证MCP协议版本兼容性
演出
- 连接池:跨请求重用viem客户端
- 状态缓存:SQLite用于快速状态检索
- 快照注册表:用于快速快照操作的内存跟踪
- 并发请求:Express处理多个并发MCP连接
路线图
- \[\]高级分析工具(Slither集成)
- \[\]调用图可视化
- \[\]AST解析实用程序
- \[\]多链支撑
- \[x\] 增强的跟踪分析(debug_traceTransaction、debug_trace Call)
- \[\]气体优化建议
- \[\]安全模式检测
贡献
欢迎投稿!拜托:
- 复刻仓库
- 创建要素分支
- 添加新功能的测试
- 更新文档
- 提交拉取请求
许可证
麻省理工学院
资源
支持
- 问题:
- 文档: TOOLS.md
- 示例:参见
test-tools.ts使用示例
