lucid-defi-mcp
v0.1.0
Published
MCP server exposing Lucid's DeFi portfolio analysis (Zerion + DeFiLlama + Aave) as tools. The host's model writes the prose; the risk engine computes every number.
Maintainers
Readme
lucid-defi-mcp
An MCP server that exposes Lucid's DeFi portfolio analysis as tools any MCP host (Claude Desktop, Claude Code, Cursor) can call.
The deterministic risk engine computes every number (health factors, IL, APYs,
concentration) with decimal.js and returns them as strings; the host's own model writes the
prose. There is no API key to manage — the host already has the model. This is the same
core (lib/defi/*) the web app uses, with no BYOK/auth/database layer.
Tools
| Tool | Input | Returns |
|---|---|---|
| analyze_portfolio | address | Full assessment: value, positions, health factors, concentration, IL, idle assets, rate arbitrage, overall risk |
| get_positions | address | Normalized positions only (Zerion; cheap, no on-chain/yield lookups) |
| get_suggestions | address | Prioritized opportunities (liquidation, concentration, idle, rate arbitrage) |
| get_health_factors | address | Aave V3 / Compound V3 health factors (needs RPC; degrades gracefully) |
| compare_yields | symbol, currentProtocol? | Best / current-vs-best yield via DeFiLlama (no key) |
Every result includes a disclaimer: findings are opportunities detected, not financial advice.
How it works
you ──prompt──► MCP host (Claude Desktop) ──tools/call──► lucid-defi-mcp ──► Zerion / DeFiLlama / Aave
▲ has the model │ has the tools
└──────── JSON (numbers as strings) ──────┘
│
model writes the report ──► you- Spawn — the host launches
lucid-defi-mcpas a child process (per your config) and pipes newline-delimited JSON-RPC over stdio (no HTTP, no port). - Handshake — host sends
initialize; server replies name/version. - Discovery — host sends
tools/list; server returns the 5 tools with descriptions + zod input schemas, so the model knows what's available. - Call — you ask a question; the model picks a tool and fills its arguments, host sends
tools/call. - Execute — the handler runs
lib/defi/*(Zerion → risk engine, alldecimal.js), serializes Decimals → strings, returns{ content: [JSON, disclaimer] }. Wrapped in a guard so it never throws out of the server. - Prose — the host feeds that JSON back to its own model, which writes the answer. The server never calls an LLM — it only computes numbers.
This split (server = numbers, host model = words) is enforced by the protocol — the same principle the web app implements by hand.
Environment
| Var | Required | For |
|---|---|---|
| ZERION_API_KEY | ✅ for wallet tools | positions / analyze / suggestions |
| ETHEREUM_RPC_URL | optional | health factors (Aave/Compound). Absent → those are skipped with a note |
Missing ZERION_API_KEY returns a clear tool error; the server stays up.
compare_yields needs no keys.
Use it
Claude Desktop
Add to claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"lucid": {
"command": "npx",
"args": ["-y", "lucid-defi-mcp"],
"env": {
"ZERION_API_KEY": "your_zerion_key",
"ETHEREUM_RPC_URL": "https://eth-mainnet.g.alchemy.com/v2/your_key"
}
}
}
}Restart Claude Desktop, then ask: "Analyze the DeFi positions for 0xd8dA…6045."
Claude Code
claude mcp add lucid \
--env ZERION_API_KEY=your_zerion_key \
--env ETHEREUM_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/your_key \
-- npx -y lucid-defi-mcpExample usage
You: "I'm staking ETH on Lido — am I leaving yield on the table?"
The model picks compare_yields { symbol: "ETH", currentProtocol: "lido" }. The server returns
(numbers as strings — pre-computed, the model never recomputes):
{ "currentProtocol": "lido", "currentApy": "2.358",
"bestProtocol": "uniswap-v2", "bestApy": "176.7081", "differentialBps": "17435.01" }The host's model then writes: "Your Lido staking earns ~2.36% APY. The top ETH pool is ~176.7% on Uniswap V2 — ~17,435 bps higher — but that's volatile LP fees with far higher impermanent-loss and contract risk. Opportunity detected, not a recommendation."
For a wallet, ask "Analyze the DeFi positions for 0x…" → the model calls analyze_portfolio,
and may chain follow-ups (get_health_factors, compare_yields on an idle asset) in the same
turn, deciding each step from the returned JSON.
Testing
No host required — drive the server directly over stdio.
1. Build:
pnpm install
pnpm --filter lucid-defi-mcp build2. List the tools (no keys needed):
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
| node mcp/dist/index.jsExpect a JSON-RPC reply listing all 5 tools.
3. Call a keyless tool — compare_yields:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"compare_yields","arguments":{"symbol":"USDC"}}}' \
| node mcp/dist/index.jsExpect live DeFiLlama data + the disclaimer block.
4. Call a wallet tool (needs a key):
ZERION_API_KEY=your_key node -e '...' # or just use the Inspector below5. Inspector (recommended GUI):
ZERION_API_KEY=your_key npx @modelcontextprotocol/inspector node mcp/dist/index.jsOpens a browser UI — list tools, fill arguments, see raw results. Try analyze_portfolio with
a real address (e.g. 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045).
6. Real host: add the config from Use it, restart the host, and ask it to analyze a wallet.
Degradation checks: unset ZERION_API_KEY → wallet tools return a friendly error (server
stays up); unset ETHEREUM_RPC_URL → get_health_factors returns a note, analyze_portfolio
still works without health factors.
Develop
From the repo root (pnpm workspace):
pnpm install
pnpm --filter lucid-defi-mcp dev # run from source (tsx)
pnpm --filter lucid-defi-mcp build # bundle → dist/index.js (tsup, with shebang)
pnpm --filter lucid-defi-mcp typecheck # tsc --noEmitInspect with the official tool:
ZERION_API_KEY=... npx @modelcontextprotocol/inspector node mcp/dist/index.jsPublish
pnpm --filter lucid-defi-mcp build
cd mcp && npm publishbin maps lucid-defi-mcp → dist/index.js, so npx lucid-defi-mcp works after publish.
A .mcpb (Desktop Extension) bundle is a possible follow-up for one-click install.
How it relates to the web app
lucid-defi-mcp reuses lib/defi/* (Zerion, DeFiLlama, Aave/Compound, risk engine, suggestions)
directly — bundled by tsup via the @/* path alias. The Next.js web app is untouched; both
consume the same analysis core.
Disclaimer
Informational only. Not financial advice. Always do your own research.
