npm package: @lumiapassport/mcp
Description: MCP server exposing Lumia Passport SDK capabilities as tools for AI agents
Author: Lumia
Latest version: 1.0.0

# @lumiapassport/mcp

MCP (Model Context Protocol) server that exposes Lumia Passport SDK capabilities as tools for AI agents.

## Features

- ✅ **7 blockchain tools** - Wallet info, balances, transfers, contract reads, transaction status, chain management
- ✅ **Multi-chain support** - Switch between Lumia, Ethereum Sepolia, BSC Testnet, Arbitrum Sepolia, Base Sepolia
- ✅ **Auto wallet creation** - Wallet is created automatically on first use via MPC/TSS protocol
- ✅ **ERC20 support** - Native and token balances/transfers out of the box
- ✅ **Stdio transport** - Works with Claude Code, Claude Desktop, and any MCP-compatible client
- ✅ **Programmatic API** - Use as a library in your own Node.js applications

## Installation

```bash
pnpm add @lumiapassport/mcp viem dkls23-wasm
# or
npm install @lumiapassport/mcp viem dkls23-wasm
```

## Quick Start

### With Claude Code (CLI)

```bash
claude mcp add --transport stdio \
  -e LUMIA_PASSPORT_API_KEY=lp_your_api_key \
  -e LUMIA_PASSPORT_WALLET_ID=my-agent-wallet \
  -e LUMIA_PASSPORT_CHAIN_ID=2030232745 \
  lumia-passport -- npx @lumiapassport/mcp
```

Then ask Claude: *"What's my wallet address?"* or *"Send 0.1 LUMIA to 0x..."*

Verify it's registered:

```bash
claude mcp list
```

### With Claude Code (JSON config)

Add to your project `.mcp.json`:

```json
{
  "mcpServers": {
    "lumia-passport": {
      "command": "npx",
      "args": ["@lumiapassport/mcp"],
      "env": {
        "LUMIA_PASSPORT_API_KEY": "lp_your_api_key",
        "LUMIA_PASSPORT_WALLET_ID": "my-agent-wallet",
        "LUMIA_PASSPORT_CHAIN_ID": "2030232745"
      }
    }
  }
}
```

### With Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):

```json
{
  "mcpServers": {
    "lumia-passport": {
      "command": "npx",
      "args": ["@lumiapassport/mcp"],
      "env": {
        "LUMIA_PASSPORT_API_KEY": "lp_your_api_key",
        "LUMIA_PASSPORT_WALLET_ID": "my-agent-wallet"
      }
    }
  }
}
```

### Programmatic Usage

```typescript
import { createMcpServer, startMcpServer, resolveConfig } from '@lumiapassport/mcp';

// Option 1: Start with stdio transport (for MCP clients)
await startMcpServer();

// Option 2: Create server with custom config
const server = await createMcpServer({
  apiKey: 'lp_...',
  walletId: 'my-wallet',
  chainId: 2030232745,
  keyshareDir: './data/keyshares',
  debug: false,
});
```

## Configuration

All configuration is via environment variables:

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `LUMIA_PASSPORT_API_KEY` | Yes | - | Project API key (`lp_...`) from [dashboard.lumiapassport.com](https://dashboard.lumiapassport.com) |
| `LUMIA_PASSPORT_WALLET_ID` | Yes | - | Unique identifier for the server wallet |
| `LUMIA_PASSPORT_CHAIN_ID` | No | `2030232745` | Default chain (Lumia Beam testnet) |
| `LUMIA_PASSPORT_KEYSHARE_DIR` | No | `./data/keyshares` | Directory for encrypted keyshare storage |
| `LUMIA_PASSPORT_KEYSHARE_PASSWORD` | No | - | Encryption password. If omitted, uses in-memory storage (keyshares lost on restart) |
| `LUMIA_PASSPORT_DEBUG` | No | `false` | Enable debug logging to stderr |

> **Note:** For production use, always set `LUMIA_PASSPORT_KEYSHARE_PASSWORD` to persist keyshares to disk. Without it, the wallet will need to re-run the DKG protocol on every restart.

## Tools

### `get_wallet_info`

Get wallet addresses and active chain info.

```
Input: (none)
Output: { walletId, smartAccountAddress, ownerAddress, chain: { id, name, nativeCurrency, blockExplorerUrl } }
```

### `get_balance`

Check native or ERC20 token balance.

```
Input:  { address?: string, tokenAddress?: string }
Output: { address, balance, formatted, symbol, decimals, chain }
```

- Omit `address` to use the wallet's smart account
- Omit `tokenAddress` for native balance, provide it for ERC20

### `transfer`

Send native tokens or ERC20 tokens. Waits for on-chain confirmation.

```
Input:  { to: string, amount: string, tokenAddress?: string }
Output: { userOpHash, transactionHash, blockNumber, success, gasUsed, chain }
```

- `amount` is human-readable (e.g. `"1.5"`, not wei)
- Omit `tokenAddress` for native transfer

### `read_contract`

Call any view/pure function on a smart contract.

```
Input:  { address: string, abi: AbiItem[], functionName: string, args?: any[] }
Output: { result, chain }
```

### `get_transaction_status`

Check the status of a previously submitted user operation.

```
Input:  { userOpHash: string }
Output: { status: 'confirmed'|'pending'|'failed', transactionHash?, blockNumber?, success?, gasUsed? }
```

### `list_supported_chains`

List all supported blockchain networks.

```
Input: (none)
Output: { chains: [{ id, name, nativeCurrency, blockExplorerUrl, isActive }], activeChainId }
```

### `switch_chain`

Switch the active blockchain network for subsequent operations.

```
Input:  { chainId: number }
Output: { previousChainId, activeChain: { id, name, nativeCurrency, blockExplorerUrl } }
```

## Supported Chains

| Chain | ID | Type |
|-------|----|------|
| Lumia Prism | `994873017` | Mainnet |
| Lumia Beam | `2030232745` | Testnet (default) |
| Ethereum Sepolia | `11155111` | Testnet |
| BSC Testnet | `97` | Testnet |
| Arbitrum Sepolia | `421614` | Testnet |
| Base Sepolia | `84532` | Testnet |

## Testing

### With MCP Inspector

The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is the official GUI tool for testing MCP servers:

```bash
npx @modelcontextprotocol/inspector node packages/mcp/dist/bin.js
```

Set the environment variables in the inspector UI, then call tools interactively.

### Smoke Test

Run the built-in smoke test to verify tools are registered correctly:

```bash
node packages/mcp/test/smoke.mjs
```

## Architecture

```
Agent (Claude Code / Claude Desktop)
  │ stdio (JSON-RPC)
  ▼
MCP Server (this package)
  │
  ├── ChainManager (lazy pool)
  │   ├── ServerWalletManager per chain
  │   ├── PublicReadClient per chain
  │   └── Shared KeyshareStorage
  │
  └── Tools
      ├── get_wallet_info
      ├── get_balance
      ├── transfer
      ├── read_contract
      ├── get_transaction_status
      ├── list_supported_chains
      └── switch_chain
```

## License

MIT