Metadata-Version: 2.4
Name: mcp-beehive
Version: 0.1.1
Summary: MCP server for managing hundreds of EOA accounts via HD wallet derivation
Requires-Python: >=3.12
Requires-Dist: fastmcp>=2.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: web3>=7.0
Description-Content-Type: text/markdown

# mcp-beehive

An MCP server for managing hundreds of Ethereum EOA wallets derived from a single BIP44 HD seed. Exposes wallet operations — ETH transfers, ERC20 transfers, arbitrary contract calls — as MCP tools over HTTP. Wallet addresses and balances are cached in a local SQLite database.

## How wallets are named

Each wallet maps to a BIP44 derivation path index:

```
wallet-0042  →  index 42  →  m/44'/60'/0'/0/42
```

Names are zero-padded to four digits. Any tool that accepts a `wallet_name` also accepts a bare integer (`"42"`) or an unpadded name (`"wallet-42"`).

## Quickstart (recommended)

No install required — run directly from PyPI with `uvx`:

```json
{
  "mcpServers": {
    "beehive": {
      "command": "uvx",
      "args": ["mcp-beehive"],
      "env": {
        "MNEMONIC": "your twelve word seed phrase here",
        "RPC_URL": "https://mainnet.infura.io/v3/YOUR_KEY"
      }
    }
  }
}
```

Add this to:
- **Claude Desktop**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Claude Code**: `.claude/settings.json` in your project or `~/.claude/settings.json` globally

## Requirements

