A complete platform for AI agents to interact with the Lido liquid staking protocol. Stake ETH, manage withdrawals, wrap/unwrap stETH, and vote on governance — all from natural language.
Source code: github.com/daiwikmh/moly
Start with the CLI. Use other methods when needed.
| What | Best for | |
|---|---|---|
| CLI Package | npx @moly-mcp/lido — interactive terminal with setup wizard, ledger, alerts, bounds |
Primary: local automation, terminals, AI client integration, full control |
| MCP Server | Bun-based stdio server (17 tools) | Custom agent setups, embedded systems, programmatic access |
| Dashboard | Next.js web UI with MCP-over-HTTP | Web browsers, non-technical users, real-time monitoring |
The dashboard serves as both a web application and an MCP server simultaneously:
- Web Chat (
/api/chat) — Users interact with Lido through a conversational AI powered by OpenRouter - MCP Endpoint (
/api/mcp) — External AI agents (Claude Desktop, Cursor, etc.) connect to the same 17 Lido tools via the Model Context Protocol over HTTP - Shared Backend — Both interfaces use the identical tool functions in
lib/lido.ts, so behavior is always consistent - Header-based Config — The MCP endpoint reads
x-lido-mode,x-lido-network, andx-lido-chainheaders to configure per-request behavior - Discovery —
GET /api/mcpreturns a JSON manifest listing all 17 tools, configuration options, and a quickstart guide
This means a developer can point Claude Desktop at the running dashboard AND use the web UI at the same time — both hit the same Lido tools.
Mode and Network are fully independent — you can simulate on mainnet or go live on testnet:
| Toggle | Options | What it controls |
|---|---|---|
| Mode | Simulation / Live | Simulation = all writes are dry-run. Live = real transactions (MCP server with private key only) |
| Network | Hoodi Testnet / Ethereum Mainnet | Which chain to connect to. RPC, contract addresses, and chain ID switch automatically |
- Visual indicators: pulsing yellow dot for testnet, green for mainnet
- Config changes mid-conversation inject a system message so the AI knows the context shifted
- Both toggles persist across chat messages
Built-in interactive chat REPL for staking directly from your terminal:
- AI-powered — connects to OpenRouter, Claude, or Gemini for natural language interaction
- All tools available — stake, unstake, wrap, govern, bridge, monitor, bounds without leaving the terminal
- Activity ledger — write operations auto-logged to SQLite (
~/.moly/ledger.db) with full query and export - Skill context —
lido.skill.mdloaded into the system prompt so the AI understands Lido mechanics - No markdown — clean plaintext output designed for terminal readability
The agent autonomously monitors and manages a staking position within human-set bounds:
- Policy bounds — configurable limits: max stake per tx, daily stake cap, min ETH reserve for gas, governance auto-vote. Stored at
~/.moly/bounds.json. All write operations are gated by bounds enforcement before execution. - Position monitor — background daemon polls every 30s for balance thresholds, reward rate changes, reward deltas, withdrawal readiness, new proposals, and governance vote expiry. Sends alerts via Telegram or webhook.
- Cross-chain aggregation — unified ETH-equivalent position across Ethereum mainnet + Base + Arbitrum in a single tool call
- Activity ledger — SQLite audit trail of every tool execution with queryable filters (by tool, date range) and CSV/JSON export
Built-in support for the Open Wallet Standard as a secure key backend:
- Encrypted vault — private keys stored in
~/.ows/wallets/with AES-256-GCM encryption at rest - Zero key exposure — keys decrypted only at signing time, never visible to agents or LLMs
- Multi-wallet — named wallets, pick which one to use during setup
- Fallback — raw private key (chmod 600) still supported for quick setups
- Optional dependency — OWS is not required, install only if you want encrypted key storage
/skill — Mental model and operational guidelines for AI agents:
- Complete Lido mechanics reference
- All 28 tools with parameters and examples
- Safe agent patterns and common workflows
- Raw markdown at
/api/skillfor agent integration - Discoverable by any MCP client or agent
19+ pages of docs served at /docs with:
- 7 sections: Getting Started, MCP Server, Dashboard, Tools Reference, Guides, Reference, CLI Package
- Code blocks with copy-to-clipboard button (appears on hover)
- Responsive sidebar navigation with current page highlighting
- Prev/Next page navigation
- Callout boxes (info, warning, tip)
- Code samples for Anthropic API, Vercel AI SDK, and MCP SDK TypeScript
The primary and fastest way to use Moly. Full-featured terminal interface with everything you need: interactive setup wizard, activity ledger, alert management, policy bounds, and cross-chain position monitoring. Works with any AI client (Claude Desktop, Cursor, Windsurf, or custom MCP setups).
npx @moly-mcp/lidoWhy start here:
- Zero setup — wizard handles everything
- Full control — bounds, alerts, ledger, all from CLI
- Activity tracking — every operation logged to SQLite
- Monitor daemon — 30s polling for alerts via Telegram/webhook
- Works offline — all config stored locally (
~/.moly/)
The wizard asks for:
- Network — Hoodi Testnet or Ethereum Mainnet
- Custom RPC — optional, defaults to public RPCs
- Mode — Simulation (dry-run) or Live (real transactions)
- Key source — OWS Wallet (encrypted via Open Wallet Standard), raw private key (chmod 600), or skip
- AI Provider — Claude, Gemini, or OpenRouter with model selection
| Command | Description |
|---|---|
npx @moly-mcp/lido |
First run: wizard then server. After: server directly |
moly setup |
Re-run the full setup wizard |
moly config |
Print current config (keys redacted) |
moly reset |
Delete config and start fresh |
moly position [address] |
Cross-chain position summary (ETH + Base + Arbitrum) |
moly monitor start|status|stop |
Manage the alert monitoring daemon |
moly bounds [show|set|reset] |
View or update policy bounds |
moly ledger list|stats|export |
Query or export the activity ledger |
moly alert add|list|remove |
Manage alert rules |
npx @moly-mcp/lido --server |
Force-start MCP server (use in AI client configs) |
moly bounds set --max-stake-per-tx 1.0 --max-daily-stake 10 --min-eth-reserve 0.5 --governance-auto-vote falsemoly ledger list --tool stake_eth --since 2025-01-01 --limit 20
moly ledger stats --since 2025-01-01
moly ledger export --format csvAdd to your MCP client config (Claude Desktop, Cursor, Windsurf):
{
"mcpServers": {
"moly": { "command": "npx", "args": ["@moly-mcp/lido", "--server"] }
}
}Source:
cli/—bin.ts,wizard.ts,server/index.ts,tools/
If the CLI doesn't fit your setup, use this standalone Bun-based server. Reads config from environment variables, suitable for embedding in custom agent workflows.
cd mcp
cp .env.example .env
# Set PRIVATE_KEY, LIDO_MODE (simulation|live)
bun install && bun run dev{
"mcpServers": {
"lido": {
"command": "bun",
"args": ["run", "/path/to/moly/mcp/src/index.ts"],
"env": {
"LIDO_MODE": "simulation",
"PRIVATE_KEY": "0x..."
}
}
}
}Prefer a web browser? This Next.js app provides an agentic chat interface with real-time protocol data and simulation support. Serves as both a chat interface and an MCP-over-HTTP endpoint (/api/mcp) for external agents.
cp .env.example .env.local
# Add OPENROUTER_API_KEY
bun install && bun run devAll packages expose the same Lido toolset. The CLI adds settings, bounds, ledger, position, bridge, and alert tools.
| Tool | Description | Source |
|---|---|---|
get_balance |
ETH, stETH, wstETH balances for any address | balance.ts |
get_rewards |
Staking reward history over N days | balance.ts |
get_conversion_rate |
Current stETH / wstETH exchange rate | wrap.ts |
get_withdrawal_requests |
Pending withdrawal NFT IDs for an address | unstake.ts |
get_withdrawal_status |
Check finalization status per request ID | unstake.ts |
get_proposals |
List recent Lido DAO governance proposals | governance.ts |
get_proposal |
Detailed info on a specific proposal | governance.ts |
get_total_position |
Cross-chain position: ETH + stETH + wstETH across mainnet, Base, Arbitrum | position.ts |
get_bounds |
Current policy bounds (max stake, daily limit, gas reserve) | bounds/store.ts |
get_trade_history |
Query the activity ledger with filters (tool, date, limit) | ledger/store.ts |
get_staking_summary |
Aggregate stats: total operations, staked ETH, errors | ledger/store.ts |
get_settings |
Current mode, network, RPC (keys redacted) | settings.ts |
| Tool | Description | Source |
|---|---|---|
stake_eth |
Stake ETH to receive stETH (liquid staking) | stake.ts |
request_withdrawal |
Enter the Lido withdrawal queue (ERC-721 NFT) | unstake.ts |
claim_withdrawals |
Claim finalized withdrawals back to ETH | unstake.ts |
wrap_steth |
Wrap stETH into wstETH (non-rebasing) | wrap.ts |
unwrap_wsteth |
Unwrap wstETH back to rebasing stETH | wrap.ts |
cast_vote |
Vote YEA/NAY on Lido DAO proposal (needs LDO) | governance.ts |
set_bounds |
Update policy bounds that gate write operations | bounds/store.ts |
update_settings |
Change mode/network/RPC mid-conversation | settings.ts |
| Tool | Description | Source |
|---|---|---|
get_l2_balance |
ETH and wstETH balances on Base or Arbitrum. Use before bridging to check funds | bridge.ts |
get_bridge_quote |
Quote for bridging ETH or wstETH from L2 to Ethereum L1. Requires configured wallet | bridge.ts |
bridge_to_ethereum |
Bridge ETH or wstETH from Base/Arbitrum to L1. Requires private key. Dry-run in simulation | bridge.ts |
get_bridge_status |
Check status of an in-progress bridge tx. Use the hash from bridge_to_ethereum | bridge.ts |
| Tool | Description | Source |
|---|---|---|
set_alert |
Create alert (balance, reward rate, withdrawal, proposal, conversion rate, reward delta, governance expiry) | alerts.ts |
list_alerts |
List all configured alerts | alerts.ts |
remove_alert |
Remove an alert by ID | alerts.ts |
configure_alert_channels |
Set Telegram bot token/chat ID or webhook URL | alerts.ts |
In simulation mode, dry_run defaults to true — nothing is ever broadcast unless you explicitly switch to live. All write tools are gated by policy bounds before execution.
| Network | Chain ID | stETH | wstETH | Voting |
|---|---|---|---|---|
| Hoodi Testnet | 560048 | 0x3508A952176b3c15387C97BE809eaffB1982176a |
0x7E99eE3C66636DE415D2d7C880938F2f40f94De4 |
0x49B3512c44891bef83F8967d075121Bd1b07a01B |
| Ethereum Mainnet | 1 | 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84 |
0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0 |
0x2e59A20f205bB85a89C53f1936454680651E618e |
Holesky is deprecated. Use Hoodi for all testnet operations.
flowchart TD
A[AI Agent\nOpenRouter / Claude / Cursor] -->|MCP / stdio| B[Moly MCP Server\n28 Lido tools]
B --> BA{checkBounds}
BA -->|blocked| BB[Reject with reason]
BA -->|allowed| C{resolveAccount}
C -->|encrypted| D[OWS Vault\n~/.ows/ AES-256-GCM]
C -->|plaintext| E[Raw Key\n~/.moly/ chmod 600]
D --> F[viem Account]
E --> F
F --> G[Lido SDK]
G -->|stake / unstake / wrap / govern| H[Ethereum RPC\nMainnet / Hoodi]
G --> I[Activity Ledger\n~/.moly/ledger.db]
J[Monitor Daemon\n30s polling] -->|alerts| K[Telegram / Webhook]
- OWS integration — keys can be stored in an encrypted Open Wallet Standard vault (
~/.ows/wallets/). AES-256-GCM encryption at rest, decrypted only at signing time. Install OWS:curl -fsSL https://openwallet.sh/install.sh | bash - Raw key fallback — alternatively, private keys are stored locally in
~/.moly/config.json(chmod 600) or passed via env var. Never transmitted to any remote server. - API keys stored alongside config. Never logged, never printed.
- Simulation mode (default) is always dry-run — nothing broadcast unless you explicitly set it to false and switch to live.
update_settingsMCP tool intentionally cannot change private keys or API keys — only viamoly setup.- Policy bounds — write operations are gated by human-set limits before any transaction is broadcast.
- Activity ledger — every tool call is logged to
~/.moly/ledger.db(SQLite, WAL mode) for auditability. - Dashboard never holds private keys — all write operations from the web UI are simulations only.
| File | Purpose |
|---|---|
config.json |
Network, mode, RPC, wallet, AI provider (chmod 600) |
bounds.json |
Policy bounds: max stake, daily cap, gas reserve, governance |
alerts.json |
Alert rules, daemon state, channel config |
ledger.db |
SQLite activity ledger (all tool executions) |
| Component | Stack |
|---|---|
CLI (@moly-mcp/lido) |
TypeScript, tsup, @clack/prompts, @modelcontextprotocol/sdk, better-sqlite3, @open-wallet-standard/core (optional) |
| MCP Server | Bun, TypeScript, @lidofinance/lido-ethereum-sdk, viem |
| Dashboard | Next.js 16, Tailwind CSS, Vercel AI SDK v6, OpenRouter |
| On-chain | Lido stETH/wstETH, Aragon Voting, Ethereum Mainnet + Hoodi Testnet |