# liquidtrading-mcp

## Overview

`liquidtrading-mcp` is the MCP server for Liquid Trading. It exposes Liquid market data, account state, trading actions, helper tools, prompt templates, and live resources through any MCP-compatible client.

It is designed for self-hosting and intentionally depends on the SDK package rather than vendoring client logic:

- PyPI package: `liquidtrading-mcp`
- runtime SDK dependency: `liquidtrading-python>=0.1.1,<0.2`
- local development source override: `../liquidtrading-python`

## Architecture

The MCP server stack is:

1. MCP client
2. `liquidtrading-mcp`
3. `liquidtrading-python`
4. Liquid public REST API

This keeps:

- API auth/signing logic centralized in the SDK
- MCP tool code thin and focused on agent ergonomics
- API surface changes easy to propagate through one client layer

## Package Identity

- package name: `liquidtrading-mcp`
- Python requirement: `>=3.10`
- console entrypoint: `liquidtrading-mcp`
- Python package: `liquid_mcp`

## Installation

### PyPI

```bash
pip install liquidtrading-mcp
```

### uv

```bash
uv pip install liquidtrading-mcp
```

### Source Install

```bash
cd /Users/raymondcosgrove/Liquid/Public\ Apis/liquidtrading-mcp
uv sync --no-sources
```

### Source Install With Sibling SDK Checkout

If both repos are side-by-side:

```text
Public Apis/
  liquidtrading-python/
  liquidtrading-mcp/
```

then plain `uv sync` will use the sibling SDK checkout via:

```toml
[tool.uv.sources]
liquidtrading-python = { path = "../liquidtrading-python" }
```

## Running The Server

### stdio

Use this for Claude Code, Claude Desktop, Cursor, and similar MCP clients.

```bash
LIQUID_API_KEY=lq_... \
LIQUID_API_SECRET=sk_... \
LIQUID_BASE_URL=https://prometheus-prod--liquid-public-api-public-fastapi-app.modal.run \
liquidtrading-mcp
```

### Streamable HTTP

```bash
LIQUID_API_KEY=lq_... \
LIQUID_API_SECRET=sk_... \
LIQUID_BASE_URL=https://prometheus-prod--liquid-public-api-public-fastapi-app.modal.run \
liquidtrading-mcp --http
```

Default HTTP host and port:

- `0.0.0.0`
- `4243`

## Environment Variables

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `LIQUID_API_KEY` | Yes | unset | API key |
| `LIQUID_API_SECRET` | Yes | unset | API secret paired with the key |
| `LIQUID_BASE_URL` | No | SDK default | API base URL |
| `MAX_ORDER_USD` | No | `1000` | maximum single order size |
| `DAILY_LOSS_LIMIT` | No | `5000` | daily cumulative realized loss cap |
| `LIQUID_MCP_AUDIT_PATH` | No | `~/.liquidtrading-mcp/trades.jsonl` | JSONL audit log path |

Rules:

- `LIQUID_API_KEY` and `LIQUID_API_SECRET` are both required
- `MAX_ORDER_USD` must be positive
- `DAILY_LOSS_LIMIT` must be positive
- if `MAX_ORDER_USD > DAILY_LOSS_LIMIT`, the server logs a warning

## Client Configuration Examples

### Claude Code

```bash
claude mcp add liquid \
  -e LIQUID_API_KEY=lq_... \
  -e LIQUID_API_SECRET=sk_... \
  -e LIQUID_BASE_URL=https://prometheus-prod--liquid-public-api-public-fastapi-app.modal.run \
  -e MAX_ORDER_USD=1000 \
  -e DAILY_LOSS_LIMIT=5000 \
  -- liquidtrading-mcp
```

### Claude Desktop

```json
{
  "mcpServers": {
    "liquid": {
      "command": "liquidtrading-mcp",
      "env": {
        "LIQUID_API_KEY": "lq_...",
        "LIQUID_API_SECRET": "sk_...",
        "LIQUID_BASE_URL": "https://prometheus-prod--liquid-public-api-public-fastapi-app.modal.run",
        "MAX_ORDER_USD": "1000",
        "DAILY_LOSS_LIMIT": "5000"
      }
    }
  }
}
```

