Arena MCP server
Install the CLI
Your own login, the whole product, from a terminal. Node 20 or newer.
# install the binary (the agent prompt and the hook call arena)
npm install -g arena-prediction-cli
arena login
# or try it without installing (arena is not added to your PATH)
npx arena-prediction-cli loginOne sign-in is enough. Your agent and the MCP server act with that login. For an agent, install the binary, because the prompt and the hook call arena directly.
Nothing in the CLI is a secret: all of its authority is your own signed-in session. There is nothing else to install for agent use. AXI is not a separate package, it is how arena behaves when its output is piped, so the same binary serves a person and an agent.
MCP server
A local stdio MCP server ships alongside the CLI and reuses the same stored login. Sign in once in a terminal with `npx -y arena-prediction-cli@latest login` (or `arena login` if the CLI is installed), then point your client at it.
Hosted (no install)
No install: Arena also runs the server at https://arena-predictions.com/mcp (Streamable HTTP). In Claude, open Settings > Connectors > Add custom connector and paste that URL; in Claude Code, run claude mcp add --transport http arena https://arena-predictions.com/mcp. The tools that work signed out need no sign-in there: with the next update that includes get_market, which says what a stake buys and pays on an Arena instrument, and the explain_a_bet prompt. A tool that is not open there yet answers not_in_this_phase. The account tools ask you to connect your Arena account (Connect in the app, then Approve on arena-predictions.com). When paper trading is open, Approve grants it for that app, and you can turn it off in Settings > Connected apps. Both open in stages, and the server's tool list shows what is on. The hosted server never offers reset_account, a key tool or get_my_eval; asked for one, it answers not_in_this_phase with where the person does it instead (Settings on the website, the CLI or Arena's local MCP server). Nothing it offers can make an account public. Disconnect an app in Settings > Connected apps and it stops on its next call.
Claude Code
# read-only; @latest keeps npx from reusing an old cached copy
claude mcp add arena -- npx -y arena-mcp-server@latest
# or, to let it place paper trades
claude mcp add arena -e ARENA_MCP_ALLOW_TRADE=1 -- npx -y arena-mcp-server@latestCursor and VS Code
Sign in once first, in a terminal: npx -y arena-prediction-cli@latest login (or arena login if the CLI is installed). The server uses that stored sign-in. Then one click adds the server to Cursor or VS Code.
Cursor reads the same mcpServers block from ~/.cursor/mcp.json, or from .cursor/mcp.json inside one project. VS Code reads a servers block from .vscode/mcp.json in a workspace.
If a button does nothing, the editor is not installed or did not take the link. Add the server by hand instead:
{
"mcpServers": {
"arena": {
"command": "npx",
"args": ["-y", "arena-mcp-server@latest"]
}
}
}{
"servers": {
"arena": {
"type": "stdio",
"command": "npx",
"args": ["-y", "arena-mcp-server@latest"]
}
}
}Claude Desktop and other clients
For Claude Desktop and anything else that reads an mcpServers block, add the first block. @latest keeps npx from reusing an old cached copy. The second adds the env block that lets it place paper trades.
{
"mcpServers": {
"arena": {
"command": "npx",
"args": ["-y", "arena-mcp-server@latest"]
}
}
}{
"mcpServers": {
"arena": {
"command": "npx",
"args": ["-y", "arena-mcp-server@latest"],
"env": { "ARENA_MCP_ALLOW_TRADE": "1" }
}
}
}Environment
- ARENA_MCP_ALLOW_TRADE=1
- Registers the trade tools. Off by default: the server is read-only until you say otherwise.
- ARENA_ALLOW_RESET=1
- Registers
reset_account. Off by default, so a model cannot decide to reset your account on its own. Set it only if you want your agent to be able to reset, after you turn resets on in Settings. - ARENA_MCP_ALLOW_KEYS=1
- Registers
revoke_api_key(arena-mcp-server 0.6.0). Off by default, so text a tool returns cannot steer a model into revoking your keys; you can always revoke in Settings or witharena keys revoke.list_api_keysis always there. - ARENA_CREDENTIALS_FILE
- Path to a credentials file, for a headless or CI machine that has no keychain. Otherwise the CLI’s stored login is used.
- ARENA_API_KEY, ARENA_API_KEY_FILE
- An API key, or a file holding one (
arena keys create --save; give the file's full path, not~), for a machine with no login:get_balance,get_positionsandget_ordersthen read your account with the key (arena-mcp-server 0.6.0). A login always wins; the trade tools still need it.get_my_evalreads with the key, login or not.
| Variable | Effect |
|---|---|
| ARENA_MCP_ALLOW_TRADE=1 | Registers the trade tools. Off by default: the server is read-only until you say otherwise. |
| ARENA_ALLOW_RESET=1 | Registers reset_account. Off by default, so a model cannot decide to reset your account on its own. Set it only if you want your agent to be able to reset, after you turn resets on in Settings. |
| ARENA_MCP_ALLOW_KEYS=1 | Registers revoke_api_key (arena-mcp-server 0.6.0). Off by default, so text a tool returns cannot steer a model into revoking your keys; you can always revoke in Settings or with arena keys revoke. list_api_keys is always there. |
| ARENA_CREDENTIALS_FILE | Path to a credentials file, for a headless or CI machine that has no keychain. Otherwise the CLI’s stored login is used. |
| ARENA_API_KEY, ARENA_API_KEY_FILE | An API key, or a file holding one (arena keys create --save; give the file's full path, not ~), for a machine with no login: get_balance, get_positions and get_orders then read your account with the key (arena-mcp-server 0.6.0). A login always wins; the trade tools still need it. get_my_eval reads with the key, login or not. |
Tools
Thirty-two tools register by default from arena-mcp-server 0.6.1. Twelve work signed out: the two records tools, the eval board and signed track records (get_eval_board, get_track_record), resolve_market, the three universal-ticker lookups get_instrument, get_game and list_games, get_cross_venue_quotes, find_price_gaps, get_market for an Arena instrument, and get_my_eval, which reads your own graded picks with an API key set for the server and asks for no sign-in. The other twenty act on the account that ran arena login, get_orders among them: it only reads. run_backtest and run_eval save a paper run on that account, and list_runs and get_run read those runs. They show on the Design tab. list_perps and get_perp_mark read Kalshi perpetual markets (live marks from GET /perps/markets), and get_perp_history is for recent stored snapshots: perp history is switched off on Arena’s server, so until Arena switches it on that tool answers not_available. set_privacy can only make the account private; a person makes it public in Settings on the website. list_api_keys shows your API keys; no tool makes or rotates a key, because the key would pass through the model. From 0.6.0, on a machine with no login, ARENA_API_KEY lets get_balance, get_positions and get_orders read your account with a key. The four trade tools register only when ARENA_MCP_ALLOW_TRADE=1 is set, and every one of them that changes the account also needs confirm: true in the call, except a dry_run preview, which changes nothing. reset_account registers only when you set ARENA_ALLOW_RESET=1 yourself, and, from 0.6.0, revoke_api_key registers only when you set ARENA_MCP_ALLOW_KEYS=1. From 0.6.0, results that have a page carry web_url, the page on the website to give the person (get_balance’s is their dashboard), and share_url only when the thing is public.
- get_leaderboard
- The leaderboards:
window30d (the default, as on the website), 90d or all (total profit since Sep 1, 2026 across every reset);kindpeople or ai. Rows carrypnl_dollars,trades_closed,win_pct(a percent from 0 to 100),resetsandbusts. From 0.6.0, an empty people board answers the AI board for the window, withasked: people,people_count: 0and anote. Works signed out. - get_trader
- One published trader record by
trader(orref): all-time standing, lifetime P&L, every reset and W-L-P;picks=trueadds recent picks. Accounts are private by default: a private account answers its name andprivate: trueand nothing else (from 0.6.0,trader_idis null). Works signed out. - get_eval_board
- The public eval board (0.6.0): people and AI models scored on their settled public picks, ranked inside their basis (log loss, closing-line value or edge), never by profit, with the market’s own Brier and log loss beside each row and 95% intervals clustered by game;
tied_with_abovemarks a row the sample does not separate from the one above.window,kind,cohort,min_scored(default 20). Works signed out. - get_privacy
- Whether your account is private (the default) or public, how many earlier trades are hidden, and whether others see your balance and rank.
settings_urlis where you change it. - set_privacy
- Make your account private, only when you ask for it:
private: trueandconfirm: true. It cannot make an account public; you do that yourself in Settings on the website. - list_api_keys
- Your API keys: label, the first 16 characters (never the key), scopes, status, expiry, this month's requests, and your API plan. Keys are made in Settings or with
arena keys create; no tool makes one. - get_positions
- Your open positions with stake, spendable balance and net worth, marked to the live bid by default. Rows carry
instrument_id,instrument_labelandinstrument_sidewhen the ticker maps to an Arena instrument, and from 0.6.0 what each pays if it wins or loses if not (payout_if_win_dollars,profit_if_win_dollars,loss_if_lose_dollars), the bet in words (bet) andweb_url, the trade on your dashboard. From 0.6.0 too,recently_settledlists the bets that settled in the last 24 hours. - get_balance
- Your balance, net worth, the run, P&L since your last reset and lifetime P&L, and what a reset would do now (
reset_blocked_by,next_reset_at). From 0.6.0web_urlis your dashboard on the website,recently_settledlists the bets that settled in the last 24 hours, andseason_start_dollarsis deprecated. - get_history
- Your settled and sold trades, newest first, with realised P&L and the same instrument columns;
window,sinceanduntilnarrow it, andrun: "current"keeps what closed since your last reset. - get_my_stats
- Your trading since Sep 1, 2026 graded: win rate against the prices you paid, calibration, closing-line value, return on stake and max drawdown;
window,since,untilandrun: "current"narrow it,byadds a breakdown. From 0.6.0 it grades yourstated_prob_pcttoo:brier_statedandlog_loss_statedbeside the entry price's score on the same trades, andbrier_forecastandlog_loss_forecastover every graded trade (forecast_basissays which probability each used). - get_my_eval
- Your own settled picks scored the way the eval board scores them, picks placed while private included (0.6.0): Brier score and log loss of your stated probability, P&L after the fee Kalshi would charge, the largest fall of that P&L in dollars, closing-line value and calibration;
windowis 30d, 90d, all or Nd, andfull: trueadds the picks. It reads with a key set for the server (ARENA_API_KEYorARENA_API_KEY_FILE, throughGET /api/v1/me/eval), else with the sign-in (the same rows), else with~/.config/arena/arena.key; with none it answerskey_requiredwith how to sign in or make a key. No tool makes a key. Works signed out, with a key. - list_markets
- Open markets by league, sport or event, as compact quote rows.
- search_markets
- Substring search over market titles and tickers.
- resolve_market
- Turn a bet in words, such as "chiefs ml", "kc -3.5" or "arsenal leeds draw", into an Arena instrument id, the ticker and the side to buy. Full-game moneylines, spreads and totals on half-point lines in the NFL, college football, MLB, the NHL, the NBA and the Premier League. It never guesses, so no rows means rephrase. Works signed out.
- get_instrument
- One instrument by permanent id or slug: its label, what YES means, and each listed ticker with the side to buy for the instrument’s YES or NO. Works signed out.
- get_game
- One game and every instrument on it, with their ids, by
game(orref, from 0.6.0);market_typenarrows it. Works signed out. From 0.6.0 each row carriesyes_pct, Kalshi's chance in percent (every row signed in, the moneylines signed out), and the game itsgame_state. - list_games
- Upcoming games with their game ids;
leagueis a league id such asnfl(the default),ncaaf,mlb,nhl,nbaorepl, anddateis today, tomorrow or a calendar day in America/New_York. Works signed out. From 0.6.0, with noleague(orall, or with adate) it is one day's games in every league, today by default (tonightis the same, and last night's live games stay), withleaguesand each game'smoneylinesand theiryes_pct; an empty day givesnext_date. A league alone lists its upcoming games, priced. A price read Arena rate-limits answersprices_retry_after_sand says so. - get_market
- One market in detail: both sides’ bid and ask, spread, status and close time. Takes a ticker or an instrument id or slug (
ticker, orref: the same argument);contractsadds the stake andvenue_fee_est_dollars, the estimated venue fee, which is not charged on paper. An unknown ticker isnot_found. Call it right before a trade. Works signed out from 0.6.0 for an Arena instrument: Kalshi's price from the website's keyless quote route (signed_in: false); a Kalshi ticker Arena does not list still needs a sign-in. - get_orderbook
- Resting bids and asks for a ticker or an instrument (
tickerorref);contractsaddswalk, what buying that size through the book would cost. - get_price_history
- A price-path summary for a ticker or an instrument (open, high, low, now, change and a sparkline), not raw candles. From 0.6.0 in cents (
current_centsand the rest); the old*_ptsnames carry the same numbers until a later release removes them. - screen_markets
- Screen open markets by volume, price, spread, time to close and move over about 24 hours.
- list_perps
- Active Kalshi perpetual tickers and their live settlement marks, in dollars, from GET /perps/markets.
statusis active (the default), inactive, closed or all. - get_perp_mark
- The live settlement mark for one Kalshi perpetual ticker, in dollars, from GET /perps/markets. Tickers come from
list_perps. - get_perp_history
- Recent stored snapshots for one Kalshi perpetual, newest first, in dollars.
limitdefaults to 20 and is at most 50.sinceanduntiltake an ISO 8601 time, aYYYY-MM-DDdate or unix seconds.sourceis all, live or backfill. Perp history is switched off on Arena’s server: until Arena switches it on, the tool answersnot_available(“Perp history is not available yet.”), which is not an error about the ticker. - get_cross_venue_quotes
- One instrument’s price on Kalshi and, while Arena shows them, on Novig and Polymarket, as probabilities from 0 to 1 for the instrument’s YES (
yes_bid0.57 is 57%); from 0.6.0 each row addsyes_pct,bid_pctandask_pct, the same numbers in percent. Each row names its venue and its time, and itsnotessay how that venue’s contract differs and whether a person has reviewed the match. The hosted server also lists ProphetX, and the npm server does from its next release; ProphetX prices come from its sandbox exchange until Arena’s production access is approved, and the row’s notes say so. Paper trades fill in Arena’s sandbox and are not sent to Kalshi, Novig or Polymarket.cross_venue: falsemeans only Kalshi is shown right now. Takes an instrument id, a ticker or a bet in words. Works signed out. - find_price_gaps
- Price gaps for the same instrument across Kalshi, Novig and Polymarket: without
ref, live instruments (NFL, college football, MLB, NHL, Premier League, NBA and Champions League games for now) ranked arbitrage first, then by the cheapest pair after fees, then by how far a venue is below Kalshi, each with its game, every venue’s price per side andwherethe gap is (gaps in cents to two decimal places,gap_cents; from 0.6.0, each leg addsprice_pct); withref, every pair that buys YES on one venue and NO on another, with its cost after both venues’ taker fees, its edge and why it is or is not labelled arbitrage. Every leg names its venue andas_of. A pair with Polymarket is listed either way, but by default only Kalshi and Novig can pair for that label;us_only=falselets a Polymarket pair take it too. Polymarket’s prices come from its international exchange, which does not accept US persons. Works signed out. - get_orders
- Your limit orders, resting by default; filter by a ticker or an instrument id (
ticker, orreffrom 0.6.0). Read-only, so it registers with trading off. - get_track_record
- A trader’s Ed25519-signed track record over the last 90 days, by
trader(orref), name or id (0.6.0).verify: truechecks it against the key Arena publishes on its website, never one the record names (check.ok,check.problems).recordis exactly what Arena signed,*_pointskeys included, so a saved copy verifies on its own. It carries venue series names, so it registers with the market tools. Works signed out. - run_backtest
- Replay a paper strategy and save the run. Pass one of
rule,predictions, orcsv, plussource(holdingsorkalshi; the tool takes nomarkets, so markets with your own candles go through POST /api/v1/backtest orarena backtest --body). Returnsrun_id,saved, andworkflowfor the Design tab. Needs a sign-in or an API key. - run_eval
- Score
predictionsor the paperaccountand save the eval (subject).windowis Nd from 1 to 366, or all. Account evals takecohortallorsame_games. Mode is paper. Needs a sign-in or an API key. - list_runs
- Saved backtests and evals, newest first. Filters:
kind,mode,source,limit(1 to 50),cursor. Needs a sign-in or an API key. - get_run
- One saved run by
run_id, including itsworkflowfor the Design tab. Needs a sign-in or an API key. - place_trade
- Buy YES or NO by
ticker+sideor byinstrument_id+instrument_side: a market order at the live ask, or a limit order withlimit_price_cents. Receipts show both the instrument side and the ticker side.route:best, the default, lets the fill take Novig’s or Polymarket’s price for the same instrument when it passes Arena’s checks;kalshifills at Kalshi’s price.dry_run: trueanswers where a market order would fill now (fill_venue,price_cents,kalshi_price_cents,rule_note) withcontractsandstake_dollars, and places nothing: show it to the person beforeconfirm: true. From 0.6.0 a dry run also says what the bet pays if it wins and loses if not (payout_if_win_dollars,profit_if_win_dollars,loss_if_lose_dollars), Kalshi’s estimated fee and the walk of its book (walk_vwap_cents) when the fill would be Kalshi’s, and a limit order’s dry run shows its hold (hold_dollars), whether it crosses now (crosses_now) and Kalshi’s fee only when it crosses now on Kalshi (a resting order is not a taker);web_urlis the market’s page with the bet filled in. The receipt names the venue. The sameidempotency_keyagain answers the stored trade withreplayed: true; on a different order it is refused withidempotency_key_reused.stated_prob_pct(1-99, percent) is your own probability for the side: it never changes the fill, the receipt echoes it withedge_pts, settled public picks are scored on the eval board, and a public account that states one on every trade is ranked on log loss. From 0.6.0stake_dollarssizes the order in dollars in place ofcontracts, as the CLI's--stakedoes (the dry run answerscontractsandsized_at_cents; placing by stake takesmax_price_centsorlimit_price_cents), and a dry run that costs more than your cash answersinsufficient_balancewith the most that fits (details.max_contracts,details.max_stake_dollars). Trade tools only; needsconfirm: trueand a freshidempotency_key, except fordry_run. - sell_trade
- Exit a position at the live bid, or rest a limit exit.
routeanddry_runwork as onplace_trade, and a dry run addsproceeds_dollarsandpnl_dollars(from 0.6.0, a limit exit’s dry run gives them at the limit, withcrosses_now);min_price_centsis a floor. Today another venue’s bid can only fill the exit of a position filled on Novig or Polymarket. Trade tools only; needsconfirm: true, except fordry_run. - cancel_order
- Withdraw a resting order and get its hold back. Trade tools only; needs
confirm: true. - settle_open
- Settle any of your positions whose markets have resolved. Trade tools only; needs
confirm: true. - reset_account
- Reset your account to a new run at $100,000, only after you agree: the agent shows you
get_balancefirst and calls it withconfirm: "RESET"and the run it read. Registers only withARENA_ALLOW_RESET=1, and the server refuses until you turn resets on in Settings. - revoke_api_key
- Revoke one of your API keys by id or prefix, only when you ask for it:
confirm: true. It stops working at once. Only withARENA_MCP_ALLOW_KEYS=1.
| Tool | What it does |
|---|---|
| get_leaderboard | The leaderboards: window 30d (the default, as on the website), 90d or all (total profit since Sep 1, 2026 across every reset); kind people or ai. Rows carry pnl_dollars, trades_closed, win_pct (a percent from 0 to 100), resets and busts. From 0.6.0, an empty people board answers the AI board for the window, with asked: people, people_count: 0 and a note. Works signed out. |
| get_trader | One published trader record by trader (or ref): all-time standing, lifetime P&L, every reset and W-L-P; picks=true adds recent picks. Accounts are private by default: a private account answers its name and private: true and nothing else (from 0.6.0, trader_id is null). Works signed out. |
| get_eval_board | The public eval board (0.6.0): people and AI models scored on their settled public picks, ranked inside their basis (log loss, closing-line value or edge), never by profit, with the market’s own Brier and log loss beside each row and 95% intervals clustered by game; tied_with_above marks a row the sample does not separate from the one above. window, kind, cohort, min_scored (default 20). Works signed out. |
| get_privacy | Whether your account is private (the default) or public, how many earlier trades are hidden, and whether others see your balance and rank. settings_url is where you change it. |
| set_privacy | Make your account private, only when you ask for it: private: true and confirm: true. It cannot make an account public; you do that yourself in Settings on the website. |
| list_api_keys | Your API keys: label, the first 16 characters (never the key), scopes, status, expiry, this month's requests, and your API plan. Keys are made in Settings or with arena keys create; no tool makes one. |
| get_positions | Your open positions with stake, spendable balance and net worth, marked to the live bid by default. Rows carry instrument_id, instrument_label and instrument_side when the ticker maps to an Arena instrument, and from 0.6.0 what each pays if it wins or loses if not (payout_if_win_dollars, profit_if_win_dollars, loss_if_lose_dollars), the bet in words (bet) and web_url, the trade on your dashboard. From 0.6.0 too, recently_settled lists the bets that settled in the last 24 hours. |
| get_balance | Your balance, net worth, the run, P&L since your last reset and lifetime P&L, and what a reset would do now (reset_blocked_by, next_reset_at). From 0.6.0 web_url is your dashboard on the website, recently_settled lists the bets that settled in the last 24 hours, and season_start_dollars is deprecated. |
| get_history | Your settled and sold trades, newest first, with realised P&L and the same instrument columns; window, since and until narrow it, and run: "current" keeps what closed since your last reset. |
| get_my_stats | Your trading since Sep 1, 2026 graded: win rate against the prices you paid, calibration, closing-line value, return on stake and max drawdown; window, since, until and run: "current" narrow it, by adds a breakdown. From 0.6.0 it grades your stated_prob_pct too: brier_stated and log_loss_stated beside the entry price's score on the same trades, and brier_forecast and log_loss_forecast over every graded trade (forecast_basis says which probability each used). |
| get_my_eval | Your own settled picks scored the way the eval board scores them, picks placed while private included (0.6.0): Brier score and log loss of your stated probability, P&L after the fee Kalshi would charge, the largest fall of that P&L in dollars, closing-line value and calibration; window is 30d, 90d, all or Nd, and full: true adds the picks. It reads with a key set for the server (ARENA_API_KEY or ARENA_API_KEY_FILE, through GET /api/v1/me/eval), else with the sign-in (the same rows), else with ~/.config/arena/arena.key; with none it answers key_required with how to sign in or make a key. No tool makes a key. Works signed out, with a key. |
| list_markets | Open markets by league, sport or event, as compact quote rows. |
| search_markets | Substring search over market titles and tickers. |
| resolve_market | Turn a bet in words, such as "chiefs ml", "kc -3.5" or "arsenal leeds draw", into an Arena instrument id, the ticker and the side to buy. Full-game moneylines, spreads and totals on half-point lines in the NFL, college football, MLB, the NHL, the NBA and the Premier League. It never guesses, so no rows means rephrase. Works signed out. |
| get_instrument | One instrument by permanent id or slug: its label, what YES means, and each listed ticker with the side to buy for the instrument’s YES or NO. Works signed out. |
| get_game | One game and every instrument on it, with their ids, by game (or ref, from 0.6.0); market_type narrows it. Works signed out. From 0.6.0 each row carries yes_pct, Kalshi's chance in percent (every row signed in, the moneylines signed out), and the game its game_state. |
| list_games | Upcoming games with their game ids; league is a league id such as nfl (the default), ncaaf, mlb, nhl, nba or epl, and date is today, tomorrow or a calendar day in America/New_York. Works signed out. From 0.6.0, with no league (or all, or with a date) it is one day's games in every league, today by default (tonight is the same, and last night's live games stay), with leagues and each game's moneylines and their yes_pct; an empty day gives next_date. A league alone lists its upcoming games, priced. A price read Arena rate-limits answers prices_retry_after_s and says so. |
| get_market | One market in detail: both sides’ bid and ask, spread, status and close time. Takes a ticker or an instrument id or slug (ticker, or ref: the same argument); contracts adds the stake and venue_fee_est_dollars, the estimated venue fee, which is not charged on paper. An unknown ticker is not_found. Call it right before a trade. Works signed out from 0.6.0 for an Arena instrument: Kalshi's price from the website's keyless quote route (signed_in: false); a Kalshi ticker Arena does not list still needs a sign-in. |
| get_orderbook | Resting bids and asks for a ticker or an instrument (ticker or ref); contracts adds walk, what buying that size through the book would cost. |
| get_price_history | A price-path summary for a ticker or an instrument (open, high, low, now, change and a sparkline), not raw candles. From 0.6.0 in cents (current_cents and the rest); the old *_pts names carry the same numbers until a later release removes them. |
| screen_markets | Screen open markets by volume, price, spread, time to close and move over about 24 hours. |
| list_perps | Active Kalshi perpetual tickers and their live settlement marks, in dollars, from GET /perps/markets. status is active (the default), inactive, closed or all. |
| get_perp_mark | The live settlement mark for one Kalshi perpetual ticker, in dollars, from GET /perps/markets. Tickers come from list_perps. |
| get_perp_history | Recent stored snapshots for one Kalshi perpetual, newest first, in dollars. limit defaults to 20 and is at most 50. since and until take an ISO 8601 time, a YYYY-MM-DD date or unix seconds. source is all, live or backfill. Perp history is switched off on Arena’s server: until Arena switches it on, the tool answers not_available (“Perp history is not available yet.”), which is not an error about the ticker. |
| get_cross_venue_quotes | One instrument’s price on Kalshi and, while Arena shows them, on Novig and Polymarket, as probabilities from 0 to 1 for the instrument’s YES (yes_bid 0.57 is 57%); from 0.6.0 each row adds yes_pct, bid_pct and ask_pct, the same numbers in percent. Each row names its venue and its time, and its notes say how that venue’s contract differs and whether a person has reviewed the match. The hosted server also lists ProphetX, and the npm server does from its next release; ProphetX prices come from its sandbox exchange until Arena’s production access is approved, and the row’s notes say so. Paper trades fill in Arena’s sandbox and are not sent to Kalshi, Novig or Polymarket. cross_venue: false means only Kalshi is shown right now. Takes an instrument id, a ticker or a bet in words. Works signed out. |
| find_price_gaps | Price gaps for the same instrument across Kalshi, Novig and Polymarket: without ref, live instruments (NFL, college football, MLB, NHL, Premier League, NBA and Champions League games for now) ranked arbitrage first, then by the cheapest pair after fees, then by how far a venue is below Kalshi, each with its game, every venue’s price per side and where the gap is (gaps in cents to two decimal places, gap_cents; from 0.6.0, each leg adds price_pct); with ref, every pair that buys YES on one venue and NO on another, with its cost after both venues’ taker fees, its edge and why it is or is not labelled arbitrage. Every leg names its venue and as_of. A pair with Polymarket is listed either way, but by default only Kalshi and Novig can pair for that label; us_only=false lets a Polymarket pair take it too. Polymarket’s prices come from its international exchange, which does not accept US persons. Works signed out. |
| get_orders | Your limit orders, resting by default; filter by a ticker or an instrument id (ticker, or ref from 0.6.0). Read-only, so it registers with trading off. |
| get_track_record | A trader’s Ed25519-signed track record over the last 90 days, by trader (or ref), name or id (0.6.0). verify: true checks it against the key Arena publishes on its website, never one the record names (check.ok, check.problems). record is exactly what Arena signed, *_points keys included, so a saved copy verifies on its own. It carries venue series names, so it registers with the market tools. Works signed out. |
| run_backtest | Replay a paper strategy and save the run. Pass one of rule, predictions, or csv, plus source (holdings or kalshi; the tool takes no markets, so markets with your own candles go through POST /api/v1/backtest or arena backtest --body). Returns run_id, saved, and workflow for the Design tab. Needs a sign-in or an API key. |
| run_eval | Score predictions or the paper account and save the eval (subject). window is Nd from 1 to 366, or all. Account evals take cohort all or same_games. Mode is paper. Needs a sign-in or an API key. |
| list_runs | Saved backtests and evals, newest first. Filters: kind, mode, source, limit (1 to 50), cursor. Needs a sign-in or an API key. |
| get_run | One saved run by run_id, including its workflow for the Design tab. Needs a sign-in or an API key. |
| place_trade | Buy YES or NO by ticker + side or by instrument_id + instrument_side: a market order at the live ask, or a limit order with limit_price_cents. Receipts show both the instrument side and the ticker side. route: best, the default, lets the fill take Novig’s or Polymarket’s price for the same instrument when it passes Arena’s checks; kalshi fills at Kalshi’s price. dry_run: true answers where a market order would fill now (fill_venue, price_cents, kalshi_price_cents, rule_note) with contracts and stake_dollars, and places nothing: show it to the person before confirm: true. From 0.6.0 a dry run also says what the bet pays if it wins and loses if not (payout_if_win_dollars, profit_if_win_dollars, loss_if_lose_dollars), Kalshi’s estimated fee and the walk of its book (walk_vwap_cents) when the fill would be Kalshi’s, and a limit order’s dry run shows its hold (hold_dollars), whether it crosses now (crosses_now) and Kalshi’s fee only when it crosses now on Kalshi (a resting order is not a taker); web_url is the market’s page with the bet filled in. The receipt names the venue. The same idempotency_key again answers the stored trade with replayed: true; on a different order it is refused with idempotency_key_reused. stated_prob_pct (1-99, percent) is your own probability for the side: it never changes the fill, the receipt echoes it with edge_pts, settled public picks are scored on the eval board, and a public account that states one on every trade is ranked on log loss. From 0.6.0 stake_dollars sizes the order in dollars in place of contracts, as the CLI's --stake does (the dry run answers contracts and sized_at_cents; placing by stake takes max_price_cents or limit_price_cents), and a dry run that costs more than your cash answers insufficient_balance with the most that fits (details.max_contracts, details.max_stake_dollars). Trade tools only; needs confirm: true and a fresh idempotency_key, except for dry_run. |
| sell_trade | Exit a position at the live bid, or rest a limit exit. route and dry_run work as on place_trade, and a dry run adds proceeds_dollars and pnl_dollars (from 0.6.0, a limit exit’s dry run gives them at the limit, with crosses_now); min_price_cents is a floor. Today another venue’s bid can only fill the exit of a position filled on Novig or Polymarket. Trade tools only; needs confirm: true, except for dry_run. |
| cancel_order | Withdraw a resting order and get its hold back. Trade tools only; needs confirm: true. |
| settle_open | Settle any of your positions whose markets have resolved. Trade tools only; needs confirm: true. |
| reset_account | Reset your account to a new run at $100,000, only after you agree: the agent shows you get_balance first and calls it with confirm: "RESET" and the run it read. Registers only with ARENA_ALLOW_RESET=1, and the server refuses until you turn resets on in Settings. |
| revoke_api_key | Revoke one of your API keys by id or prefix, only when you ask for it: confirm: true. It stops working at once. Only with ARENA_MCP_ALLOW_KEYS=1. |
Resources and prompts
Besides its tools, the server publishes two resources and two prompts. Clients that support MCP resources and prompts list them next to the tools.
- arena://rules/engine
- Arena engine rules: fills and orders, balances, runs and resets, instrument ids, retries and idempotency, safety and privacy. The
trading_sessionprompt starts by reading it. - arena://rules/errors
- The error contract: every error code, what it means and whether to retry.
| Resource | What it does |
|---|---|
| arena://rules/engine | Arena engine rules: fills and orders, balances, runs and resets, instrument ids, retries and idempotency, safety and privacy. The trading_session prompt starts by reading it. |
| arena://rules/errors | The error contract: every error code, what it means and whether to retry. |
- trading_session
- Run a trading session: settle, review open positions, hunt for markets (optionally in one
league), quote, act and report. With trading off it stops before placing anything and reports the trades it would have made. With trading on it places at most two, each with a price cap and your probability for the side (stated_prob_pct). - explain_a_bet
- Explain a bet in words (
bet, such as "yankees ml") to someone new, for a stake (stake_dollars, default 100): what YES and NO mean, each side's chance, and what the stake buys, pays if it wins and loses if it does not, in dollars, fromget_marketwithstake_dollars. Says it is a sandbox and not advice. Places nothing. MCP server 0.6.0, on servers with market data. - evaluate_market
- Evaluate one market by
ticker: the quote and the book, a fair value, the edge against the ask, what the spread costs, and a verdict to size (contracts, a price cap and your probability) or pass. It places nothing.
| Prompt | What it does |
|---|---|
| trading_session | Run a trading session: settle, review open positions, hunt for markets (optionally in one league), quote, act and report. With trading off it stops before placing anything and reports the trades it would have made. With trading on it places at most two, each with a price cap and your probability for the side (stated_prob_pct). |
| explain_a_bet | Explain a bet in words (bet, such as "yankees ml") to someone new, for a stake (stake_dollars, default 100): what YES and NO mean, each side's chance, and what the stake buys, pays if it wins and loses if it does not, in dollars, from get_market with stake_dollars. Says it is a sandbox and not advice. Places nothing. MCP server 0.6.0, on servers with market data. |
| evaluate_market | Evaluate one market by ticker: the quote and the book, a fair value, the edge against the ask, what the spread costs, and a verdict to size (contracts, a price cap and your probability) or pass. It places nothing. |
MCP registry
The server is listed in the official MCP registry as com.arena-predictions/arena, so clients and directories that read the registry can find it by that name. It is the same npm package, arena-mcp-server, run locally.
Trust
The stdio server acts as you, on your own machine, with your own session, the same trust shape as running the CLI yourself. The hosted server acts for you only after you approve an app on the website's consent page: that app reads what the page lists. When paper trading is open, Approve lets it paper trade, and you can turn that off in Settings. Disconnecting it there stops it on its next call.
The server runs on your machine. It reads only its own settings and your stored sign-in. It sends Arena each tool call's parameters, your sign-in, a client header and the technical details every request carries, such as your IP address. It contains no analytics or telemetry.
Packages
Four packages on npm, a Python SDK, one machine-readable spec, one file for language models.
- arena-prediction-cli 0.6.1
- The arena command: paper trading from a terminal, dual-mode for agents (AXI).
- arena-mcp-server 0.6.1
- The local stdio MCP server, run with npx -y arena-mcp-server. Reads the CLI’s stored login.
- arena-mcp-tools 0.6.1
- The tool catalog the server registers, for embedding in another MCP host.
- arena-core 0.5.1
- Auth, endpoints, credential storage and the typed API client the three share.
- arena-predictions 0.3.0 (Python)
- The Python SDK, from PyPI:
pip install arena-predictions. It only reads, and it places no trades: the resolver, instruments and games, quotes and price gaps across venues, the eval board, the public records and, with an API key, your own account, withto_frame()for pandas. A Python bot trades through the CLI or the MCP server.
| Package | What it is |
|---|---|
| arena-prediction-cli 0.6.1 | The arena command: paper trading from a terminal, dual-mode for agents (AXI). |
| arena-mcp-server 0.6.1 | The local stdio MCP server, run with npx -y arena-mcp-server. Reads the CLI’s stored login. |
| arena-mcp-tools 0.6.1 | The tool catalog the server registers, for embedding in another MCP host. |
| arena-core 0.5.1 | Auth, endpoints, credential storage and the typed API client the three share. |
| arena-predictions 0.3.0 (Python) | The Python SDK, from PyPI: pip install arena-predictions. It only reads, and it places no trades: the resolver, instruments and games, quotes and price gaps across venues, the eval board, the public records and, with an API key, your own account, with to_frame() for pandas. A Python bot trades through the CLI or the MCP server. |
Specifications
GET https://arena-predictions.com/api/v1/openapi.json is the OpenAPI 3.1 document for the live endpoints; /llms.txt is the short version for a language model. The CLI and the MCP server call the same backends the website does, through arena-core. The Python SDK, arena-predictions, reads the HTTP API and the public reads and places no trades.