MCP Anvil Tools

MCP Anvil Tools

Enables AI agents to interact with Ethereum smart contracts through Anvil, providing capabilities to read Solidity code, simulate and execute transactions, manipulate blockchain state, query events, and test contracts in isolated environments for development and auditing workflows.

Category
访问服务器

README

MCP Anvil Tools

Model Context Protocol (MCP) server providing Ethereum development and testing tools for AI agents. Built on Anvil (Foundry's local Ethereum node) and viem for robust blockchain interactions.

Overview

MCP Anvil Tools enables AI agents to:

  • Read Solidity source code and contract storage
  • Simulate and execute transactions on local Anvil or testnets
  • Manipulate blockchain state with snapshots and impersonation
  • Query events and decode bytecode
  • Test smart contracts in isolated environments

Perfect for AI-powered smart contract auditing, testing workflows, and blockchain development automation.

Key Features

  • Dual Transport Modes: Stateless HTTP via /mcp endpoint or stdio for CLI/desktop integration
  • Reading Tools (4): Source code, storage, bytecode, and event log access
  • Execution Tools (5): Transaction simulation, sending, and state manipulation
  • Tracing Tools (2): Transaction and call tracing with multiple tracer types
  • Anvil Integration: Automatic Anvil process management with snapshot/revert support
  • State Persistence: SQLite-backed deployment and session tracking
  • Type Safety: Full TypeScript support with Zod validation

Quick Start

Installation

# 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

Configuration

# Copy example environment file
cp .env.example .env

# Edit .env with your configuration
nano .env

Required environment variables:

  • AUDIT_MCP_PORT - Server port (default: 3000)
  • MAINNET_RPC_URL - RPC endpoint for mainnet interactions
  • ETHERSCAN_API_KEY - Optional, for source code verification

Running the Server

HTTP/SSE Mode (for web clients, multi-agent systems):

npm start
# Server runs on http://localhost:3000

stdio Mode (for Claude Desktop, CLI tools):

npm run start:stdio
# Communicates via stdin/stdout

Development Mode (with hot reload):

npm run dev

Transport Modes

HTTP Mode

Use HTTP mode for:

  • Web-based AI clients
  • Multi-agent architectures
  • Stateless MCP connections
  • RESTful API interactions

Endpoints:

  • GET /health - Health check (unauthenticated)
  • GET /metrics - Deployment and instance statistics
  • POST /mcp - MCP protocol endpoint (StreamableHTTPServerTransport)

Example Connection:

# 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 Mode

Use stdio for:

  • Claude Desktop integration
  • Command-line MCP clients
  • Programmatic testing
  • Shell script automation

Example Test:

# 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

Available Tools

Reading Tools

1. read_source

Read Solidity source code files from the v4-core repository.

Input:

  • path (string): Relative path from lib/v4-core/src/ (e.g., PoolManager.sol)

Output:

  • content (string): Full source code
  • lines (number): Total line count
  • path (string): Absolute file path
  • size (number): File size in bytes
  • lastModified (string): ISO timestamp

Example:

{
  "path": "PoolManager.sol"
}

2. read_storage

Read contract storage slots (persistent storage only, not transient).

Input:

  • address (string): Contract address
  • slot (string): Storage slot (hex, e.g., 0x0)
  • blockTag (optional): latest, earliest, pending, block number, or block hash
  • rpc (optional): RPC URL (default: http://localhost:8545)

Output:

  • value (string): Raw 32-byte hex value
  • decoded (optional): Best-effort interpretation (uint256, address, bool, bytes32)

Example:

{
  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "slot": "0x0",
  "blockTag": "latest"
}

3. read_bytecode

Retrieve deployed bytecode from a contract address.

Input:

  • address (string): Contract address
  • blockTag (optional): Block identifier
  • rpc (optional): RPC URL

Output:

  • bytecode (string): Hex-encoded bytecode
  • size (number): Bytecode size in bytes
  • codeHash (string): Keccak256 hash
  • isEmpty (boolean): True if no code deployed (EOA)

Example:

{
  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}

4. read_events

Query and decode contract event logs.

Input:

  • address (string): Contract address
  • eventSignature (optional): Event signature (e.g., Transfer(address,address,uint256))
  • topics (optional): Indexed topics filter
  • fromBlock (optional): Starting block (default: earliest)
  • toBlock (optional): Ending block (default: latest)
  • rpc (optional): RPC URL

Output:

  • events (array): Event logs with block info
  • count (number): Total events returned
  • fromBlock (string): Actual starting block
  • toBlock (string): Actual ending block

Example:

{
  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "eventSignature": "Transfer(address,address,uint256)",
  "fromBlock": 1000000,
  "toBlock": 1000100
}

Execution Tools

5. simulate_tx

Simulate transactions without sending them to the network.

Input:

  • to (string): Target contract address
  • data (string): Calldata (hex)
  • from (optional): Sender address
  • gasLimit (optional): Gas limit
  • value (optional): ETH value in wei (hex)
  • abi (optional): Contract ABI for decoding
  • functionName (optional): Function name for decoding
  • blockNumber (optional): Block to simulate at
  • stateOverrides (optional): State overrides by address
  • rpc (optional): RPC endpoint

Output:

  • result (string): Return data (hex)
  • decoded (optional): Decoded return value
  • reverted (boolean): Whether call reverted
  • revertReason (optional): Decoded revert reason
  • revertData (optional): Raw revert data

Example:

{
  "to": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "data": "0x70a08231000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266",
  "abi": [...],
  "functionName": "balanceOf"
}

6. send_tx

Send actual transactions to the network.

Input:

  • to (optional): Target address (omit for deployment)
  • data (string): Transaction data / bytecode
  • from (optional): Sender address
  • value (optional): ETH value in wei (hex)
  • gasLimit (optional): Gas limit (auto-estimated)
  • gasPrice (optional): Legacy gas price
  • maxFeePerGas (optional): EIP-1559 max fee
  • maxPriorityFeePerGas (optional): EIP-1559 priority fee
  • nonce (optional): Transaction nonce
  • privateKey (optional): Private key for signing
  • confirmations (optional): Confirmations to wait (default: 1)
  • rpc (optional): RPC endpoint

Output:

  • txHash (string): Transaction hash
  • blockNumber (string): Block number
  • blockHash (string): Block hash
  • gasUsed (string): Gas consumed
  • effectiveGasPrice (string): Actual gas price
  • status (enum): success or reverted
  • logs (array): Event logs
  • contractAddress (optional): Deployed contract address
  • from (string): Sender address
  • to (optional): Recipient address

Example:

{
  "to": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "data": "0xa9059cbb...",
  "value": "0x0",
  "privateKey": "0x..."
}

7. impersonate

Impersonate any address on Anvil (testing only).

Input:

  • address (string): Address to impersonate
  • stopImpersonating (optional): Stop impersonation (default: false)
  • rpc (optional): RPC endpoint (must be Anvil)

Output:

  • success (boolean): Whether operation succeeded
  • address (string): Impersonated address
  • active (boolean): Current impersonation status
  • balance (optional): Current balance

Example:

{
  "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
}

8. create_snapshot

Create Anvil state snapshot for later revert.

Input:

  • name (optional): Human-readable snapshot name
  • description (optional): Snapshot description
  • rpc (optional): RPC endpoint (must be Anvil)

Output:

  • snapshotId (string): Unique snapshot identifier
  • name (optional): Snapshot name
  • blockNumber (number): Block at snapshot
  • blockHash (string): Block hash
  • timestamp (number): Block timestamp
  • created (number): Unix timestamp created

Example:

{
  "name": "before-attack-simulation",
  "description": "State before testing exploit scenario"
}

9. revert_snapshot

Revert blockchain state to a previous snapshot.

Input:

  • snapshotId (string): Snapshot ID or name
  • rpc (optional): RPC endpoint (must be Anvil)

Output:

  • success (boolean): Whether revert succeeded
  • snapshotId (string): Reverted snapshot ID
  • blockNumber (number): Block after revert
  • blockHash (string): Block hash after revert
  • timestamp (number): Block timestamp
  • reverted (boolean): State revert confirmation

Example:

{
  "snapshotId": "before-attack-simulation"
}

Tracing Tools

10. trace_transaction

Trace an existing transaction by hash using debug_traceTransaction.

Input:

  • txHash (string): Transaction hash to trace (64 hex characters)
  • tracer (optional): Tracer type - callTracer, prestateTracer, 4byteTracer, or omit for raw opcode trace
  • tracerConfig (optional): Tracer-specific configuration object
    • For callTracer: { onlyTopCall: true } to exclude subcalls
  • rpc (optional): RPC URL (default: http://localhost:8545)

Output:

  • result: Trace result (format depends on tracer type)
    • callTracer: Call tree with type, from, to, value, gas, input, output
    • prestateTracer: Pre-execution state of all touched accounts
    • 4byteTracer: Map of function selectors to call counts
    • No tracer: Full opcode trace with structLogs array
  • txHash (string): Transaction hash that was traced

Example:

{
  "txHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "tracer": "callTracer",
  "tracerConfig": {
    "onlyTopCall": true
  }
}

Use Cases:

  • Debug failed transactions
  • Analyze gas usage patterns
  • Understand contract interactions
  • Detect reentrancy or complex call paths

11. trace_call

Trace a call without sending transaction using debug_traceCall.

Input:

  • to (string): Target contract address
  • data (string): Calldata (hex encoded)
  • from (optional): Sender address
  • value (optional): ETH value in wei (hex)
  • blockTag (optional): Block to trace at - latest, earliest, pending, safe, finalized, or block number
  • tracer (optional): Tracer type (same as trace_transaction)
  • tracerConfig (optional): Tracer configuration
  • rpc (optional): RPC URL

Output:

  • result: Trace result (format depends on tracer type, same as trace_transaction)

Example:

{
  "to": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "data": "0xa9059cbb000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000de0b6b3a7640000",
  "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
  "tracer": "callTracer"
}

Use Cases:

  • Debug before sending actual transactions
  • Analyze call behavior at specific blocks
  • Test state override scenarios
  • Investigate potential exploits safely

Claude Desktop Integration

Add to your Claude Desktop configuration (~/Library/Application Support/Claude/claude_desktop_config.json on 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"
      }
    }
  }
}