### From Source

```json
{
  "mcpServers": {
    "liquid": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/Users/raymondcosgrove/Liquid/Public Apis/liquidtrading-mcp",
        "liquidtrading-mcp"
      ],
      "env": {
        "LIQUID_API_KEY": "lq_...",
        "LIQUID_API_SECRET": "sk_...",
        "LIQUID_BASE_URL": "https://prometheus-prod--liquid-public-api-public-fastapi-app.modal.run"
      }
    }
  }
}
```

## Tool Catalog

The server currently exposes 22 tools.

## Market Data Tools

These tools are marked read-only in MCP annotations.

### `get_markets`

Returns all tradeable markets.

Typical use:

- first call in a session
- symbol discovery
- validating symbol spelling before trading

### `get_ticker(symbol)`

Returns:

- mark price
- volume
- funding rate
- minimum order info
- suggested next steps

### `get_orderbook(symbol, depth=20)`

Returns:

- full L2 snapshot
- bid/ask depth
- next-step hints for order placement

### `get_candles(symbol, interval="1h", limit=100, start=None, end=None)`

Returns:

- symbol
- interval
- candle list
- next-step hints

## Account Tools

### `get_account`

Returns:

- equity
- margin used
- available balance
- account value

### `get_balances`

Returns:

- exchange
- balance breakdown
- cross-margin summary when available

### `get_positions`

Returns open positions with:

- side
- size
- leverage
- liquidation price
- unrealized PnL

## Order Tools

These tools are destructive and marked as such in MCP annotations.

### `place_order`

Parameters:

- `symbol`
- `side`
- `size`
- `type`
- `leverage`
- `price`
- `tp`
- `sl`
- `reduce_only`
- `time_in_force`
- `dry_run`

Important:

- `size` is USD notional, not token count
- dry runs are still written to the audit log
- large orders, missing TP/SL, and high leverage may produce warnings

### `place_bracket_order`

This is the safest entry tool for most agents because TP and SL are required as part of the order request.

Parameters:

- `symbol`
- `side`
- `size`
- `tp`
- `sl`
- `leverage`
- `price`
- `type`
- `time_in_force`
- `dry_run`

### `get_open_orders`

Returns:

- `orders`
- `next_steps`

### `get_order(order_id)`

Returns a single order record and suggested follow-up actions.

### `cancel_order(order_id, dry_run=False)`

Cancels one order or previews the cancel in dry-run mode.

### `cancel_all_orders(dry_run=False)`

Cancels all open orders or previews the action in dry-run mode.

## Position Tools

### `close_position(symbol, size=None, dry_run=False)`

Important:

- full close when `size` is omitted
- partial close when `size` is provided
- partial close size is in coin units

### `set_tp_sl(symbol, tp=None, sl=None, dry_run=False)`

Sets or updates TP and/or SL for an existing position.

### `update_leverage(symbol, leverage, is_cross=False, dry_run=False)`

Behavior:

- validates leverage `1..200`
- warns above `20x`
- returns `warnings` when risk is elevated

### `update_margin(symbol, amount, dry_run=False)`

Adjusts isolated margin by positive or negative amount.

## Helper Tools

### `calculate_token_amount(symbol, usd_amount)`

Converts USD notional to token count at current mark price.

### `calculate_position_size(symbol, percent_of_equity)`

Converts a portfolio allocation percentage into USD size and token amount.

### `validate_trade(symbol, side, size, leverage=1, type="market")`

Performs pre-flight checks for:

- order size vs max limit
- daily loss limit
- side validity
- type validity
- leverage range
- available balance
- symbol validity

This should generally be called before larger trades.

## Resources

The server exposes two resources:

### `liquid://portfolio`

Returns:

- current account summary
- open positions

### `liquid://risk`

Returns:

- `max_order_usd`
- `daily_loss_limit`
- `daily_loss_used`
- `daily_loss_remaining`
- `positions_count`
- `total_exposure`

If the server cannot fetch positions, the resource still returns guardrail state with an `error_hint`.

## Prompt Templates

The MCP server currently registers four prompts:

- `scalp`
- `swing`
- `funding_arb`
- `momentum_scan`

