Enables AI agents to interact with Ethereum blockchain through Anvil local node, including reading smart contracts, simulating and executing transactions, querying events, manipulating blockchain state with snapshots and impersonation, and tracing transaction execution.
Provides tools for reading and analyzing Solidity source code files, particularly from the v4-core repository, supporting smart contract auditing and development workflows.
Uses SQLite for persistent storage of deployment tracking and session management data.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP Anvil Toolssimulate a transaction to transfer 100 ETH from the deployer to a test address"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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
/mcpendpoint or stdio for CLI/desktop integrationReading 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 buildConfiguration
# Copy example environment file
cp .env.example .env
# Edit .env with your configuration
nano .envRequired environment variables:
AUDIT_MCP_PORT- Server port (default: 3000)MAINNET_RPC_URL- RPC endpoint for mainnet interactionsETHERSCAN_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:3000stdio Mode (for Claude Desktop, CLI tools):
npm run start:stdio
# Communicates via stdin/stdoutDevelopment Mode (with hot reload):
npm run devTransport 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 statisticsPOST /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.shAvailable Tools
Reading Tools
1. read_source
Read Solidity source code files from the v4-core repository.
Input:
path(string): Relative path fromlib/v4-core/src/(e.g.,PoolManager.sol)
Output:
content(string): Full source codelines(number): Total line countpath(string): Absolute file pathsize(number): File size in byteslastModified(string): ISO timestamp
Example:
{
"path": "PoolManager.sol"
}2. read_storage
Read contract storage slots (persistent storage only, not transient).
Input:
address(string): Contract addressslot(string): Storage slot (hex, e.g.,0x0)blockTag(optional):latest,earliest,pending, block number, or block hashrpc(optional): RPC URL (default:http://localhost:8545)
Output:
value(string): Raw 32-byte hex valuedecoded(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 addressblockTag(optional): Block identifierrpc(optional): RPC URL
Output:
bytecode(string): Hex-encoded bytecodesize(number): Bytecode size in bytescodeHash(string): Keccak256 hashisEmpty(boolean): True if no code deployed (EOA)
Example:
{
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}4. read_events
Query and decode contract event logs.
Input:
address(string): Contract addresseventSignature(optional): Event signature (e.g.,Transfer(address,address,uint256))topics(optional): Indexed topics filterfromBlock(optional): Starting block (default:earliest)toBlock(optional): Ending block (default:latest)rpc(optional): RPC URL
Output:
events(array): Event logs with block infocount(number): Total events returnedfromBlock(string): Actual starting blocktoBlock(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 addressdata(string): Calldata (hex)from(optional): Sender addressgasLimit(optional): Gas limitvalue(optional): ETH value in wei (hex)abi(optional): Contract ABI for decodingfunctionName(optional): Function name for decodingblockNumber(optional): Block to simulate atstateOverrides(optional): State overrides by addressrpc(optional): RPC endpoint
Output:
result(string): Return data (hex)decoded(optional): Decoded return valuereverted(boolean): Whether call revertedrevertReason(optional): Decoded revert reasonrevertData(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 / bytecodefrom(optional): Sender addressvalue(optional): ETH value in wei (hex)gasLimit(optional): Gas limit (auto-estimated)gasPrice(optional): Legacy gas pricemaxFeePerGas(optional): EIP-1559 max feemaxPriorityFeePerGas(optional): EIP-1559 priority feenonce(optional): Transaction nonceprivateKey(optional): Private key for signingconfirmations(optional): Confirmations to wait (default: 1)rpc(optional): RPC endpoint
Output:
txHash(string): Transaction hashblockNumber(string): Block numberblockHash(string): Block hashgasUsed(string): Gas consumedeffectiveGasPrice(string): Actual gas pricestatus(enum):successorrevertedlogs(array): Event logscontractAddress(optional): Deployed contract addressfrom(string): Sender addressto(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 impersonatestopImpersonating(optional): Stop impersonation (default: false)rpc(optional): RPC endpoint (must be Anvil)
Output:
success(boolean): Whether operation succeededaddress(string): Impersonated addressactive(boolean): Current impersonation statusbalance(optional): Current balance
Example:
{
"address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
}8. create_snapshot
Create Anvil state snapshot for later revert.
Input:
name(optional): Human-readable snapshot namedescription(optional): Snapshot descriptionrpc(optional): RPC endpoint (must be Anvil)
Output:
snapshotId(string): Unique snapshot identifiername(optional): Snapshot nameblockNumber(number): Block at snapshotblockHash(string): Block hashtimestamp(number): Block timestampcreated(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 namerpc(optional): RPC endpoint (must be Anvil)
Output:
success(boolean): Whether revert succeededsnapshotId(string): Reverted snapshot IDblockNumber(number): Block after revertblockHash(string): Block hash after reverttimestamp(number): Block timestampreverted(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 tracetracerConfig(optional): Tracer-specific configuration objectFor
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,outputprestateTracer: Pre-execution state of all touched accounts
4byteTracer: Map of function selectors to call counts
No tracer: Full opcode trace with
structLogsarray
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 addressdata(string): Calldata (hex encoded)from(optional): Sender addressvalue(optional): ETH value in wei (hex)blockTag(optional): Block to trace at -latest,earliest,pending,safe,finalized, or block numbertracer(optional): Tracer type (same astrace_transaction)tracerConfig(optional): Tracer configurationrpc(optional): RPC URL
Output:
result: Trace result (format depends on tracer type, same astrace_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_keyUse any Alchemy network slug directly:
Network | Slug |
Ethereum |
|
Arbitrum |
|
Optimism |
|
Polygon |
|
Base |
|
New networks are supported automatically as Alchemy adds them - no code changes needed.
Environment Variables
Variable | Description | Default |
| HTTP server port |
|
| HTTP server host |
|
| SQLite database path |
|
| Anvil port range start |
|
| Anvil port range end |
|
| Default chain ID |
|
| Alchemy API key (enables multi-network) | - |
| Mainnet RPC (overrides Alchemy) | - |
| Sepolia RPC (overrides Alchemy) | - |
| Etherscan API key | - |
| Arbiscan API key | - |
| Logging level |
|
| Log file path |
|
| Path to Slither binary |
|
| Path to Solc binary |
|
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 schemasDatabase 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 testManual Testing
# Test stdio transport
./test-stdio-manual.sh
# Test specific tools
npm run test:toolsExample 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 devLinting
# Run ESLint
npm run lint
# Format code
npm run formatAdding New Tools
Define input/output schemas with Zod in
src/tools/Implement handler function
Export tool in tools object
Register in
src/tools/index.tsAdd 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 :3000Verify environment variables in
.envCheck database permissions for
AUDIT_MCP_DB_PATH
Anvil connection fails:
Ensure Anvil is installed:
which anvilCheck 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
Enhanced trace analysis (debug_traceTransaction, debug_traceCall)
Gas optimization suggestions
Security pattern detection
Contributing
Contributions welcome! Please:
Fork the repository
Create a feature branch
Add tests for new functionality
Update documentation
Submit a pull request
License
MIT
Resources
TOOLS.md - Detailed tool reference
Support
Issues: GitHub Issues
Documentation: TOOLS.md
Examples: See
test-tools.tsfor usage examples
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.