Reins
Model Context Protocol

A Hyperliquid MCP server with the limits outside the model

Reins gives Claude, Claude Code, Cursor or any MCP client a set of Hyperliquid trading tools. Every order it places goes through a risk engine in a different process, so the position cap, the stop-loss requirement and the daily loss limit hold whatever the model decides — or is persuaded to do.

$ npx @r2rlabs/reins init

Connecting it

init writes the config for the client you pick and starts in paper mode: simulated fills on live prices, no money at risk. To wire it by hand, point any MCP client at the server:

{
  "mcpServers": {
    "reins": {
      "command": "npx",
      "args": ["-y", "@r2rlabs/reins", "serve"],
      "env": { "REINS_NETWORK": "testnet", "REINS_SYMBOLS": "BTC,ETH" }
    }
  }
}

Paper and testnet need no key at all. Live trading signs with a Hyperliquid API wallet, which can place and cancel orders but cannot withdraw — and which you can revoke on Hyperliquid at any moment, cutting the agent off without asking anyone.

The tools a model gets

get_limits

The limits in force and the room left under each

get_positions

Open positions, PnL, and which have no stop-loss

get_book, get_candles

Market data for sizing and timing

place_order

Checked against every limit before it reaches the exchange

set_stop_loss

Protect a position, replacing any stop already there

cancel_order, close_position

Always allowed: they only lower risk

get_recent_decisions

Its own record, including what was refused

There is deliberately no tool for changing a limit. An agent that could raise its own position cap has no cap, and prompt injection is a real attack on anything that trades: the whole point is that the rules live where the model's context cannot reach them.

What it refuses

Each refusal names its rule, so an agent corrects itself instead of retrying blindly.

POSITION_TOO_LARGE

Past the cap for that asset, counting what is already held

NO_STOP_LOSS

An order that opens or adds without a stop attached

SYMBOL_NOT_ALLOWED

An asset outside the allowlist, which the message prints

DAILY_LOSS_LIMIT

Realised losses hit the day's limit; only closing orders pass

RATE_LIMIT

More orders a minute than a strategy has reasons for

Every attempt on the record

The decision log keeps what the agent tried, the reason it gave in its own words, what the risk engine said and what the exchange did. Refusals are kept as carefully as fills — "the agent tried six times its position cap at 3am, and here is what it said it was doing" is the single most useful thing this can tell you, and it only exists if refusals are written down.

The stated reason is testimony, not proof: a model can rationalise after the fact. It is still the only record of why, and it is worth having.

If you would rather not run it

Reins Cloud is the same engine as a service: keys in a KMS, an owner login with two-factor, alerts by email, Telegram and SMS, orders over a size you choose held for your approval, and one URL your agent connects to. Reins itself stays free and open source.