These prompts encode Liquid-specific perp trading guidance, including:

- perpetual futures semantics
- funding awareness
- leverage caution
- TP/SL expectations
- validation flow

## Safety Model

The server includes several layers of guardrails.

### Max Order Limit

`MAX_ORDER_USD` caps:

- single orders

It also enforces the Hyperliquid minimum order floor of `$10`.

### Daily Loss Tracker

The daily loss tracker:

- records realized losses by UTC date
- blocks new orders after the configured loss cap is hit
- is thread-safe for concurrent tool usage

### Dry Run Support

Destructive tools support `dry_run=True` so agents can preview actions without execution.

### Audit Trail

Trade operations are written to a JSONL audit file, including dry runs.

Default path:

```text
~/.liquidtrading-mcp/trades.jsonl
```

### Structured Recovery Hints

SDK exceptions are converted to MCP-friendly structured error objects with:

- `error`
- `error_code`
- `message`
- `hint`
- `next_steps`

This is important because LLM clients recover more reliably from structured action guidance than raw stack traces.

## Server Instructions And Trading Semantics

The built-in server instructions teach the agent:

- all markets are perpetual futures
- `size` is USD notional
- funding matters
- leverage affects liquidation risk
- isolated and cross margin are different
- TP/SL should be set by default

This is one of the core reasons to keep the MCP layer separate from the raw SDK: the MCP server can encode operational guidance for agents in addition to just exposing functions.

## Known Compatibility Notes

### Market Endpoints

All endpoints require a valid API token — there are no unauthenticated routes. This includes market-data endpoints like `/v1/markets/*` which require read-scope auth.

## Self-Hosting Guidance

Recommended release model:

1. publish `liquidtrading-python`
2. publish `liquidtrading-mcp`
3. optionally publish MCP Registry metadata

For self-hosting users, the install path should be:

```bash
pip install liquidtrading-mcp
```

not:

- cloning both repos manually
- vendoring SDK code into the MCP repo

Keeping the SDK as a normal package dependency is the cleanest long-term split for independent repos.

## Troubleshooting

### Tools Do Not Appear

Check:

- the MCP client was restarted after config changes
- `liquidtrading-mcp` is on `PATH`
- source install paths are correct

### Authentication Errors

Check:

- both `LIQUID_API_KEY` and `LIQUID_API_SECRET` are set
- the credentials are valid for the target base URL
- the API key has sufficient scopes

### Unexpected Order Or Position State

On network errors, the recommended recovery path is:

1. `get_positions`
2. `get_open_orders`
3. `get_order`

This avoids duplicate execution after a timeout or connection failure.

## Source Of Truth In Code

Main files:

- [server.py](/Users/raymondcosgrove/Liquid/Public Apis/liquidtrading-mcp/liquid_mcp/server.py)
- [config.py](/Users/raymondcosgrove/Liquid/Public Apis/liquidtrading-mcp/liquid_mcp/config.py)
- [client_manager.py](/Users/raymondcosgrove/Liquid/Public Apis/liquidtrading-mcp/liquid_mcp/client_manager.py)
- [guardrails.py](/Users/raymondcosgrove/Liquid/Public Apis/liquidtrading-mcp/liquid_mcp/guardrails.py)
- [resources.py](/Users/raymondcosgrove/Liquid/Public Apis/liquidtrading-mcp/liquid_mcp/resources.py)
- [prompts.py](/Users/raymondcosgrove/Liquid/Public Apis/liquidtrading-mcp/liquid_mcp/prompts.py)
- [tools/](/Users/raymondcosgrove/Liquid/Public Apis/liquidtrading-mcp/liquid_mcp/tools)
- [pyproject.toml](/Users/raymondcosgrove/Liquid/Public Apis/liquidtrading-mcp/pyproject.toml)

Related docs:

- [SDK.md](/Users/raymondcosgrove/Liquid/Public Apis/liquidtrading-python/docs/SDK.md)
- [REST_API.md](/Users/raymondcosgrove/Liquid/Public Apis/combined/docs/REST_API.md)
- [QUICKSTART.md](/Users/raymondcosgrove/Liquid/Public Apis/combined/docs/QUICKSTART.md)
