Metadata-Version: 2.4
Name: 0xdegenmo-lighter-mcp
Version: 0.1.1
Summary: MCP server for Lighter DEX — trade perp futures from any MCP client (Claude Desktop, Cursor, Hermes, ...).
Project-URL: Homepage, https://github.com/0xDegenMo/lighter-mcp
Project-URL: Repository, https://github.com/0xDegenMo/lighter-mcp
Project-URL: Issues, https://github.com/0xDegenMo/lighter-mcp/issues
Author: 0xDegenMo
License: MIT
License-File: LICENSE
Keywords: claude,defi,dex,lighter,mcp,model-context-protocol,perpetuals,trading
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.10
Requires-Dist: aiohttp>=3.9.0
Requires-Dist: lighter-sdk>=1.0.6
Requires-Dist: mcp>=1.2.0
Requires-Dist: python-dotenv>=1.0.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# lighter-mcp

A [Model Context Protocol](https://modelcontextprotocol.io) server for [Lighter](https://lighter.xyz) — a zero-fee zk-rollup perpetual DEX on Ethereum.

Connect any MCP-aware client (Claude Desktop, Cursor, Hermes, custom Anthropic SDK apps) and trade Lighter perpetuals natively: place orders, manage positions, set on-chain stop-loss / take-profit, query markets and account state.

## Free + sustained by a small optional fee

**This MCP is free and open-source.** You can install it, run it, and trade through it without paying anyone.

If you find it useful, you can opt-in to a small fee that helps keep the project sustained — one on-chain transaction, no recurring action. The fee is **1 bp maker (0.01%) / 2 bps taker (0.02%)** on your own trades:

| Your trade volume | Per-trade cost (taker) | Yearly cost (50 trades/month) |
|---|---|---|
| $1,000 | $0.20 | ~$120 |
| $100 | $0.02 | ~$12 |
| $50 (lighter sub-account default) | $0.01 | ~$6 |

The fee routes via Lighter's permissionless partner-integrator program to the maintainer's account `725426`. **No fees flow until you sign an on-chain `ApproveIntegrator` once.** It's strictly opt-in: you can install + trade without ever approving.

**Honest disclosure about Lighter's standard fees:**
- Lighter **Standard Accounts** (retail default) currently trade with **0 maker / 0 taker fees**. Approving the integrator means you pay 1-2 bps that wouldn't otherwise apply.
- Lighter **Premium Accounts** trade with 2/20 bps. Approving the integrator gives you 1/2 bps instead — you save money.

For Standard Accounts the approve is a small "thanks" contribution. For Premium Accounts it's a clear win-win.

## How to opt in (or out)

**Opt in (one-time, ~60 seconds, recommended browser flow):**

```bash
lighter-mcp-approve
```

A localhost web page opens; connect Metamask/Rabby; click *Approve*; sign the EIP-191 message in your wallet. Your L1 wallet key never leaves the wallet UI — only an EIP-191 personal signature passes back to the local script.

**Revoke at any time:**

```bash
lighter-mcp-approve --revoke
```

Sets the approval to zero fees. Or simpler — disable client-side without an on-chain change:

```bash
# In your MCP server env:
LIGHTER_NO_INTEGRATOR=true
```

When set, integrator params aren't even attached to your orders. Zero attribution, zero potential fee flow.

**Approve expires after 90 days by default** — you re-approve only if you want to keep contributing. No silent lock-in.

## Features

- **17 trading tools** + `get_status` and `how_to_approve_integrator` diagnostics
- **Three credential tiers** — install + try with no credentials, opt in to more as you go
- **Native on-chain SL/TP** — survives client restarts
- **USDC-notional market orders** for simple sizing; base-amount limit orders for precision
- **Multi-market** — symbols auto-discovered from the order-book API
- **Sub-account-first design** — API key signs for a sub-account; your main wallet stays cold
- **Server-side safety caps** — max trade size, slippage limit, symbol allowlist
- **Per-market price/size encoding** — handles all listed perpetuals correctly (BTC 1-decimal, NEAR 5-decimal, etc.)

## Modes

The server picks one of three modes at startup based on which env vars are set. Higher modes are strictly opt-in.

| Mode | Required env | Tools available | Use for |
|---|---|---|---|
| **PUBLIC** | _(none)_ | 7 public market-data tools (markets, candles, orderbook, funding...) | Trying it out, exploring Lighter data, building analytics |
| **READ** | `LIGHTER_ACCOUNT_INDEX` | + 3 account-state tools (balance, positions) | Monitoring your account from Claude/Cursor |
| **TRADE** | + `LIGHTER_PRIVATE_KEY` _(and not_ `LIGHTER_READ_ONLY=true`_)_ | + 8 trading tools | Autonomous / assisted trading |

In TRADE mode you can demote to read-only at any time with `LIGHTER_READ_ONLY=true` — order-placement tools are then not even registered.

## Install

```bash
pip install 0xdegenmo-lighter-mcp
# For live trading you also need the git version of the Lighter SDK:
pip install --upgrade git+https://github.com/elliottech/lighter-python.git@main
```

## Configure

### Claude Desktop

`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or
`%APPDATA%\Claude\claude_desktop_config.json` (Windows):

**Minimal — PUBLIC mode (no Lighter account needed):**
```json
{
  "mcpServers": {
    "lighter": {
      "command": "python",
      "args": ["-m", "lighter_mcp"]
    }
  }
}
```

**Full — TRADE mode (sub-account API key required):**
```json
{
  "mcpServers": {
    "lighter": {
      "command": "python",
      "args": ["-m", "lighter_mcp"],
      "env": {
        "LIGHTER_URL": "https://mainnet.zklighter.elliot.ai",
        "LIGHTER_ACCOUNT_INDEX": "<your-sub-account-index>",
        "LIGHTER_PRIVATE_KEY": "<api-key-private-key>",
        "LIGHTER_API_KEY_INDEX": "2",
        "LIGHTER_MAX_QUOTE_USD": "100"
      }
    }
  }
}
```

Restart Claude Desktop. Try: *"List my Lighter markets"* (PUBLIC works) or *"What's my balance?"* (needs READ+).

### Cursor / other MCP clients

Same command and args. Check your client's MCP server config for the exact format.

### Hermes Agent

```yaml
mcp_servers:
  lighter:
    command: "python"
    args: ["-m", "lighter_mcp"]
    env:
      LIGHTER_URL: "https://mainnet.zklighter.elliot.ai"
      LIGHTER_ACCOUNT_INDEX: "<sub>"
      LIGHTER_PRIVATE_KEY: "<api-key-priv>"
      LIGHTER_API_KEY_INDEX: "2"
```

## Tools

### Always available (Tier 1 — PUBLIC)
- `get_status` — current mode, safety policy, integrator config (no secrets)
- `how_to_approve_integrator` — instructions for opt-in / opt-out
- `list_markets`, `get_market(symbol)` — market discovery
- `get_candles`, `get_ticker`, `get_orderbook`, `get_funding_rate` — market data

### With `LIGHTER_ACCOUNT_INDEX` (Tier 2 — READ)
- `get_balance` — collateral / margin-in-use / available / asset_value
- `get_positions`, `get_position(symbol)` — open positions

### With `LIGHTER_PRIVATE_KEY` (Tier 3 — TRADE)
- `set_leverage(symbol, leverage, cross)`
- `place_market_order(symbol, side, quote_amount_usd, reduce_only)`
- `place_limit_order(symbol, side, base_amount, price)`
- `place_stop_loss(symbol, side, base_amount, trigger_price)` — on-chain, reduce-only
- `place_take_profit(symbol, side, base_amount, trigger_price)` — on-chain, reduce-only
- `close_position(symbol)`
- `cancel_order(order_id, symbol)`
- `cancel_all_orders`

## Trust & Security

This server signs transactions with whatever key you put in `LIGHTER_PRIVATE_KEY`. Treat that as the most sensitive value in the whole config.

**Why you can trust this MCP** (or audit it):
- **Fully open-source** — every line of code lives at github.com/0xDegenMo/lighter-mcp. ~800 lines of Python total, readable in under 30 minutes.
- **Sub-account isolation** — the API key signs only for one Lighter sub-account; cannot withdraw funds, cannot touch your main wallet.
- **Three-tier separation** — tools that need credentials are only registered when those credentials are present. A PUBLIC-mode server *cannot* place trades even if asked.
- **Integrator fees are Lighter-enforced** — even if the maintainer ships malicious code that tries to skim, Lighter's protocol requires your on-chain `ApproveIntegrator` for fees to flow at all. Without your signature, integrator params are inert.
- **Easy revoke** — `lighter-mcp-approve --revoke` or `LIGHTER_NO_INTEGRATOR=true` env, takes seconds.
- **Approve expires** — default 90-day expiry means you re-confirm intent, never silently locked in.

**Wallet hygiene**
- **Use a Lighter sub-account, not your main wallet.** Create the sub-account in the Lighter UI, fund only what you're willing to risk, generate an API key with `apiKeyIndex >= 2` for that sub-account. That key cannot withdraw — it can only sign trading transactions for that sub-account.
- **Never put your main wallet seed or main signing key in env vars.** This MCP doesn't need it.
- **Treat `LIGHTER_PRIVATE_KEY` as a secret.** Don't commit `.env`; don't paste into shared chats.

**Server-side caps** (enforced before the order leaves the process)
- `LIGHTER_MAX_QUOTE_USD` (default **100**) — opening trade size cap in USDC. `reduce_only=True` orders bypass the cap, so closing/trimming always works.
- `LIGHTER_MAX_SLIPPAGE` (default **0.005** = 0.5%) — applied to market orders.
- `LIGHTER_ALLOWED_SYMBOLS` (default: all markets) — comma-separated allowlist. If set, trades on any other symbol are refused server-side.
- `LIGHTER_API_KEY_INDEX < 2` — logged as a warning at startup. Indices 0/1 are typically reserved for the main account.

**Operational notes**
- Logs (stderr) include the active mode and integrator config but **never** the private key (only first/last few chars in the rare case keys appear in error paths).
- `cancel_all_orders` cancels across **all** markets in the sub-account. Use intentionally.
- Cross-margin: all positions in the sub-account share collateral; a bad trade can drain the whole sub-account but nothing else.

## Forking for your own integrator

If you fork this project, you can route fees to your own account:
```bash
LIGHTER_INTEGRATOR_ACCOUNT_INDEX=<your-account-index>
LIGHTER_INTEGRATOR_MAKER_FEE=<raw>  # 100 = 1 bp
LIGHTER_INTEGRATOR_TAKER_FEE=<raw>  # 200 = 2 bps
```

Then each install needs its own `ApproveIntegrator` for *your* account before fees flow.

## Environment

| Var | Tier | Default | Description |
|---|---|---|---|
| `LIGHTER_URL` | all | mainnet | API base URL |
| `LIGHTER_ACCOUNT_INDEX` | READ+ | _(unset)_ | Sub-account index |
| `LIGHTER_PRIVATE_KEY` | TRADE | _(unset)_ | API-key private key (sub-account, not main wallet) |
| `LIGHTER_API_KEY_INDEX` | TRADE | `2` | Index of the API key |
| `LIGHTER_READ_ONLY` | any | _(unset)_ | If `true`, disables order-placement tools |
| `LIGHTER_MAX_QUOTE_USD` | TRADE | `100` | Cap on opening trade size in USDC |
| `LIGHTER_MAX_SLIPPAGE` | TRADE | `0.005` | Max slippage fraction on market orders |
| `LIGHTER_ALLOWED_SYMBOLS` | TRADE | _(unset)_ | Comma-separated symbol allowlist |
| `LIGHTER_NO_INTEGRATOR` | any | _(unset)_ | If `true`, strips integrator params entirely |
| `LIGHTER_INTEGRATOR_ACCOUNT_INDEX` | any | `725426` | Override integrator account (forks) |
| `LIGHTER_INTEGRATOR_MAKER_FEE` | any | `100` | Override maker fee (raw int) |
| `LIGHTER_INTEGRATOR_TAKER_FEE` | any | `200` | Override taker fee (raw int) |
| `LIGHTER_MCP_LOG_LEVEL` | any | `INFO` | Log level on stderr |

## License

MIT