Important: Use absolute paths for the command args. Restart Claude Desktop after configuration changes.

Configuration

Alchemy Multi-Network Support

Set ALCHEMY_API_KEY to enable access to any Alchemy-supported network without additional configuration:

ALCHEMY_API_KEY=your_alchemy_api_key

Use any Alchemy network slug directly:

Network Slug
Ethereum eth-mainnet, eth-sepolia
Arbitrum arb-mainnet, arb-sepolia
Optimism opt-mainnet, opt-sepolia
Polygon polygon-mainnet, polygon-amoy
Base base-mainnet, base-sepolia

New networks are supported automatically as Alchemy adds them - no code changes needed.

Environment Variables

Variable Description Default
AUDIT_MCP_PORT HTTP server port 3000
AUDIT_MCP_HOST HTTP server host 0.0.0.0
AUDIT_MCP_DB_PATH SQLite database path ./audit-mcp.db
ANVIL_PORT_START Anvil port range start 8545
ANVIL_PORT_END Anvil port range end 8555
ANVIL_DEFAULT_CHAIN_ID Default chain ID 31337
ALCHEMY_API_KEY Alchemy API key (enables multi-network) -
MAINNET_RPC_URL Mainnet RPC (overrides Alchemy) -
SEPOLIA_RPC_URL Sepolia RPC (overrides Alchemy) -
ETHERSCAN_API_KEY Etherscan API key -
ARBISCAN_API_KEY Arbiscan API key -
LOG_LEVEL Logging level info
LOG_FILE Log file path ./audit-mcp.log
SLITHER_PATH Path to Slither binary /usr/local/bin/slither
SOLC_PATH Path to Solc binary /usr/local/bin/solc

