Skip to main content
Glama
evidai

alpaca-guard-mcp

alpaca-guard-mcp — Alpaca Trading Guard MCP Server

MCP server wrapping the Alpaca trading API with a hard daily USD cap guard. Enforced server-side — an over-eager AI agent literally cannot exceed it. Paper trading by default; live trading requires explicit opt-in.

npm version MCP Registry License: MIT MCP FSA Q1–Q11 Non-custodial v2

🍋 Part of the LemonCake suite. Japan FSA Q1–Q11 inquiry completed (2026-05); pure SDK / non-custodial distribution model confirmed registration-exempt. External security audit cleared. See LemonCake security posture.

npx -y alpaca-guard-mcp

30-second pitch

Alpaca's official MCP exposes the Alpaca trading API directly to LLMs. Powerful, but the single biggest objection from teams shipping agentic trading is:

"What if the AI rage-buys $50k of meme stocks at 3am because the prompt got injected?"

Alpaca's MCP doesn't ship agent-level spending controls (correctly so — that's not Alpaca's job). alpaca-guard-mcp does:

  • Preflight every order against a daily USD cap stored in ~/.alpaca-guard/cap.json.

  • Refuse the call (with a structured hint the LLM can read) if the trade would breach the cap.

  • Record the charge on success; the cap survives across MCP server restarts and rolls over at UTC midnight.

  • Paper trading is the default. Live trading is blocked unless the operator sets ALPACA_GUARD_ALLOW_LIVE=yes-i-understand.

There is no agent-side override. The cap is a circuit breaker, not a suggestion.


Quickstart

1. Install (Claude Desktop / Cursor / Cline)

Add to your MCP client config (claude_desktop_config.json or equivalent):

{
  "mcpServers": {
    "alpaca-guard": {
      "command": "npx",
      "args":    ["-y", "alpaca-guard-mcp"],
      "env": {
        "ALPACA_API_KEY":     "PK...",
        "ALPACA_SECRET_KEY":  "...",
        "ALPACA_PAPER_TRADE": "true"
      }
    }
  }
}

Restart your MCP client. The 🔨 tools icon should show alpaca-guard-mcp tools.

Free Alpaca paper-trading account: https://app.alpaca.markets/paper/dashboard/overview

2. Set your daily cap

In your MCP client, ask:

Set my alpaca-guard daily limit to $50.

The agent will call guard_set_limit({ dailyLimitUsd: 50 }). The first-ever default is $10 as a safety floor.

3. Let the agent trade — and watch it refuse the dumb ones

Buy 1000 NVDA at limit $900.

The agent will call guarded_place_order. The guard will preflight: notional = 1000 × $900 = $900,000, remaining = $50, refused with BUDGET_EXCEEDED.

The hint the agent sees back:

This order would cost ~$900000.00 but only $50.00 remains under today's
$50.00 cap. Either (a) wait until tomorrow (UTC), (b) call guard_set_limit
to raise the cap (you decide, not the agent), or (c) split the order into
smaller qty. The agent cannot override this from inside a tool call.

Tools

Tool

Read-only?

Notes

setup

Env state, mode, current cap, ledger location

guard_status

Daily limit / used / remaining / recent 10 orders

guard_set_limit

Set the daily USD cap. Idempotent.

get_account

Alpaca account snapshot

get_positions

Current open positions

get_latest_quote

Bid / ask / mid for a symbol

guarded_place_order

Place an order; preflighted against the cap

guarded_close_position

Close a position; preflighted on notional


Configuration

Env var

Required

Default

Notes

ALPACA_API_KEY

From Alpaca dashboard

ALPACA_SECRET_KEY

From Alpaca dashboard

ALPACA_PAPER_TRADE

true

Set to false for live trading (still requires ALPACA_GUARD_ALLOW_LIVE)

ALPACA_GUARD_ALLOW_LIVE

live only

Must literally be yes-i-understand to enable real-money orders

ALPACA_GUARD_LEDGER_DIR

~/.alpaca-guard

Where cap.json lives. Useful for tests / multiple ledgers.

LEMON_CAKE_PERMIT

