|
| 1 | +# Etherscan MCP Python Server |
| 2 | + |
| 3 | +A complete Python implementation of the Etherscan Model Context Protocol (MCP) server, providing comprehensive access to Ethereum blockchain data through the Etherscan API. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +This server provides 53+ tools for accessing Ethereum blockchain data, including: |
| 8 | + |
| 9 | +- **Account Tools**: Balance checking, transaction history, internal transactions |
| 10 | +- **Block Tools**: Block data, rewards, timing information |
| 11 | +- **Contract Tools**: Source code, ABI, verification status |
| 12 | +- **Transaction Tools**: Transaction details, receipts, status |
| 13 | +- **Token Tools**: Transfers, balances, supply information |
| 14 | +- **Gas Tools**: Gas prices, estimates, oracle data |
| 15 | +- **Statistics Tools**: Network metrics, supply data |
| 16 | +- **RPC Tools**: Ethereum RPC proxy methods |
| 17 | +- **Logs Tools**: Event logs and filtering |
| 18 | + |
| 19 | +## Requirements |
| 20 | + |
| 21 | +- Python 3.8+ |
| 22 | +- Etherscan API Key |
| 23 | + |
| 24 | +## Installation |
| 25 | + |
| 26 | +```bash |
| 27 | +cd etherscan-mcp-python |
| 28 | +pip install -e . |
| 29 | +``` |
| 30 | + |
| 31 | +## Configuration |
| 32 | + |
| 33 | +Set your Etherscan API key as an environment variable: |
| 34 | + |
| 35 | +```bash |
| 36 | +export ETHERSCAN_API_KEY="your_api_key_here" |
| 37 | +``` |
| 38 | + |
| 39 | +## Usage |
| 40 | + |
| 41 | +### Standalone Server |
| 42 | +```bash |
| 43 | +python server.py |
| 44 | +``` |
| 45 | + |
| 46 | +### With MCP Tools (Agno Framework) |
| 47 | +```python |
| 48 | +from agno.tools.mcp import MCPTools |
| 49 | + |
| 50 | +etherscan_mcp = MCPTools( |
| 51 | + command="python etherscan-mcp-python/server.py", |
| 52 | + env={"ETHERSCAN_API_KEY": "your_api_key"}, |
| 53 | + timeout_seconds=120 |
| 54 | +) |
| 55 | +``` |
| 56 | + |
| 57 | +## Complete Tool Reference |
| 58 | + |
| 59 | +### 🏦 Account Tools (12 tools) |
| 60 | +| Tool Name | Description | Key Parameters | |
| 61 | +|-----------|-------------|----------------| |
| 62 | +| `account_balance` | Get ETH balance for single address | `address`, `chainid` | |
| 63 | +| `account_balancemulti` | Get ETH balance for multiple addresses (up to 20) | `address` (comma-separated), `chainid` | |
| 64 | +| `account_txlist` | Get normal transactions by address | `address`, `startblock`, `endblock`, `page`, `offset` | |
| 65 | +| `account_txlistinternal` | Get internal transactions by address | `address`, `startblock`, `endblock`, `page`, `offset` | |
| 66 | +| `account_txlistinternal_byhash` | Get internal transactions by transaction hash | `txhash`, `chainid` | |
| 67 | +| `account_txlistinternal_byblock` | Get internal transactions by block range | `startblock`, `endblock`, `page`, `offset` | |
| 68 | +| `account_tokentx` | Get ERC20 token transfer events | `address`, `contractaddress`, `startblock`, `endblock` | |
| 69 | +| `account_tokennfttx` | Get ERC721 (NFT) token transfer events | `address`, `contractaddress`, `startblock`, `endblock` | |
| 70 | +| `account_token1155tx` | Get ERC1155 token transfer events | `address`, `contractaddress`, `startblock`, `endblock` | |
| 71 | +| `account_fundedby` | Get address funding source and age | `address`, `chainid` | |
| 72 | +| `account_getminedblocks` | Get blocks validated by address | `address`, `blocktype`, `page`, `offset` | |
| 73 | +| `account_txsBeaconWithdrawal` | Get beacon chain withdrawals | `address`, `startblock`, `endblock`, `page`, `offset` | |
| 74 | + |
| 75 | +### 🧱 Block Tools (4 tools) |
| 76 | +| Tool Name | Description | Key Parameters | |
| 77 | +|-----------|-------------|----------------| |
| 78 | +| `block_getblockreward` | Get block mining reward and uncle rewards | `blockno`, `chainid` | |
| 79 | +| `block_getblockcountdown` | Get estimated time until block is mined | `blockno`, `chainid` | |
| 80 | +| `block_getblocknobytime` | Get block number by timestamp | `timestamp`, `closest`, `chainid` | |
| 81 | +| `block_getblocktxnscount` | Get number of transactions in block | `blockno`, `chainid` | |
| 82 | + |
| 83 | +### 📄 Contract Tools (4 tools) |
| 84 | +| Tool Name | Description | Key Parameters | |
| 85 | +|-----------|-------------|----------------| |
| 86 | +| `contract_getabi` | Get contract ABI for verified contracts | `address`, `chainid` | |
| 87 | +| `contract_getsourcecode` | Get verified contract source code | `address`, `chainid` | |
| 88 | +| `contract_getcontractcreation` | Get contract creator and creation tx hash | `contractaddresses`, `chainid` | |
| 89 | +| `contract_checkverifystatus` | Check contract verification status | `guid`, `chainid` | |
| 90 | + |
| 91 | +### 🔄 Transaction Tools (2 tools) |
| 92 | +| Tool Name | Description | Key Parameters | |
| 93 | +|-----------|-------------|----------------| |
| 94 | +| `transaction_getstatus` | Get contract execution status | `txhash`, `chainid` | |
| 95 | +| `transaction_gettxreceiptstatus` | Get transaction receipt status | `txhash`, `chainid` | |
| 96 | + |
| 97 | +### 🪙 Token Tools (2 tools) |
| 98 | +| Tool Name | Description | Key Parameters | |
| 99 | +|-----------|-------------|----------------| |
| 100 | +| `stats_tokensupply` | Get ERC20 token total supply | `contractaddress`, `chainid` | |
| 101 | +| `account_tokenbalance` | Get ERC20 token balance of address | `contractaddress`, `address`, `chainid` | |
| 102 | + |
| 103 | +### ⛽ Gas Tools (3 tools) |
| 104 | +| Tool Name | Description | Key Parameters | |
| 105 | +|-----------|-------------|----------------| |
| 106 | +| `gas_gasestimate` | Get estimated confirmation time for gas price | `gasprice`, `chainid` | |
| 107 | +| `gas_gasoracle` | Get current safe/proposed/fast gas prices | `chainid` | |
| 108 | +| `stats_dailyavggaslimit` | Get historical daily average gas limit | `startdate`, `enddate`, `sort`, `chainid` | |
| 109 | + |
| 110 | +### 📊 Statistics Tools (13 tools) |
| 111 | +| Tool Name | Description | Key Parameters | |
| 112 | +|-----------|-------------|----------------| |
| 113 | +| `stats_ethsupply` | Get total ETH supply (excluding staking/burnt) | `chainid` | |
| 114 | +| `stats_ethsupply2` | Get total ETH supply (including staking/burnt) | `chainid` | |
| 115 | +| `stats_ethprice` | Get current ETH price | `chainid` | |
| 116 | +| `stats_chainsize` | Get blockchain size over date range | `startdate`, `enddate`, `clienttype`, `syncmode` | |
| 117 | +| `stats_nodecount` | Get total discoverable nodes | `chainid` | |
| 118 | +| `stats_dailytxnfee` | Get daily transaction fees paid to miners | `startdate`, `enddate`, `sort` | |
| 119 | +| `stats_dailynewaddress` | Get daily new address count | `startdate`, `enddate`, `sort` | |
| 120 | +| `stats_dailynetutilization` | Get daily network utilization percentage | `startdate`, `enddate`, `sort` | |
| 121 | +| `stats_dailyavghashrate` | Get daily average network hash rate | `startdate`, `enddate`, `sort` | |
| 122 | +| `stats_dailytx` | Get daily transaction count | `startdate`, `enddate`, `sort` | |
| 123 | +| `stats_dailyavgnetdifficulty` | Get daily average mining difficulty | `startdate`, `enddate`, `sort` | |
| 124 | +| `stats_ethdailyprice` | Get historical ETH prices | `startdate`, `enddate`, `sort` | |
| 125 | + |
| 126 | +### 📝 Logs Tools (3 tools) |
| 127 | +| Tool Name | Description | Key Parameters | |
| 128 | +|-----------|-------------|----------------| |
| 129 | +| `logs_getLogsByAddress` | Get event logs from address with block range | `address`, `fromBlock`, `toBlock`, `page`, `offset` | |
| 130 | +| `logs_getLogsByTopics` | Get event logs filtered by topics | `fromBlock`, `toBlock`, `topic0-3`, operators | |
| 131 | +| `logs_getLogsByAddressAndTopics` | Get event logs from address filtered by topics | `address`, `fromBlock`, `toBlock`, `topic0-3` | |
| 132 | + |
| 133 | +### 🔗 RPC Proxy Tools (13 tools) |
| 134 | +| Tool Name | Description | Key Parameters | |
| 135 | +|-----------|-------------|----------------| |
| 136 | +| `proxy_eth_blockNumber` | Get latest block number | `chainid` | |
| 137 | +| `proxy_eth_getBlockByNumber` | Get block information by number | `tag`, `boolean`, `chainid` | |
| 138 | +| `proxy_eth_getUncleByBlockNumberAndIndex` | Get uncle block by number and index | `tag`, `index`, `chainid` | |
| 139 | +| `proxy_eth_getBlockTransactionCountByNumber` | Get transaction count in block | `tag`, `chainid` | |
| 140 | +| `proxy_eth_getTransactionByHash` | Get transaction by hash | `txhash`, `chainid` | |
| 141 | +| `proxy_eth_getTransactionByBlockNumberAndIndex` | Get transaction by block and index | `tag`, `index`, `chainid` | |
| 142 | +| `proxy_eth_getTransactionCount` | Get transaction count by address | `address`, `tag`, `chainid` | |
| 143 | +| `proxy_eth_getTransactionReceipt` | Get transaction receipt | `txhash`, `chainid` | |
| 144 | +| `proxy_eth_call` | Execute message call without transaction | `to`, `data`, `tag`, `chainid` | |
| 145 | +| `proxy_eth_getCode` | Get code at address | `address`, `tag`, `chainid` | |
| 146 | +| `proxy_eth_getStorageAt` | Get storage value at position | `address`, `position`, `tag`, `chainid` | |
| 147 | +| `proxy_eth_gasPrice` | Get current gas price | `chainid` | |
| 148 | +| `proxy_eth_estimateGas` | Estimate gas for transaction | `data`, `to`, `value`, `gas`, `gasPrice` | |
| 149 | + |
| 150 | +## 🎯 Use Cases & Examples |
| 151 | + |
| 152 | +### Basic Balance Check |
| 153 | +```python |
| 154 | +# Get ETH balance for single address |
| 155 | +account_balance(address="0x...", chainid="1") |
| 156 | + |
| 157 | +# Get balances for multiple addresses (up to 20) |
| 158 | +account_balancemulti(address="0x...,0x...,0x...", chainid="1") |
| 159 | +``` |
| 160 | + |
| 161 | +### Transaction Analysis |
| 162 | +```python |
| 163 | +# Get transaction history for address |
| 164 | +account_txlist(address="0x...", startblock="0", endblock="99999999") |
| 165 | + |
| 166 | +# Get internal transactions (contract interactions) |
| 167 | +account_txlistinternal(address="0x...", page="1", offset="100") |
| 168 | +``` |
| 169 | + |
| 170 | +### Block Information |
| 171 | +```python |
| 172 | +# Get transaction count in specific block (like the web3_GAIA_test.py example) |
| 173 | +block_getblocktxnscount(blockno="17000000", chainid="1") |
| 174 | + |
| 175 | +# Get block mining rewards |
| 176 | +block_getblockreward(blockno="17000000", chainid="1") |
| 177 | +``` |
| 178 | + |
| 179 | +### Market Data |
| 180 | +```python |
| 181 | +# Get current ETH price |
| 182 | +stats_ethprice(chainid="1") |
| 183 | + |
| 184 | +# Get current gas prices |
| 185 | +gas_gasoracle(chainid="1") |
| 186 | +``` |
| 187 | + |
| 188 | +### Smart Contract Analysis |
| 189 | +```python |
| 190 | +# Get contract source code (if verified) |
| 191 | +contract_getsourcecode(address="0x...", chainid="1") |
| 192 | + |
| 193 | +# Get contract ABI |
| 194 | +contract_getabi(address="0x...", chainid="1") |
| 195 | +``` |
| 196 | + |
| 197 | +## 🔧 Advanced Configuration |
| 198 | + |
| 199 | +### Multi-Chain Support |
| 200 | +The server supports multiple Ethereum networks via the `chainid` parameter: |
| 201 | +- `"1"` - Ethereum Mainnet (default) |
| 202 | +- `"5"` - Goerli Testnet |
| 203 | +- `"11155111"` - Sepolia Testnet |
| 204 | +- And other supported networks |
| 205 | + |
| 206 | +### Error Handling |
| 207 | +The server includes comprehensive error handling for: |
| 208 | +- ❌ Missing API keys |
| 209 | +- ❌ Invalid parameters |
| 210 | +- ❌ API rate limits |
| 211 | +- ❌ Network timeouts |
| 212 | +- ❌ Malformed responses |
| 213 | + |
| 214 | +### Performance Optimization |
| 215 | +- ✅ Synchronous HTTP client for MCP compatibility |
| 216 | +- ✅ Efficient JSON parsing and response formatting |
| 217 | +- ✅ Proper timeout handling (120 seconds default) |
| 218 | +- ✅ Memory-efficient tool registration |
| 219 | + |
| 220 | +## 🔐 Security & Best Practices |
| 221 | + |
| 222 | +### API Key Management |
| 223 | +- Store `ETHERSCAN_API_KEY` in environment variables |
| 224 | +- Never commit API keys to version control |
| 225 | +- Use `.env` files for local development |
| 226 | +- Rotate API keys regularly |
| 227 | + |
| 228 | +### Rate Limiting |
| 229 | +- Etherscan API has rate limits (free tier: 5 calls/sec) |
| 230 | +- The server respects these limits |
| 231 | +- Consider upgrading to Etherscan Pro for higher limits |
| 232 | + |
| 233 | +### Data Validation |
| 234 | +- All input parameters are validated |
| 235 | +- API responses are checked for errors |
| 236 | +- Malformed data is handled gracefully |
| 237 | + |
| 238 | +## 🆘 Troubleshooting |
| 239 | + |
| 240 | +### Common Issues |
| 241 | + |
| 242 | +**❌ "ETHERSCAN_API_KEY not set"** |
| 243 | +- Solution: Set the environment variable `export ETHERSCAN_API_KEY="your_key"` |
| 244 | + |
| 245 | +**❌ "Connection closed" or "Runtime error"** |
| 246 | +- Solution: Ensure you're not running in nested async context |
| 247 | +- Check that the server.py uses synchronous `main()` function |
| 248 | + |
| 249 | +**❌ "Tool not found"** |
| 250 | +- Solution: Verify tool names use underscores (`account_balance` not `account/balance`) |
| 251 | +- Check that tool renaming for Gemini compatibility is applied |
| 252 | + |
| 253 | +**❌ "Timeout after 120 seconds"** |
| 254 | +- Solution: Check internet connectivity and API key validity |
| 255 | +- Verify Etherscan API is not experiencing outages |
| 256 | + |
| 257 | +### Debug Mode |
| 258 | +For debugging, you can modify the server to add verbose logging: |
| 259 | +```python |
| 260 | +import logging |
| 261 | +logging.basicConfig(level=logging.DEBUG) |
| 262 | +``` |
| 263 | + |
| 264 | +## 🤝 Contributing |
| 265 | + |
| 266 | +### Adding New Tools |
| 267 | +1. Choose appropriate tool category file (`src/tools/`) |
| 268 | +2. Follow existing patterns for parameter validation |
| 269 | +3. Add comprehensive docstrings |
| 270 | +4. Test with actual API calls |
| 271 | +5. Update this README with new tool documentation |
0 commit comments