Architecture

Project Structure

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

Database Schema

SQLite tables for state persistence:

  • deployments - Contract deployment records
  • anvil_instances - Running Anvil instances
  • audit_sessions - Audit session metadata
  • audit_findings - Discovered vulnerabilities
  • audit_notes - Session notes

Transport Architecture

┌─────────────────┐
│  AI Agent/User  │
└────────┬────────┘
         │
    ┌────┴────┐
    │  HTTP   │  stdio
    │  /mcp   │  (stdin/stdout)
    └────┬────┘
         │
    ┌────┴──────────────────┐
    │  McpServer (stateless)│
    │  + registerTool API   │
    └────┬──────────────────┘
         │
    ┌────┴────────┐
    │   11 Tools  │
    │  Reading: 4 │
    │ Execution: 5│
    │  Tracing: 2 │
    └────┬────────┘
         │
    ┌────┴────────┐
    │    viem +   │
    │    Anvil    │
    └─────────────┘

Testing

Automated Tests

# Run stdio transport tests
npx tsx test-stdio.ts

# Run all tool tests
npm test

Manual Testing

# Test stdio transport
./test-stdio-manual.sh

# Test specific tools
npm run test:tools

Example Workflows

1. Read and analyze contract:

# Read source
read_source { "path": "PoolManager.sol" }

