ERC20 Token Guide¶
This guide walks you through creating an MCP server for any ERC20 token. You'll be able to:
- ✅ Check token balances
- ✅ View token metadata (name, symbol, decimals)
- ✅ Track transfers and approvals
- ✅ Transfer tokens (optional)
- ✅ Approve spending (optional)
Prerequisites¶
- abi-to-mcp installed
- RPC endpoint (free from Alchemy/Infura or public)
- Token contract address
Step 1: Choose Your Token¶
For this guide, we'll use USDC on Ethereum mainnet:
| Property | Value |
|---|---|
| Token | USD Coin (USDC) |
| Address | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 |
| Network | Ethereum Mainnet |
Step 2: Generate the Server¶
abi-to-mcp generate 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 \
--network mainnet \
--output ./usdc-mcp-server \
--name "USDC Token"
This will: 1. Fetch the ABI from Etherscan 2. Parse functions and events 3. Generate the MCP server
Output:
🔍 Fetching ABI from Etherscan (mainnet)...
✅ Found verified contract: FiatTokenV2_2
📊 Detected standard: ERC20
📁 Generated files:
./usdc-mcp-server/
├── server.py
├── config.py
├── README.md
├── pyproject.toml
└── requirements.txt
🎉 Server ready! Run with: python ./usdc-mcp-server/server.py
Step 3: Configure the Server¶
Navigate to the generated directory:
Create a .env file:
# Required
RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR-API-KEY
# Optional - only for write operations
# PRIVATE_KEY=your-private-key-here
Never Commit .env
Add .env to your .gitignore to keep secrets safe.
Step 4: Install Dependencies¶
Or with the project:
Step 5: Run the Server¶
The server starts and listens for MCP connections.
Step 6: Test with Claude¶
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"usdc-token": {
"command": "python",
"args": ["/path/to/usdc-mcp-server/server.py"],
"env": {
"RPC_URL": "https://eth-mainnet.g.alchemy.com/v2/YOUR-API-KEY"
}
}
}
}
Restart Claude Desktop and try:
"What's the USDC balance of vitalik.eth?"
Claude will use the balance_of tool to check the balance.
Available Tools¶
Read Tools (No gas required)¶
| Tool | Description | Example |
|---|---|---|
name |
Get token name | "USD Coin" |
symbol |
Get token symbol | "USDC" |
decimals |
Get decimal places | 6 |
total_supply |
Get total supply | "26234567890000000" |
balance_of |
Get address balance | "1000000000" (1000 USDC) |
allowance |
Get spending approval | "500000000" |
Write Tools (Gas required)¶
| Tool | Description | Parameters |
|---|---|---|
transfer |
Send tokens | to, amount, simulate |
approve |
Approve spending | spender, amount, simulate |
transfer_from |
Transfer on behalf | from_, to, amount, simulate |
Working with Balances¶
USDC has 6 decimals, so:
| Raw Value | Human Readable |
|---|---|
1000000 |
1 USDC |
1000000000 |
1,000 USDC |
1000000000000 |
1,000,000 USDC |
Conversion Helper
Querying Transfers¶
The server also exposes Transfer events as a resource:
# Get recent transfers to an address
transfers = await get_transfer_events(
to_address="0x...",
from_block=current_block - 1000,
limit=10
)
Each transfer includes:
{
"from": "0x123...",
"to": "0x456...",
"value": "1000000000", # 1000 USDC
"block_number": 18500000,
"transaction_hash": "0x..."
}
Making Transfers¶
Real Money
Transfers move real tokens. Always simulate first and double-check addresses.
Simulate First¶
# This only simulates - no tokens moved
result = await transfer(
to="0x742d35Cc6634C0532925a3b844Bc9e7595f5b7A5",
amount="1000000", # 1 USDC
simulate=True # Default
)
Result:
Execute Transfer¶
# This WILL move tokens
result = await transfer(
to="0x742d35Cc6634C0532925a3b844Bc9e7595f5b7A5",
amount="1000000",
simulate=False # Actually execute
)
Result:
Read-Only Mode¶
If you only need to query data:
abi-to-mcp generate 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 \
--network mainnet \
--output ./usdc-readonly \
--read-only
This generates a server with only read tools - no transfer or approve functions.
Common Issues¶
"Contract source code not verified"¶
The token contract isn't verified on Etherscan. Solutions:
- Use a local ABI file if you have one
- Try a different block explorer
- Check if the contract is a proxy
"execution reverted"¶
Usually means: - Insufficient balance - Not enough allowance - Contract is paused
Balance shows 0 for known holder¶
Check: - Correct network (mainnet vs testnet) - Correct contract address - Address format (with 0x prefix)
Next Steps¶
- Track NFTs - Similar process for ERC721
- DeFi Integration - More complex protocols
- Claude Desktop - Full integration guide
Quick Start Example
A ready-to-use ERC20 example with USDC ABI is available in examples/erc20_token/.