mantle-mcp
by Tmalone1250
README.md
# Mantle Network MCP Server (`mantle-mcp`)
A highly optimized Model Context Protocol (MCP) server built with Python and [FastMCP](https://github.com/modelcontextprotocol/python-sdk). This server exposes a suite of tools that enable agentic frameworks and LLM interfaces (like KinetiFi) to interact with the **Mantle Network** (Layer 2 on Ethereum) for querying native and ERC-20 balances, checking allowances, retrieving DEX swap quotes (V2 and V3 architectures), estimating L2 gas costs, and managing on-chain **Real World Assets (RWA)** and **ERC-8004 Agent Identities/Reputations**.
---
## Features
- **Asynchronous Architecture:** Built from the ground up using `asyncio` and `web3[async]` to minimize latency and maximize performance when handling multiple requests.
- **Dynamic Token Resolution:** Resolves token symbols (e.g., `USDC`, `WETH`) dynamically by checking a local registry first, then falling back to Blockscout Explorer APIs for both mainnet and testnet.
- **Uniswap V3 / Merchant Moe / Agni Finance Integration:** Computes exact, real-time swap quotes (`quoteExactInputSingle`) using standard Uniswap V3 QuoterV2 logic.
- **ERC-8004 Identity & Reputation:** Implements the proposed ERC-8004 standard on Mantle to register agent ownership and verify reputation scores on-chain.
- **RWA Yield Optimization:** Integrates Mantle Staked Ether (`mETH`) yield index queries and Ondo `USDY` transaction generators.
- **Advanced Execution Bundler:** Formulates atomic, multi-step transaction bundles for advanced DeFi strategies like Arbitrage, Portfolio Rebalancing, and Yield Auto-Compounding.
- **Zero-Trust & Stateless:** Exposes read-only queries and generates unsigned EVM transaction payloads (to, data, value). Never requests, handles, or stores private keys.
- **Offline Test Suite:** A robust and comprehensive test suite using `pytest` and `unittest.mock` for fully offline, fast, and deterministic verification of all L2 RPC and API interactions.
---
## Repository Structure
```tree
mantle-mcp/
├── .env # Environment configurations for L2 RPC endpoints
├── README.md # Server documentation
├── requirements.txt # Project Python dependencies
├── server.py # Main entrypoint initializing FastMCP and registering tools
├── tools/ # Sub-modules implementing individual blockchain queries
│ ├── __init__.py # Web3 client initializer and network constant definitions
│ ├── advanced_execution.py # Rebalance, arbitrage, and autocompound transaction builders
│ ├── balance.py # Native MNT balance lookup
│ ├── dex.py # V2 and V3 DEX swap quotes (Uniswap V2 Router & V3 QuoterV2)
│ ├── erc20.py # ERC-20 balanceOf and allowance query functions
│ ├── execution.py # Aave supply and Merchant Moe zap bundle generators
│ ├── gas.py # L2 gas units and gas price estimation
│ ├── identity.py # ERC-8004 Agent Identity registry & Reputation metrics
│ ├── moe_scanner.py # Merchant Moe pool scanning and math calculations
│ ├── network.py # Network metadata and connection health checker
│ ├── rwa.py # Ondo USDY and mETH yield rate query & wrap tools
│ ├── tokens.py # Dynamic token symbol-to-address resolution
│ └── yield_scanner.py # Aave reserve yield scanner
└── tests/ # Deterministic async offline tests
├── test_dex.py # V2 & V3 Swap quote mocks & assertions
├── test_erc20.py # ERC-20 allowance and balance mocks
├── test_identity.py # ERC-8004 Identity & Reputation mock tests
├── test_rwa.py # mETH yields and USDY wrap payload mock tests
├── test_server.py # Native balance, gas, network info, and server endpoints
└── test_tokens.py # Local registry and API fallback tests
```
---
## Prerequisites
Before setting up the project, ensure you have the following installed:
- **Python 3.10+** (tested and verified on Python 3.14)
- **Virtual Environment Tool** (`venv`)
- **MCP Host** (e.g., Claude Desktop, Cursor, Roo-Code, or any custom client)
---
## Installation & Setup
Follow these steps to set up the Mantle MCP server locally:
### 1. Navigate to Directory
```bash
cd /home/tmalone1250/KinetiFi_local/KinetiFi/mantle-mcp
```
### 2. Create and Activate Virtual Environment
```bash
python3 -m venv .venv
source .venv/bin/activate
```
### 3. Install Dependencies
```bash
pip install --upgrade pip
pip install -r requirements.txt
```
---
## Configuration
Environment variables are managed using a `.env` file in the project root. Create or update `.env` as follows:
```env
# Mantle Network MCP Server Environment Variables
# Leave blank to use the official public RPC endpoints, or override them below.
# Mainnet RPC Endpoint (Default: https://rpc.mantle.xyz)
MANTLE_RPC_URL=
# Sepolia Testnet RPC Endpoint (Default: https://rpc.sepolia.mantle.xyz)
MANTLE_SEPOLIA_RPC_URL=
```
### Fallback Network Constants
If the environment variables are left blank, the server automatically falls back to these defaults:
| Parameter | Mainnet | Testnet (Sepolia) |
| :--- | :--- | :--- |
| **RPC URL** | `https://rpc.mantle.xyz` | `https://rpc.sepolia.mantle.xyz` |
| **Block Explorer** | `https://explorer.mantle.xyz` | `https://explorer.sepolia.mantle.xyz` |
| **Chain ID** | `5000` | `5003` |
| **Native Currency** | `MNT` | `MNT` |
---
## Running the Server
### Development Mode (with Live Reload Dashboard)
```bash
fastmcp dev server.py
```
### Production Mode
Run the server to handle MCP JSON-RPC standard input/output streams:
```bash
python server.py
```
### Integrating with MCP Clients
To link `mantle-mcp` to your favorite LLM assistant client, register it under the custom MCP servers config file:
#### For Claude Desktop
Add this to your Claude Desktop configuration (typically at `~/.config/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"mantle-mcp": {
"command": "/home/tmalone1250/KinetiFi_local/KinetiFi/mantle-mcp/.venv/bin/python",
"args": [
"/home/tmalone1250/KinetiFi_local/KinetiFi/mantle-mcp/server.py"
],
"env": {
"MANTLE_RPC_URL": "https://rpc.mantle.xyz",
"MANTLE_SEPOLIA_RPC_URL": "https://rpc.sepolia.mantle.xyz"
}
}
}
}
```
---
## MCP Tool Reference
`mantle-mcp` exposes 19 native blockchain tools to clients:
### 1. `get_native_balance`
Retrieves the native MNT balance of an address on the Mantle Network.
- **Arguments:**
- `address` (string, required): The EVM address to query.
- `network` (string, optional): The network to query (`'testnet'` or `'mainnet'`). Defaults to `'testnet'`.
- **Response Format:**
`str` representing a human-readable balance (e.g., `"12.3450 MNT"`).
---
### 2. `get_erc20_balance`
Retrieves the ERC-20 token balance for a specific wallet address. Automatically resolves token symbols to addresses and formats the balance using the token's decimals.
- **Arguments:**
- `wallet_address` (string, required): The EVM wallet address to query.
- `token_symbol` (string, required): The token symbol (e.g., `'USDC'`, `'WETH'`, `'USDT'`).
- `network` (string, optional): The network to query (`'testnet'` or `'mainnet'`). Defaults to `'testnet'`.
- **Response Format:**
```json
{
"wallet": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"token": "USDC",
"balance": 150.5,
"network": "testnet"
}
```
---
### 3. `get_erc20_allowance`
Retrieves the ERC-20 token allowance granted by a wallet to a specific spender.
- **Arguments:**
- `wallet_address` (string, required): The EVM wallet address that owns the tokens.
- `spender_address` (string, required): The EVM address authorized to spend the tokens.
- `token_symbol` (string, required): The token symbol (e.g., `'USDC'`, `'WETH'`).
- `network` (string, optional): The network to query (`'testnet'` or `'mainnet'`). Defaults to `'testnet'`.
- **Response Format:**
```json
{
"wallet": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"spender": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"token": "USDC",
"allowance": 500.0,
"network": "testnet"
}
```
---
### 4. `get_swap_quote` (Uniswap V2)
Gets a swap quote (expected output) for a given trade pair on the FusionX DEX router using Uniswap V2 Router logic.
- **Arguments:**
- `sell_symbol` (string, required): The token symbol to sell (e.g., `'USDC'`).
- `buy_symbol` (string, required): The token symbol to buy (e.g., `'WETH'`).
- `amount_in` (float, required): The human-readable amount of `sell_symbol` to swap.
- `network` (string, optional): The network to query (`'testnet'` or `'mainnet'`). Defaults to `'testnet'`.
- **Response Format:**
```json
{
"sell_token": "USDC",
"buy_token": "WETH",
"amount_in": 100.0,
"expected_output": 0.05,
"network": "testnet"
}
```
---
### 5. `get_dex_quote` (Uniswap V3)
Gets a V3 swap quote (exact input) from specific DEXes like `merchant_moe` or `agni_finance` on Mantle.
- **Arguments:**
- `dex_name` (string, required): The DEX name to query (`'merchant_moe'` or `'agni_finance'`).
- `token_in` (string, required): EVM contract address of the incoming token.
- `token_out` (string, required): EVM contract address of the outgoing token.
- `amount_in_wei` (integer, required): The amount of input token, in raw wei.
- `fee_tier` (integer, optional): The pool fee tier (e.g., `3000` representing `0.30%`). Defaults to `3000`.
- `network` (string, optional): The network to query (`'mainnet'` or `'testnet'`). Defaults to `'mainnet'`.
- **Response Format:**
```json
{
"dex": "merchant_moe",
"amount_out_wei": 50000000000000000,
"estimated_gas_from_quoter": 150000,
"status": "success"
}
```
---
### 6. `estimate_l2_gas`
Estimates the gas units and total cost required to execute a transaction on Mantle L2.
- **Arguments:**
- `to_address` (string, required): The target EVM address of the recipient or contract.
- `data` (string, optional): The hex data payload of the transaction. Defaults to `'0x'`.
- `value_wei` (integer, optional): The native currency value to send, in wei. Defaults to `0`.
- `network` (string, optional): The network to query (`'testnet'` or `'mainnet'`). Defaults to `'testnet'`.
- **Response Format:**
```json
{
"success": true,
"network": "testnet",
"estimated_gas_units": 21000,
"gas_price_gwei": 1.0,
"estimated_cost_mnt": 0.000021,
"estimated_cost_wei": 21000000000000
}
```
---
### 7. `get_token_address`
Dynamically resolves a token symbol to its smart contract address on Mantle. If the token is not cached in the local registry, it falls back to querying the Blockscout explorer API.
- **Arguments:**
- `symbol` (string, required): The token symbol (e.g., `'USDC'`, `'WETH'`, `'WMNT'`).
- `network` (string, optional): The network to query (`'testnet'` or `'mainnet'`). Defaults to `'testnet'`.
- **Response Format:**
```json
{
"symbol": "USDC",
"address": "0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9",
"network": "mainnet",
"source": "local_registry"
}
```
---
### 8. `get_mantle_network_info`
Returns the network metadata and connection parameters (including connectivity check) for the requested Mantle Network.
- **Arguments:**
- `network` (string, optional): The network name to query (`'testnet'` or `'mainnet'`). Defaults to `'testnet'`.
- **Response Format:**
```json
{
"success": true,
"network": "testnet",
"chain_id": 5003,
"rpc_url": "https://rpc.sepolia.mantle.xyz",
"explorer_url": "https://explorer.sepolia.mantle.xyz",
"native_currency": "MNT",
"rpc_connection_active": true
}
```
---
### 9. `fetch_meth_yield`
Fetches the current mETH (Mantle Staked Ether) yield exchange rate from the on-chain contract.
- **Arguments:**
- `network` (string, optional): The network name to query (`'mainnet'` or `'testnet'`). Defaults to `'mainnet'`.
- **Response Format:**
```json
{
"asset": "mETH",
"exchange_rate_raw": 1052000000000000000,
"exchange_rate_formatted": 1.052,
"status": "success"
}
```
---
### 10. `prepare_usdy_wrap`
Generates an unsigned transaction payload to wrap USDC into Ondo USDY.
- **Arguments:**
- `amount_wei` (integer, required): The raw amount of USDC in wei to wrap.
- `usdy_address` (string, optional): The USDY target wrap contract address. Defaults to Ondo USDY Mainnet.
- `network` (string, optional): The network (`'mainnet'` or `'testnet'`). Defaults to `'mainnet'`.
- **Response Format:**
```json
{
"chainId": 5000,
"to": "0x5bE26527e817998A7206475496fDE1E68957c5A6",
"data": "0xwrap...",
"value": "0x0",
"readModel": {
"protocol": "Ondo USDY",
"method": "wrap(uint256)",
"params": [1000000]
}
}
```
---
### 11. `verify_erc8004_identity`
Checks the owner address of an ERC-8004 Agent Identity on the Mantle Network.
- **Arguments:**
- `identity_id` (integer, required): The ID of the agent identity NFT to query.
- `network` (string, optional): The network to query (`'mainnet'` or `'testnet'`). Defaults to `'mainnet'`.
- **Response Format:**
```json
{
"identity_id": 42,
"owner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"network": "mainnet",
"status": "registered"
}
```
---
### 12. `query_erc8004_reputation`
Queries an agent's on-chain trust reputation score on the Mantle Network.
- **Arguments:**
- `identity_id` (integer, required): The ID of the agent identity NFT to query.
- `network` (string, optional): The network to query (`'mainnet'` or `'testnet'`). Defaults to `'mainnet'`.
- **Response Format:**
```json
{
"identity_id": 42,
"score": 95,
"total_updates": 5,
"network": "mainnet"
}
```
---
### 13. `prepare_agent_registration`
Returns an unsigned payload to register and mint an ERC-8004 Identity NFT on the Mantle Network.
- **Arguments:**
- `owner_address` (string, required): The EVM address that will own the agent NFT.
- `metadata_uri` (string, required): The IPFS/HTTPS metadata link for the agent identity.
- `network` (string, optional): The network to query (`'mainnet'` or `'testnet'`). Defaults to `'mainnet'`.
- **Response Format:**
```json
{
"chainId": 5000,
"to": "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
"data": "0xregister...",
"value": "0x0",
"readModel": {
"protocol": "ERC-8004 Identity",
"method": "register(address,string)",
"params": ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "ipfs://QmMock"]
}
}
```
---
### 14. `generate_aave_supply_bundle`
Generates an unsigned transaction bundle to approve and supply an asset to Aave V3 on Mantle. For native MNT, it generates an auto-wrap-and-supply workflow (MNT -> WMNT -> Approve -> Supply).
- **Arguments:**
- `asset_symbol` (string, required): The token symbol (e.g. `'USDC'`, `'MNT'`).
- `amount` (float, required): The amount to supply.
- `wallet_address` (string, required): The user's address.
- `network` (string, optional): The network to query. Defaults to `'mainnet'`.
---
### 15. `scan_aave_yields`
Scans Aave V3 on Mantle for real-time asset supply APYs and returns the top opportunities.
- **Arguments:**
- `network` (string, optional): The target network. Defaults to `'mainnet'`.
---
### 16. `moe_zap_bundle`
Generates a single atomic transaction bundle calling the `MerchantMoeZapper` to wrap MNT, swap 50% for USDT, add liquidity to WMNT/USDT pool, and return the LP NFT plus any dust.
- **Arguments:**
- `mnt_amount` (float, required): Amount of native MNT to zap.
- `wallet_address` (string, required): User's address.
---
### 17. `get_rebalance_bundle`
Generates a transaction bundle to rebalance an uneven portfolio by executing a swap of a designated token to a target token on Merchant Moe or FusionX.
- **Arguments:**
- `token_to_sell` (string, required): Symbol of token to sell.
- `token_to_buy` (string, required): Symbol of token to buy.
- `amount_to_sell` (float, required): Amount of token to sell.
- `target_protocol` (string, required): Target exchange (`'merchant_moe'` or `'fusionx'`).
- `user_address` (string, required): The user's wallet address.
---
### 18. `get_arbitrage_bundle`
Generates a multi-hop, cross-DEX transaction bundle to exploit price discrepancies (e.g., swapping Token A to Token B on Agni, then swapping Token B back to Token A on Merchant Moe).
- **Arguments:**
- `token_path` (array of strings, required): Ordered list of token symbols forming the cycle (e.g., `["WMNT", "USDC", "WMNT"]`).
- `flash_amount` (float, required): The amount of the initial token to swap.
- `user_address` (string, required): The user's wallet address.
---
### 19. `get_autocompound_bundle`
Generates a multi-step transaction bundle to claim pending protocol rewards (from Lendle or Merchant Moe staking) and zap them back into the principal LP position.
- **Arguments:**
- `protocol` (string, required): Target protocol (`'lendle'` or `'merchant_moe'`).
- `pool_address` (string, required): Address of the staking/reward contract.
- `user_address` (string, required): The user's wallet address.
---
## Token Registry Details
The server includes a built-in fast local registry for common assets. If a token is queried that does not exist in the local registry, the server issues an asynchronous HTTP query to the Blockscout Explorer Search API to resolve the address dynamically.
### Local Registry Addresses
#### Mainnet
- **MNT:** `native`
- **WMNT:** `0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8`
- **WETH:** `0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111`
- **USDC:** `0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9`
- **USDT:** `0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE`
#### Testnet (Sepolia)
- **MNT:** `native`
- **WMNT:** `0x1404c04fE52478546D869Ff94119DF37eAA6e1c4`
- **WETH:** `0x7383D62D50E7dF82c6114dDF603952a2DE549B8a`
- **USDC:** `0x2D4a161f36402E8d4234baC5aC6f12e873aC1A62`
- **USDT:** `0xC216f40A3Ceb03F4f03936F76E296e8346cbDE6e`
---
## Testing
The project has a 100% mocked, deterministic test suite, meaning **you can run all tests offline without needing live RPC access or internet connectivity**.
Run all tests using the virtual environment `pytest` executable:
```bash
.venv/bin/pytest -v
```
---
## Security & Architectural Standards
1. **Explicit Type Hints:** Every function signature specifies types for input parameters and return shapes.
2. **Robust Error Handling:** System calls catch RPC connection failures, contract reverts, and invalid address validation errors, returning structured error messages rather than crashing.
3. **Zero State Modification:** The MCP server tools are read-only (`view` and gas estimation). They do not store private keys, hold funds, or initiate state-changing transactions directly, rendering the server highly secure.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues