Skip to main content
Glama
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.