risk-agent-explain
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
alpaca-risk-agent
A scheduled paper-trading agent for Alpaca. It takes a deliberately simple signal (SMA 5/15 crossover) and wraps it in a risk layer that sizes each trade from the stop distance, caps how much of the account any one symbol can use, halts after a bad day, and writes down why it did or did not trade for every symbol on every run. A read-only MCP server exposes that log, so an assistant can answer "why did you buy 50 AAPL?" from the agent's own record instead of guessing.
It started from Stephen Kimoi's tutorial A Trading Agent That Sizes Its Own Risk and Explains Itself (Aug 2026, for the lablab.ai Alpaca hackathon). Running the tutorial's design against the real CLI turned up six problems that would show up in unattended operation. They are fixed here and each one has a test.
What changed from the tutorial, and why
# | Tutorial behaviour | Failure it causes | Fix here | Test |
1 | Checks for an open position only | A run before the fill (or outside market hours) sees no position and buys again: double orders | Checks the market clock, open orders, and today's orders. The client order ID is deterministic per symbol per day, so Alpaca also rejects duplicates if two runs overlap |
|
2 | Concentration cap breach skips the trade | A valid signal is thrown away instead of sized down | Size is |
|
3 | Market entry, stop computed from the last trade | The fill can land above the reference price while the stop stays fixed, so the real loss exceeds the stated budget | Marketable limit entry at reference +0.2%. Shares are sized against that worst-case price, so the loss at the stop is capped by construction |
|
4 | Bracket with | If the stop and take-profit legs inherit |
|
|
5 | SMA computed over bars that include today's | Today's daily bar is still forming during market hours, so the signal can flip intraday on a half-built candle | Today's bar is dropped; only completed sessions vote. Bars are split-adjusted |
|
6 | Assistant gets Alpaca's full MCP toolset | A chat session can place orders that collide with the scheduled agent | Alpaca's MCP server is limited to |
|
Also: the agent refuses to start if ALPACA_LIVE_TRADE=true (the CLI's switch to a live account), defaults to
dry-run unless DRY_RUN is literally false, validates watchlist symbols before they reach a subprocess, and
uses Windows Task Scheduler instead of cron.
Not verified yet. Whether Alpaca's bracket legs inherit day (fix 4) is not stated in Alpaca's docs. The
fix doesn't depend on the answer, and the stop-leg check will show the real behaviour on the first live run.
Related MCP server: TradeZylo MCP Server
How a run works
scheduler (every 15 min) ──> python -m risk_agent.agent
market clock open? ── no ──> exit 0, nothing logged
account ACTIVE and not blocked? ── no ──> skip all, exit 1
daily P/L <= -3%? ── yes ──> skip all (circuit breaker)
per symbol:
cancel stale GTC entries from earlier days
entry still working? -> skip
position open? stop leg live? -> skip | no stop -> ALERT, exit 1
already entered today? -> skip
SMA(5) > SMA(15) on completed bars? -> no: skip (with both SMA values)
price >= $1? qty >= 1? -> no: skip
submit limit bracket (entry + stop + take-profit), log the full risk mathEvery symbol ends in exactly one record in data/decisions.jsonl. A failure on one symbol is logged as
error and the others are still evaluated. Exit codes: 0 ok, 1 alert/error/account blocked,
2 broker unreachable, 3 refused to start (config or live-trade guard).
Default risk limits (src/risk_agent/config.py): 0.5% of equity at risk per trade, stop 3% below
reference, take-profit at 2R, at most 20% of equity per symbol, halt at -3% on the day.
Setup (Windows)
# 1. Alpaca CLI: download cli_<ver>_windows_amd64.zip from github.com/alpacahq/cli/releases,
# verify it against checksums.txt, put alpaca.exe on PATH. uv (for Alpaca's MCP server):
winget install astral-sh.uv
# 2. Project
python -m venv .venv
.venv\Scripts\python -m pip install -e ".[dev]" # add ,ui for the dashboard
copy .env.example .env # paste PAPER keys into .env
# 3. Verify, then dry-run
.venv\Scripts\python -m pytest
alpaca doctor
.venv\Scripts\python -m risk_agent.agent # DRY_RUN=true by defaultSet DRY_RUN=false in .env to place real paper orders. To schedule:
powershell -ExecutionPolicy Bypass -File scripts\register_task.ps1.
Asking it why
.mcp.json registers two servers for Claude Code (or any MCP client):
alpaca: Alpaca's official server, read-only toolsets. It readsALPACA_API_KEY/ALPACA_SECRET_KEYfrom your shell environment (it doesn't read.env), so set them there before starting the client.risk-agent-explain: this repo's server, with toolsrecent_decisions,explain_decision,open_positions.
Restart the client after adding servers. Then ask "why did you size AAPL that way?" and the answer comes from the logged risk math, for example: "SMA long signal (short 118.0 > long 113.0); bought 50 sh with limit $312.67 (stop $302.69, take-profit $332.63). Worst-case loss $499.00 vs $500.00 budget; binding constraint: risk (risk allows 50, 20% concentration cap allows 63)."
Dashboard (optional): .venv\Scripts\python -m risk_agent.ui. Known issue: gradio 6.31 requires
pillow<13, and pillow 12.3 has open CVEs fixed in 13.0. The dashboard is localhost-only and never
processes images, so that code isn't reachable here, but it is a real gap in pip-audit. The agent and the
MCP server don't depend on gradio.
Paper execution verification
Pending. No paper fill or live protective-stop observation has been verified yet.
Run .venv\Scripts\python -m risk_agent.paper_verification --execute-paper during market hours.
It requires an initially flat paper account, runs a dry run, submits at most one signal-approved
bracket with DRY_RUN=false, waits for a full fill, checks a covering GTC stop in the broker's open-order
response, and runs the same agent again. It only passes when that next run reports
position already open (stop-loss leg ... live). A missing signal is pending, not success.
On failure it cancels an unfilled test entry and attempts to close an unprotected test position;
any cleanup failure is recorded as ALERT. It never touches preexisting positions.
After a pass it updates this status block and sets .env to DRY_RUN=false.
The raw report and logs remain local in data/paper-verification.json and logs/paper-verification.log.
Limitations
The signal is a toy. A 5/15 SMA crossover has no demonstrated edge, and this repo makes no claim that it does. The point is the execution and risk layer, which doesn't depend on the signal (
strategy.pyis swappable).Long-only, US equities, prices of $1 and up. No options and no shorting.
Sizing uses account equity, which on a margin account can be backed by borrowed buying power. The cap limits concentration per symbol, not gross leverage across symbols.
iexis the default data feed because free accounts can't query recent SIP data. IEX volume is thin, so latest-trade prices can lag the consolidated tape.One entry per symbol per day, by design. A stop-out is not re-entered the same session.
Dry-run never cancels stale entries; they remain visible as working orders and block new entries.
Daily-loss entry halts still audit watchlist positions for missing stops and fail if the audit fails. Monitoring currently runs during the regular market session and covers watchlist symbols only.
A working entry does not suppress a missing-stop alert for an existing position in that symbol.
Paper fill/protective-stop verification status is recorded above. Offline tests include one that runs the real
alpacabinary in--dry-runmode to confirm the flags it builds.
Development
.venv\Scripts\python -m pytest # unit + real-binary dry-run test, coverage gate 80%
.venv\Scripts\ruff check src tests
.venv\Scripts\mypy # strict
.venv\Scripts\pip-auditTool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
AI risk officer: private trading theses, evidence, exit criteria and decision history. No execution.
Read-only access to your MetaTrader 4 and 5 accounts for AI agents: balances, open positions, trade history with win rate, live quotes, symbol specs and candles. It cannot place, modify or close orders.
AI trading partner and trading journal: trades, reports, journaling, market data.
Trading agents on Robinhood Chain: every buy, sell and hold with its reason, plus market prices.
Related MCP Servers
- FlicenseAqualityCmaintenanceEnables agents to generate alpha signals, retrieve market snapshots, compute portfolio risk, validate and submit paper orders, and trigger a kill switch, all under deterministic pre-trade risk controls and audit logging.5-
- AlicenseAqualityCmaintenanceEnables AI assistants to read and write trading journal data, including trade logs, analytics, psychology audits, risk limits, playbooks, and daily reviews. Provides 38 tools across 7 domains plus workflow prompts for pre-market prep and post-session analysis.388 npmMIT
- AlicenseAqualityBmaintenanceEnables AI assistants to trade futures on TopstepX by reading market data, placing and managing orders, tracking positions and P&L, and journaling trades for review.201Apache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables natural-language questions about public and prediction markets, returning structured, source-backed answers drawn from SEC filings, earnings call transcripts, financial metrics, stock and crypto market data, and prediction market research and news. It also exposes live documentation search and reading tools so clients can discover agent workflows and setup guidance in-session.MIT