- Python 3.12+
- [uv](https://docs.astral.sh/uv/)

## Configuration

All configuration is via environment variables:

| Variable    | Required          | Default                    | Description                        |
|-------------|-------------------|----------------------------|------------------------------------|
| `MNEMONIC`  | Yes (for signing) | —                          | BIP39 mnemonic phrase              |
| `RPC_URL`   | No                | `https://eth.llamarpc.com` | Default JSON-RPC endpoint          |
| `DB_PATH`   | No                | `beehive.db`               | SQLite cache file path             |
| `TRANSPORT` | No                | `stdio`                    | `stdio` or `http`                  |
| `HOST`      | No                | `0.0.0.0`                  | HTTP bind address (http mode only) |
| `PORT`      | No                | `8000`                     | HTTP port (http mode only)         |

> **Security:** keep your mnemonic in a secrets manager or `.env` file that is never committed. The server never returns or logs the mnemonic.

## HTTP mode (self-hosted / shared)

To run as a persistent HTTP server instead:

```bash
TRANSPORT=http \
MNEMONIC="your twelve word seed phrase here" \
RPC_URL="https://mainnet.infura.io/v3/YOUR_KEY" \
uvx mcp-beehive
```

The MCP endpoint is available at `http://localhost:8000/mcp`.

Connect Claude to it:

```json
{
  "mcpServers": {
    "beehive": {
      "type": "http",
      "url": "http://localhost:8000/mcp"
    }
  }
}
```

## Development install

```bash
git clone https://github.com/layer-3/mcp-beehive
cd mcp-beehive
uv sync
MNEMONIC="..." uv run python main.py
```

## Tools

### Wallet management

| Tool | Parameters | Description |
|------|-----------|-------------|
| `list_wallets` | `start=0`, `count=10` | List wallet names and addresses. Max 100 per call. |
| `get_wallet` | `wallet_name` | Address and all cached balances for one wallet. |

### Balances

| Tool | Parameters | Description |
|------|-----------|-------------|
| `get_eth_balance` | `wallet_name`, `rpc_url?`, `use_cache?` | ETH balance. Pass `use_cache=true` to skip an RPC call. |
| `refresh_eth_balances` | `wallet_names[]`, `rpc_url?` | Batch-refresh ETH balances for a list of wallets. |
| `get_erc20_balance` | `wallet_name`, `token_address`, `rpc_url?` | ERC20 balance (fetches decimals and symbol automatically). |

### Transactions

| Tool | Parameters | Description |
|------|-----------|-------------|
| `send_eth` | `from_wallet`, `to_address`, `amount_eth`, `rpc_url?`, fee params | Send ETH. |
| `send_erc20` | `from_wallet`, `token_address`, `to_address`, `amount`, `decimals?`, `rpc_url?`, fee params | Send ERC20 tokens. Human-readable amount (e.g. `"100.5"` for 100.5 USDC). |
| `send_transaction` | `from_wallet`, `to_address`, `data?`, `value_eth?`, `gas?`, `rpc_url?`, fee params | Arbitrary contract call or deployment. |
| `get_transaction_status` | `tx_hash`, `rpc_url?` | Check if a transaction is pending, confirmed, or failed. Updates the local cache. |
| `list_transactions` | `wallet_name?`, `limit=20` | Recent transactions from the local SQLite cache. |

### Utilities

| Tool | Parameters | Description |
|------|-----------|-------------|
| `get_nonce` | `wallet_name`, `rpc_url?` | Confirmed and pending nonce for a wallet. |
| `estimate_gas` | `from_wallet`, `to_address`, `data?`, `value_eth?`, `rpc_url?` | Gas estimate and cost in ETH. |

### Gas fee parameters

`send_eth`, `send_erc20`, and `send_transaction` all accept optional fee overrides:

| Parameter | Description |
|-----------|-------------|
| `max_fee_gwei` | EIP-1559 max fee per gas (Gwei) |
| `priority_fee_gwei` | EIP-1559 miner tip (Gwei). Default: `1` |
| `gas_price_gwei` | Legacy gas price (Gwei). Use on non-EIP-1559 chains. Takes priority over EIP-1559 params. |

If no fee params are provided the server auto-detects the chain type and sets fees from the latest block.

## Usage examples

### Derive the first 10 wallets

```
list_wallets(start=0, count=10)
```

### Check a balance

```
get_eth_balance("wallet-0042")
get_erc20_balance("wallet-0042", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")  # USDC
```

### Send ETH

```
send_eth(
  from_wallet="wallet-0042",
  to_address="0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
  amount_eth="0.1"
)
```

### Send ERC20 (USDC)

```
send_erc20(
  from_wallet="wallet-0042",
  token_address="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  to_address="0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
  amount="50"
)
```

### Call a contract

```
send_transaction(
  from_wallet="wallet-0000",
  to_address="0xContractAddress",
  data="0xa9059cbb...",
  value_eth="0"
)
```

### Check transaction status

```
get_transaction_status("0xabc123...")
```

## Multi-chain usage

Pass `rpc_url` to any tool to target a different chain. The server detects EIP-1559 support automatically.

```
send_eth(
  from_wallet="wallet-0000",
  to_address="0x...",
  amount_eth="0.01",
  rpc_url="https://polygon-rpc.com"
)
```

## SQLite cache

Beehive keeps a local `beehive.db` (path configurable via `DB_PATH`) with three tables:

- **`wallets`** — derived addresses and cached ETH balances
- **`erc20_balances`** — per-wallet ERC20 balances with symbol and decimals
- **`transactions`** — submitted transactions and their status

The cache is write-through: balances are updated on every live fetch and transaction status is updated whenever `get_transaction_status` is called. Cached values are never used for signing — nonces are always fetched fresh from the chain.

## Development

```bash
uv sync --group dev
uv run pytest
```

Tests run entirely offline. Unit tests use an in-memory SQLite database; integration tests inject a mock Web3 instance so no RPC calls are made.

## Project structure

```
beehive/
├── config.py          # env vars, ERC20 ABI
├── wallet.py          # pure BIP44 derivation (no I/O)
├── db.py              # SQLite CRUD (connection injected)
├── chain.py           # Web3 helpers (Web3 instance injected)
├── server.py          # FastMCP instance
└── tools/
    ├── wallets.py
    ├── balances.py
    ├── transactions.py
    └── utils.py
tests/
├── conftest.py                    # per-test isolated SQLite
├── unit/                          # wallet, db, chain — no network
└── integration/                   # tool functions with mocked RPC
main.py                            # entry point
```

## License

MIT