Currently unused (v0.1 local-ledger mode). Future: switch the guard to LemonCake's permit-based preflight when the upstream API ships it. See issue #4.


Worked example (end-to-end via stdio smoke test)

Without any Alpaca credentials, the guard still works for the preflight stage. From the test in this repo:

$ ALPACA_GUARD_LEDGER_DIR=/tmp/alpaca-guard-test \
  echo '{"jsonrpc":"2.0",...,"method":"tools/call","params":{"name":"guarded_place_order",
        "arguments":{"symbol":"NVDA","qty":1000,"side":"buy","type":"limit","limitPrice":900}}}' \
  | node dist/index.js

Returns:

{
  "allowed":          false,
  "status":           "BUDGET_EXCEEDED",
  "tradeNotionalUsd": 900000,
  "remainingUsd":     10,
  "limitUsd":         10,
  "hint":             "This order would cost ~$900000.00 but only $10.00 remains ..."
}

That preflight ran before any Alpaca call — and would refuse the order even on a paper account. With paper credentials added and a sensible cap, the same guarded_place_order against a 1-share order at $25 will succeed and record $25 against the daily ledger.


How the guard is composed (architecture)

┌──────────────────────────────────┐
│  Agent (Claude / Cursor / Cline) │
└────────────┬─────────────────────┘
             │ tool: guarded_place_order(symbol, qty, side, type, limitPrice?, tif?)
             ▼
┌────────────────────────────────────────────────────────────────────┐
│  alpaca-guard-mcp                                                   │
│                                                                     │
│  1. Resolve effective price (limit_input OR get_latest_quote)       │
│  2. Preflight against ~/.alpaca-guard/cap.json                      │
│  3. If !allowed → refuse with BUDGET_EXCEEDED (no Alpaca call)      │
│  4. If allowed → forward to Alpaca REST /v2/orders                  │
│  5. On success → record charge in ledger (cap.json + history)       │
│  6. Return Alpaca order + x402-shaped receipt                       │
└──────────────────┬──────────────────┬──────────────────────────────┘
                   │                  │
                   ▼                  ▼
┌──────────────────────┐   ┌──────────────────────────┐
│ Alpaca REST          │   │  ~/.alpaca-guard/cap.json │
│ (paper or live)      │   │  { dailyLimitUsd,         │
└──────────────────────┘   │    todayUsedUsd,          │
                           │    history[] }            │
                           └──────────────────────────┘

Read-only tools (get_account, get_positions, get_latest_quote) bypass the guard — they don't spend.


Why the cap is local-file rather than LemonCake API (today)

alpaca-guard-mcp is built by the same team as agent-payment-mcp at lemoncake.xyz. The eventual goal is for the guard to live on LemonCake's permit preflight endpoint — same daily cap mechanic, but server-side and shared across MCP clients.

That endpoint doesn't exist yet (see issue #4). Until it does, the local ledger is the right shape: zero network dependency, survives restarts, simple to inspect.

When the LemonCake API ships, LEMON_CAKE_PAY_TOKEN will be honored: if set, the guard switches to remote preflight. The tool surface stays identical.


Status & roadmap

Phase

Status

Notes

Phase A: local-ledger guard + paper trading

✅ shipped v0.1.0

This release

Phase B: LemonCake permit integration

⏳ gated

issue #4

Phase C: KYA tier multi-cap (daily + weekly + per-symbol)

After Phase B

Phase D: Listed on Anthropic Connectors Directory

Same submission flow as agent-payment-mcp


License

MIT. Source at github.com/evidai/lemon-cake/tree/main/alpaca-guard-mcp.

  • Alpaca MCP server v2 — the upstream this guard wraps (logically; we talk directly to Alpaca REST so we don't depend on it at runtime)

  • agent-payment-mcp — sibling MCP from the same team, where the permit flow originates

  • LemonCake — interactive playground & docs

Install Server
A
license - permissive license
A
quality
B
maintenance

Maintenance

Maintainers
14hResponse time
0dRelease cycle
9Releases (12mo)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/evidai/agent-payment-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server