Skip to main content
Glama
ARSA Guard

ARSA Guard

README.md
<p align="center"><img src="https://arsaguard.com/img/logo/readme.png" width="120" alt="ARSA Guard"></p>

# ARSA Guard

**Brakes for your trading agent.** An MCP server that sits between your AI client (Claude, Cursor, Codex) and Robinhood Agentic Trading. Reads pass straight through. Every order is checked against your rules first, in plain code with no model in the loop. A broken rule is a **HOLD**, and a hold is final.

The guard only ever stops orders. None of its rules can place one.

## Install

Needs Node.js 20 or newer.

```sh
npm install -g arsaguard
arsaguard              # status: mode, sign-in, market, rules
arsaguard web          # local dashboard on 127.0.0.1:4320
arsaguard try buy AAPL 1 --limit 180
```

## Connect your client

Claude Desktop (`claude_desktop_config.json`) or Cursor (`~/.cursor/mcp.json`):

```json
{
  "mcpServers": {
    "robinhood-guarded": { "command": "npx", "args": ["-y", "arsaguard", "serve"] }
  }
}
```

Claude Code:

```sh
claude mcp add robinhood-guarded -- npx -y arsaguard serve
```

## Modes

| Mode | Command | An order that passes every rule |
|---|---|---|
| Paper | `serve` | fills in a local paper account at the last real price. No Robinhood account needed. |
| Live, dry-run | `serve --live` | is sent to Robinhood's `review_equity_order`, never placed. |
| Live, armed | `serve --live --armed` | is placed on your Robinhood account. |

Live mode needs `arsaguard login` (Robinhood's own OAuth sign-in in your browser; the guard never sees your password) and an account with Agentic Trading access.

## Rules

All on by default. Change them with `arsaguard set`, `on`, `off`, `block`, or in the dashboard. The agent can read them, never edit them.

| ID | Default | Holds an order when |
|---|---|---|
| `max_order_usd` | $100 | a buy is larger than the cap |
| `daily_buy_usd` | $300 | today's buys plus this one go over the cap |
| `daily_orders` | 10 | this many orders were already let through today |
| `daily_loss` | $50 | a buy comes after this much in logged losses today |
| `cool_down` | 30 min | a buy comes right after a logged losing exit |
| `limit_only` | on | the order is a market order |
| `regular_hours` | on | outside 9:30-16:00 New York, on an exchange holiday, or after 13:00 on an early-close day |
| `earnings_block` | 48 h | a buy comes shortly before the company reports (Nasdaq calendar) |
| `equities_only` | on | it is an option, crypto or option exercise |
| `blocklist` | empty | a buy is for a symbol on your list |

Anything the guard cannot read (symbol, side, size, the earnings calendar) is held rather than guessed. Unknown tools whose names sound like they move money are treated as orders.

## The record

Every decision is one JSON line holding the hash of the line before it, in `~/.arsaguard/guard-audit.jsonl`. `arsaguard audit --verify` checks the chain.

## Commands

```
arsaguard serve [--live] [--armed]     MCP server for your AI client
arsaguard try buy|sell SYM n [--limit 180] [--dollars 50] [--market]
arsaguard set ID key=value             e.g. arsaguard set max_order_usd usd=250
arsaguard on|off ID · block|unblock SYM
arsaguard loss USD [note]              log a losing exit
arsaguard audit [n] [--verify]
arsaguard paper [reset CASH]
arsaguard web [--port 4320]
arsaguard login|logout
```

Add `--json` to any command for machine-readable output.

## Limits

Prices come from Yahoo Finance and earnings dates from Nasdaq's public calendar; both are unofficial. Exchange closures announced at short notice are not known in advance. Losses made outside the guard count only once you log them.

Not financial advice. Not affiliated with Robinhood.

## Links

[arsaguard.com](https://arsaguard.com) · [npm](https://www.npmjs.com/package/arsaguard) · [GitHub](https://github.com/arsaguard-dev/arsaguard) · [X @arsaguard](https://x.com/arsaguard)

## License

MIT