# Get bytecode
read_bytecode { "address": "0x..." }

# Read storage
read_storage { "address": "0x...", "slot": "0x0" }

2. Simulate and execute transaction:

# Simulate first
simulate_tx {
  "to": "0x...",
  "data": "0x...",
  "abi": [...]
}

# If successful, send
send_tx {
  "to": "0x...",
  "data": "0x...",
  "privateKey": "0x..."
}

3. Test with snapshots:

# Create snapshot
create_snapshot { "name": "clean-state" }

# Run test transactions
send_tx { ... }

# Revert to clean state
revert_snapshot { "snapshotId": "clean-state" }

Development

Building

# Build TypeScript
npm run build

# Watch mode
npm run dev

Linting

# Run ESLint
npm run lint

# Format code
npm run format

Adding New Tools

  1. Define input/output schemas with Zod in src/tools/
  2. Implement handler function
  3. Export tool in tools object
  4. Register in src/tools/index.ts
  5. Add documentation to TOOLS.md

Security Considerations

  • Impersonation: Only works on Anvil, not production networks
  • Private Keys: Never log or expose private keys
  • RPC Access: Use secure RPC endpoints with authentication
  • State Overrides: Validate carefully to prevent unintended behavior
  • Gas Limits: Always set reasonable gas limits to prevent DoS
  • Input Validation: All inputs validated with Zod schemas

Troubleshooting

Common Issues

Server won't start:

  • Check port availability: lsof -i :3000
  • Verify environment variables in .env
  • Check database permissions for AUDIT_MCP_DB_PATH

Anvil connection fails:

  • Ensure Anvil is installed: which anvil
  • Check port range configuration
  • Verify no port conflicts

Tool execution errors:

  • Check RPC endpoint availability
  • Verify contract address exists
  • Ensure sufficient gas for transactions
  • Check impersonation is only used on Anvil

stdio mode issues:

  • Ensure one JSON-RPC message per line
  • Check stderr for log messages (stdout is for responses)
  • Verify MCP protocol version compatibility

Performance

  • Connection Pooling: Reuses viem clients across requests
  • State Caching: SQLite for fast state retrieval
  • Snapshot Registry: In-memory tracking for quick snapshot operations
  • Concurrent Requests: Express handles multiple concurrent MCP connections

Roadmap

  • [ ] Advanced analysis tools (Slither integration)
  • [ ] Call graph visualization
  • [ ] AST parsing utilities
  • [ ] Multi-chain support
  • [x] Enhanced trace analysis (debug_traceTransaction, debug_traceCall)
  • [ ] Gas optimization suggestions
  • [ ] Security pattern detection

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Update documentation
  5. Submit a pull request

License

MIT

Resources

Support

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选