Skip to main content
Glama
polymarket-mcp-server

polymarket-mcp-server

by ByBastianRok

polymarket-mcp-server

A read-only MCP server for Polymarket. It lets an MCP client (Claude Code, Claude Desktop, …) query markets, order books, price history, wallet positions, and market holders — using Polymarket's three public, unauthenticated APIs.

No trading. No private keys. No signer. No authenticated CLOB endpoints. It only uses the SDK's public read-only client; viem/ethers are not installed (note: @polymarket/client depends on ox, so npm install pulls some crypto primitives transitively, unused here). The market/data tools are readOnlyHint: true; the paper-trading + calibration tools only write a local, gitignored data/ ledger of simulated bets — never real money, no order is ever placed.


What it can do — 23 tools

13 read-only market/data tools, 5 simulated paper-trading tools (local ledger, no real money), and 5 analytics/automation tools.

Tool

API

Purpose

polymarket_search_markets

Gamma

Find markets by keyword, or list top markets by volume.

polymarket_get_market

Gamma

Full detail of one market by slug, incl. CLOB token ids per outcome.

polymarket_get_events

Gamma

Events grouping related markets (a whole tournament/election).

polymarket_get_orderbook

CLOB (SDK)

Live best bid/ask, spread, mid, depth — is an edge executable?

polymarket_get_price_history

CLOB (SDK)

Historical implied probability over a window, with summary stats.

polymarket_get_quote

CLOB (SDK)

Quick midpoint / buy / sell / spread / last-trade for one outcome.

polymarket_get_trades

Data

Recent trades — a market's tape, or a wallet's trade history.

polymarket_get_open_interest

Data

Open interest (capital at stake) for one or more markets.

polymarket_get_leaderboard

Data

Global trader ranking by realized P&L or volume.

polymarket_get_positions

Data

Open positions + P&L for a public wallet.

polymarket_get_closed_positions

Data

A wallet's resolved positions with realized P&L.

polymarket_get_user_activity

Data

A wallet's full activity feed (trades, splits, merges, …).

polymarket_get_market_holders

Data

Largest holders ("whales") of each outcome in a market.

polymarket_paper_open / _status / _close

local

SIMULATED paper trading — record bets to a local ledger (fills at ask + taker fee), mark-to-market, auto-score at resolution, Brier vs the market. Opening is capped by the available virtual bankroll. No real money, no order placed.

polymarket_paper_delete / _reset

local

Rewrite the simulated ledger: drop one bet, or wipe it and start a fresh virtual bankroll (_reset needs confirm: true). Destructive — resolved bets stop counting towards P&L, ROI and Brier.

polymarket_find_arbitrage

CLOB (SDK)

Scan for baskets priced under $1 (Yes+No, or a negRisk event) net of fees — the one edge a read-only bot can detect. Detection ≠ capture.

polymarket_xray

mixed

One-call deep look: detail + quote + whales + price history + trade tape.

polymarket_calibration_snapshot / _report

mixed

Snapshot markets now; when they resolve, score a reliability curve + Brier — is the market well-priced?

polymarket_daily_digest

mixed

A "morning briefing": paper status + arbitrage scan + top movers + calibration status.

The CLOB read tools run on the official @polymarket/client SDK (public read-only client — no keys, no wallet); Gamma and Data run on native fetch. The paper-trading and calibration tools write only a local, gitignored data/ ledger — never real money.


Related MCP server: polymarket-mcp

The identifier model (read this once)

Polymarket uses several ids and it's easy to get lost:

  • A binary market has a human slug, a conditionId, and two clobTokenIds — one per outcome (Yes / No).

  • The order book and price history key on the token_id (a ~77-digit number), not the slug.

Flow: slug → polymarket_get_market gives you the clobTokenIds → CLOB tools use a token_id.

For convenience, the CLOB tools (get_orderbook, get_price_history, get_quote) accept either:

  • token_id directly (preferred if you have it), or

  • slug + outcome (e.g. "Yes") — the server resolves the token id for you via Gamma.


Prerequisites

  • Node.js ≥ 24 (required by the official Polymarket SDK; Gamma/Data still use the built-in fetch). Check with node --version.

    • Windows: winget install OpenJS.NodeJS.LTS or download from nodejs.org.

Install & build

npm install
npm run build      # compiles TypeScript to dist/

Try it with the MCP Inspector

npm run inspector  # builds, then opens the MCP Inspector against dist/index.js

Then call e.g. polymarket_search_markets with { "query": "bitcoin" }.

Register in Claude Code

This repo already ships a project-scoped .mcp.json with a relative path, so it works on any machine once you've run npm install && npm run build from the project root:

{
  "mcpServers": {
    "polymarket": {
      "command": "node",
      "args": ["dist/index.js"]
    }
  }
}

The relative dist/index.js resolves from the project root (where Claude Code is launched). If your client needs an absolute path, substitute the full path to dist/index.js on that machine. No secrets or environment variables are required — everything it touches is public.

Install from a clone

git clone <your-repo-url>
cd polymarket-mcp
npm install
npm run build

Then reload MCP / restart Claude Code (project .mcp.json servers need a one-time approval in an interactive session). Requires Node ≥ 24 on the new machine.


Usage examples

  • "What Polymarket markets are there about the Fed?" → polymarket_search_markets { query: "Fed" }

  • "What's the real spread on Argentina to win the World Cup?" → polymarket_get_orderbook { slug: "will-argentina-win-the-2026-fifa-world-cup-245", outcome: "Yes" }

  • "How has that market moved this month?" → polymarket_get_price_history { slug: "…", outcome: "Yes", interval: "1m" }

  • "How is wallet 0xabc… doing?" → polymarket_get_positions { wallet: "0xabc…" }

  • "Who are the whales on the Yes side?" → polymarket_get_market_holders { slug: "…" }

  • "Give me the full picture on this market" → polymarket_xray { slug: "…", outcome: "Yes" }

  • "Any arbitrage in the top events?" → polymarket_find_arbitrage { scan_top: 10 }

  • "Track a simulated bet" → polymarket_paper_open { slug: "…", outcome: "No", size_usdc: 50, p_estimate: 0.6 }, then polymarket_paper_status

  • "Start the paper lab over" → polymarket_paper_reset { confirm: true, bankroll: 500 } (erases every simulated bet — there is no undo)

  • "My morning briefing" → polymarket_daily_digest


Scheduling the daily digest (Windows)

The server is a local stdio process, so a cloud routine can't reach it. To get the digest unattended, use Windows Task Scheduler to run a headless Claude command with its "Start in" set to the project root:

claude -p "Run polymarket_daily_digest and print it" --allowedTools "mcp__polymarket__polymarket_daily_digest" --output-format text >> "%USERPROFILE%\polymarket-digest.log"

Requires: the PC on/awake at the trigger time; Claude Code installed and authenticated for non-interactive use; the task's Start in = the project folder (so .mcp.json's relative dist/index.js resolves); and the one tool pre-allowed (a scheduled run can't answer permission prompts). Each run consumes Claude usage. (/loop also works, but only while a session stays open; cloud /schedule does not reach a local stdio server.)


Design notes

  • APIs / transport: Gamma gamma-api.polymarket.com and Data data-api.polymarket.com over native fetch; the CLOB reads (order book, price history, quote) go through the official @polymarket/client public client (createPublicClient(), no keys). See src/clobSdk.ts.

  • Rate limits: Gamma allows ~60 req/min unauthenticated. The client backs off exponentially (honoring Retry-After) on 429/5xx and retries transient network errors.

  • Context discipline: responses default to concise Markdown; pass response_format: "json" for full structured data. Every tool also returns machine-readable structuredContent.

  • JSON-string fields: Gamma returns outcomes, outcomePrices, and clobTokenIds as JSON-encoded strings; the client parses and zips them so each outcome is paired with its token id and implied price.

Project layout

src/
  index.ts          # entry: McpServer + stdio transport
  constants.ts      # base URLs, limits
  types.ts          # raw API + normalized types
  client.ts         # PolymarketClient: Gamma/Data fetch+backoff, error mapping, slug→token; CLOB via SDK
  clobSdk.ts        # official @polymarket/client public client + pure response mappers (CLOB reads)
  arbMath.ts        # pure arbitrage math (edge + depth-walked executable size)
  calibrationMath.ts # pure calibration math (buckets, reliability curve, Brier, ECE)
  paperFees.ts      # taker-fee model + fractional-Kelly + Brier (pure)
  paperStore.ts / calibrationStore.ts / dataDir.ts  # local JSON ledgers (gitignored data/)
  schemas.ts        # Zod input/output schemas
  format.ts         # formatting + result/error helpers
  tools/            # one file per tool (23)

Scope / non-goals

Read-only by design. Order placement, cancellation, approvals, or anything requiring a signature/API key is intentionally out of scope — the official SDK is used only via its public read-only client (createPublicClient()), which pulls no wallet/crypto libraries. Global trader rankings are available via polymarket_get_leaderboard; polymarket_get_market_holders covers per-market whale visibility.

License

MIT

Screenshots

How it was built

Most of the code was written by Claude Code. I set the scope, made the design decisions and tested the behaviour.

Available Tools

23 tools
polymarket_calibration_reportCalibration reportA

Score the calibration snapshots: resolve any that have settled since, then compute a reliability curve (predicted vs observed per decile) + Brier score + ECE. Tells you whether the market's prices are honest. Needs elapsed time for markets to resolve, so it's sparse early on.

Args:

  • min_resolved (number, default 1): note if fewer than this have resolved.

Returns: { totalSnapshots, resolvedCount, pendingCount, brier, ece, curve:[{bucket,label,n,predictedMean,observedFreq}] }.

Inputs: min_resolved, response_format. Returns: ece, brier, curve, pendingCount, +2 more

polymarket_calibration_snapshotSnapshot markets for calibrationA

Record a SNAPSHOT of current open markets' implied probabilities (one per outcome) into a local file, so that when they resolve, polymarket_calibration_report can measure whether the market is well-calibrated (do 30% markets resolve Yes ~30% of the time?). Forward-only. Writes a local file; no real money.

Args:

  • query (string, optional): snapshot markets about a keyword; omit for top markets by volume.

  • limit (1-50, default 25), min_volume (default 0, filters dead markets).

Returns: { recorded, skipped, totalSnapshots, byBucket }. Re-running the same day won't double-count.

Inputs: limit, query, min_volume, response_format. Returns: skipped, byBucket, recorded, totalSnapshots

polymarket_daily_digestPolymarket daily digestA
Read-onlyIdempotent

A one-shot "morning briefing": your paper-trading status, a small arbitrage scan, the day's top movers, and your calibration status — all in one call. Read-only vs Polymarket (reads the local ledgers). Meant to be run each morning (see the README for scheduling it on Windows).

Args:

  • arb_scan_top (1-15, default 5): top events to scan for arbitrage.

  • movers_limit (1-15, default 5): how many top markets to rank by 24h move.

Inputs: arb_scan_top, movers_limit, response_format. Returns: arbs, paper, movers, calibration, +1 more

polymarket_find_arbitrageFind Polymarket arbitrageA
Read-onlyIdempotent

Scan for risk-free pricing gaps: a binary market whose best-ask(YES)+best-ask(NO) < $1, or a negRisk event basket whose Σ best-ask(legs) < $1. Fee-aware (reports gross AND net-of-fee edge) and depth-aware (estimates executable size). This is the one edge a read-only bot can DETECT precisely — but detection is not capture.

Args:

  • event_slug (string, optional) OR scan_top (1-25): scan one event, or sweep the top-N events by 24h volume.

  • min_edge_pct (number, default 0.5): only flag arbs whose NET edge% ≥ this.

  • category ('crypto'|'sports'|'politics'|'macro'|'geopolitics'|'other'): taker-fee assumption (geopolitics free).

  • max_legs (number, default 12): skip baskets larger than this.

Returns: { scanned, feePerShare, category, count, arbs:[{ type, title, legs, grossEdge/Pct, netEdge/Pct, executable:{sets,notionalUsd,estNetProfitUsd,bottleneckLeg} }] }.

Inputs: category, max_legs, scan_top, event_slug, +2 more. Returns: arbs, count, scanned, category, +1 more

polymarket_get_closed_positionsGet Polymarket closed positionsA
Read-onlyIdempotent

Get a wallet's CLOSED (resolved) positions with REALIZED profit/loss — the settled history behind polymarket_get_positions (which shows only open positions).

Args:

  • wallet (string): 0x… address (42 chars).

  • limit (number): max closed positions, 1-100 (default 25).

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { wallet, count, totalRealizedPnl, positions:[{ title, slug, outcome, conditionId, avgPrice, totalBought, realizedPnl, curPrice }] }. An unknown wallet returns 0 positions.

Inputs: wallet (required), limit, response_format. Returns: count, wallet, positions, totalRealizedPnl

polymarket_get_eventsGet Polymarket eventsA
Read-onlyIdempotent

Get Polymarket EVENTS, which group related markets under one question (e.g. a tournament or election, with a market per team/candidate).

Use this when a question spans many outcomes: one event carries all its markets. Pass a slug for one event, or omit it for the top events by 24h volume.

Args:

  • slug (string, optional): event slug for one event with all its markets. If omitted, returns top events.

  • limit (number): max events when listing, 1-20 (default 5).

  • active_only (boolean): only open/unresolved events (default true).

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { count, events:[{ slug, title, startDate, endDate, active, closed, volume, liquidity, volume24hr, negRisk, marketCount, markets:[{ question, slug, conditionId, outcomes, volume, closed }] }] }. Errors: "No event found for slug '…'" if the slug is wrong.

Inputs: slug, limit, active_only, response_format. Returns: count, events

polymarket_get_leaderboardGet Polymarket trader leaderboardA
Read-onlyIdempotent

Get the trader LEADERBOARD — top wallets ranked by realized profit (PnL) or traded volume over a time window.

Args:

  • order_by ('PNL' | 'VOL'): rank by profit or volume (default 'PNL').

  • time_period ('DAY' | 'WEEK' | 'MONTH' | 'ALL'): window (default 'MONTH').

  • category (string, optional): e.g. OVERALL, POLITICS, SPORTS, CRYPTO, CULTURE, ECONOMICS, TECH, FINANCE.

  • limit (number): top N traders, 1-50 (default 10).

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { orderBy, timePeriod, count, entries:[{ rank, wallet, name, pnl, volume }] }. This is a global ranking (unlike polymarket_get_market_holders, which is per-market).

Inputs: limit, category, order_by, time_period, +1 more. Returns: count, entries, orderBy, timePeriod

polymarket_get_marketGet one Polymarket marketA
Read-onlyIdempotent

Fetch the full detail of a single market by its slug, including the CLOB token ids for each outcome.

Use this to follow a specific market you already know, or after a search to get the exact token ids needed by the order book / price history tools.

Args:

  • slug (string): the market slug (from polymarket_search_markets).

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { market: { slug, question, conditionId, description, startDate, endDate, negRisk, enableOrderBook, acceptingOrders, active, closed, volume, liquidity, volume24hr, eventSlug, outcomes:[{outcome, tokenId, price, impliedProbabilityPct}] } }.

Errors: "No market found for slug '…'" if the slug is wrong — verify it with polymarket_search_markets.

Inputs: slug (required), response_format. Returns: market

polymarket_get_market_holdersGet Polymarket market holders (whales)A
Read-onlyIdempotent

Get the largest holders of each outcome in a market — the "whales" with the most exposure.

Useful to see who is positioned on each side and how concentrated a market is. Identify the market by slug (preferred, so outcomes get named) OR conditionId.

Args:

  • slug (string, optional): market slug. Provide this OR condition_id.

  • condition_id (string, optional): market conditionId (0x…). Provide this OR slug.

  • limit (number): top holders per outcome, 1-20 (default 5).

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { conditionId, slug, question, outcomes:[{ outcome, tokenId, holders:[{ rank, name, wallet, amountShares }] }] }.

Notes: amounts are share counts (each resolves to $1 if that outcome wins). Anonymous holders show a shortened wallet. This is per-market holder ranking, not a global leaderboard. Errors: "Provide either 'condition_id' or 'slug'"; "No market found for slug…".

Inputs: slug, limit, condition_id, response_format. Returns: slug, outcomes, question, conditionId

polymarket_get_open_interestGet Polymarket open interestA
Read-onlyIdempotent

Get the OPEN INTEREST (total value of outstanding positions) for one or more markets — a measure of how much capital is currently at stake.

Identify markets by conditionId(s), or pass a slug (resolved to its conditionId).

Args:

  • condition_ids (string[], optional): one or more market conditionIds (0x…). Provide this OR slug.

  • slug (string, optional): market slug (resolved to its conditionId). Provide this OR condition_ids.

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { count, totalValue, openInterest:[{ market, value }] }. Errors: "Provide either 'condition_ids' or 'slug'."; "No market found for slug…".

Inputs: slug, condition_ids, response_format. Returns: count, totalValue, openInterest

polymarket_get_orderbookGet Polymarket order bookA
Read-onlyIdempotent

Get the live order book for one market outcome: best bid/ask, spread, mid price, implied probability, and top-of-book depth.

This is where you check whether an edge is real: the implied probability (mid) is the market's estimate, while best ask is what you'd actually pay to buy and best bid what you'd receive to sell. A wide spread or thin depth means the "price" you saw elsewhere may not be executable.

Identify the outcome either by token_id (preferred) OR by slug + outcome.

Args:

  • token_id (string, optional): the ~77-digit CLOB token id for one outcome.

  • slug (string, optional) + outcome (string, optional): e.g. slug + "Yes". Outcome defaults to the first.

  • depth (number): price levels per side to include, 1-50 (default 10).

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { tokenId, outcome, slug, question, bestBid, bestAsk, mid, spread, impliedProbabilityPct, spreadPct, totalBidSize, totalAskSize, bids:[{price,size}], asks:[{price,size}], timestamp }.

Errors: "No market found for slug…" (bad slug); an empty side is reported as bestBid/bestAsk = null.

Inputs: slug, depth, outcome, token_id, +1 more. Returns: mid, asks, bids, slug, +11 more

polymarket_get_positionsGet Polymarket wallet positionsA
Read-onlyIdempotent

Get the open positions and P&L for a public wallet address ("how is this wallet doing").

Returns each position's entry price, current price, current value and profit/loss, plus the wallet's total portfolio value. Read-only and public — anyone's positions are visible by address.

Args:

  • wallet (string): 0x… address (42 chars). The on-chain proxy wallet, not a username.

  • limit (number): max positions, 1-100 (default 25).

  • min_value (number): hide positions worth less than this USD (default 1, filters dust).

  • redeemable_only (boolean): only resolved positions ready to redeem (default false).

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { wallet, portfolioValue, openPositions, totalCurrentValue, totalCashPnl, positions:[{ title, slug, outcome, conditionId, tokenId, size, avgPrice, curPrice, initialValue, currentValue, cashPnl, percentPnl, realizedPnl, redeemable, endDate }] }.

Errors: an invalid address is rejected before any request; an unknown wallet returns 0 positions.

Inputs: wallet (required), limit, min_value, redeemable_only, +1 more. Returns: wallet, positions, totalCashPnl, openPositions, +2 more

polymarket_get_price_historyGet Polymarket price historyA
Read-onlyIdempotent

Get the historical price (implied probability over time) for one market outcome, plus summary stats.

Use this to see how a market moved and where you might have entered or exited. Identify the outcome by token_id (preferred) OR slug + outcome.

Args:

  • token_id (string, optional): the ~77-digit CLOB token id.

  • slug (string, optional) + outcome (string, optional): e.g. slug + "Yes".

  • interval ('1h'|'6h'|'1d'|'1w'|'1m'|'max'): look-back window (default '1w').

  • fidelity (number, optional): minutes between points.

  • max_points (number): downsample to at most this many points (default 150).

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { tokenId, outcome, interval, count, truncated, summary:{first,last,min,max,changeAbs,changePct,from,to}, points:[{t, iso, p}] }. Prices are 0-1 (probability). 'count' is the number of returned points; 'truncated' indicates downsampling.

Inputs: slug, outcome, fidelity, interval, +3 more. Returns: count, points, outcome, summary, +3 more

polymarket_get_quoteGet a quick Polymarket quoteA
Read-onlyIdempotent

Get a lightweight live quote for one market outcome — midpoint, best buy/sell price, spread and last trade — WITHOUT pulling the full order book.

Faster than polymarket_get_orderbook when you just want "what's this worth right now". Identify the outcome by token_id (preferred) OR slug + outcome.

Args:

  • token_id (string, optional): the ~77-digit CLOB token id.

  • slug (string, optional) + outcome (string, optional): e.g. slug + "Yes". Outcome defaults to the first.

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { tokenId, outcome, slug, question, midpoint, buyPrice, sellPrice, spread, spreadPct, impliedProbabilityPct, lastTradePrice, lastTradeSide }. Prices are 0-1 (midpoint ≈ implied probability; buyPrice is what you'd pay, sellPrice what you'd receive). Any value the book can't provide is null. For full depth, use polymarket_get_orderbook.

Inputs: slug, outcome, token_id, response_format. Returns: slug, spread, outcome, tokenId, +8 more

polymarket_get_tradesGet Polymarket tradesA
Read-onlyIdempotent

Get recent trades — either a MARKET's tape (who traded, at what price) or a WALLET's trade history.

Provide market (a conditionId) for the market tape, OR wallet for that address's trades.

Args:

  • market (string, optional): market conditionId (0x…). Provide this OR wallet.

  • wallet (string, optional): 0x… address. Provide this OR market.

  • taker_only (boolean): only taker trades (default true); false adds maker fills for the full tape.

  • limit (number): max trades, 1-100 (default 20).

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { market, user, count, trades:[{ wallet, name, side, outcome, price, size, usdcSize, timestamp, iso, conditionId, title, slug, transactionHash }] }. Errors: "Provide either 'market' or 'wallet'." if neither is given.

Inputs: limit, market, wallet, taker_only, +1 more. Returns: user, count, market, trades

polymarket_get_user_activityGet Polymarket wallet activityA
Read-onlyIdempotent

Get a wallet's full on-chain ACTIVITY feed — beyond open positions: trades plus splits, merges, redeems, rewards, deposits and withdrawals.

Complements polymarket_get_positions (current holdings) and polymarket_get_trades (just trades) with the complete history.

Args:

  • wallet (string): 0x… address (42 chars).

  • type (string[], optional): filter to types like TRADE, SPLIT, MERGE, REDEEM, REWARD, DEPOSIT, WITHDRAWAL (default: all).

  • limit (number): max entries to request, 1-500 (default 50). At most 200 are returned.

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { wallet, count, truncated, activities:[{ type, timestamp, iso, side, outcome, size, usdcSize, price, conditionId, title, slug, transactionHash }] }. The 'truncated' flag is true when more entries existed than were returned. An unknown wallet returns 0 activities.

Inputs: wallet (required), type, limit, response_format. Returns: count, wallet, truncated, activities

polymarket_paper_closeClose a SIMULATED (paper) bet earlyA

Manually close an OPEN paper bet at the current price (models selling before the market resolves). Fills at the executable BID minus the taker fee. No real money.

Args:

  • id (string): the paper bet id (from polymarket_paper_status).

Inputs: id (required), response_format. Returns: bet, bankroll

polymarket_paper_deleteDelete a SIMULATED (paper) betA
Destructive

Permanently remove one bet from the local paper-trading ledger. Works on any status (open, won, lost, closed).

This rewrites simulated history — a deleted resolved bet stops counting towards realized P&L, ROI, hit rate and Brier, so your track record will change. To stop tracking a bet while keeping an honest record, use polymarket_paper_close instead. No real money is involved either way.

Args:

  • id (string): the paper bet id (from polymarket_paper_status).

Inputs: id (required), response_format. Returns: bet, bankroll

polymarket_paper_openOpen a SIMULATED (paper) Polymarket betA

Record a SIMULATED bet in the local paper-trading ledger. No real money, no order is placed — this only writes a local file to track a hypothesis and score it later.

Fills honestly at the executable ASK plus the category taker fee (Polymarket charges takers since 2026-03-30), so the simulated P&L isn't a fantasy. Prefer slug + outcome so the conditionId is captured for auto-scoring at resolution.

Args:

  • token_id (string, optional) OR slug (string) + outcome (string).

  • size_usdc (number): simulated stake (virtual money).

  • p_estimate (number 0-1, optional): your probability for this outcome (for Brier scoring + the Kelly hint).

  • category ('crypto'|'sports'|'politics'|'macro'|'geopolitics'|'other'): taker-fee bucket.

  • note (string, optional): the hypothesis you're testing.

Returns: the recorded bet + a fractional-Kelly sizing hint (full & half) + the virtual bankroll.

Inputs: size_usdc (required), note, slug, outcome, +4 more. Returns: bet, bankroll, kellyFull, kellyHalf

polymarket_paper_resetReset the SIMULATED paper-trading ledgerA
DestructiveIdempotent

Wipe the local paper-trading ledger and start a fresh virtual bankroll. Erases every simulated bet, including resolved ones — realized P&L, ROI, hit rate and Brier all go back to zero. There is no undo.

Requires confirm=true; without it the call is rejected so the ledger can't be wiped by accident. No real money is involved — this only rewrites a local file.

Args:

  • confirm (boolean): must be true to proceed.

  • bankroll (number, optional): new virtual starting bankroll (default 1000).

Inputs: confirm, bankroll, response_format. Returns: bankroll, deletedCount

polymarket_paper_statusPaper-trading status & scoringA

Show the SIMULATED paper-trading ledger: open bets marked-to-market, resolved bets scored automatically (a resolved market pays the winning outcome $1), and totals — realized/unrealized P&L net of fees, ROI, hit rate, and Brier scores (yours vs the market's implied probability at entry) on your probability estimates. No real money anywhere.

Args:

  • response_format ('markdown' | 'json'): default 'markdown'.

Inputs: response_format. Returns: bets, roiPct, hitRate, bankroll, +7 more

polymarket_search_marketsSearch Polymarket marketsA
Read-onlyIdempotent

Discover Polymarket markets by keyword, or list the highest-volume markets.

Use this first to find a market's slug and its current implied probability, then feed the slug into the other tools.

Args:

  • query (string, optional): keyword(s) like 'bitcoin' or 'election'. If omitted, returns the top markets by volume.

  • limit (number): max markets, 1-50 (default 10).

  • active_only (boolean): only open/unresolved markets (default true).

  • response_format ('markdown' | 'json'): default 'markdown'.

Returns: { count, query, markets: [{ slug, question, conditionId, outcomes:[{outcome, tokenId, price, impliedProbabilityPct}], volume, liquidity, volume24hr, endDate, active, closed, acceptingOrders, eventSlug }] }.

Examples:

  • "What markets are there about the Fed?" -> query="Fed".

  • "Show me the biggest markets right now" -> no query. Note: 'price' is the implied probability of that outcome (0-1). For an executable price/spread, use polymarket_get_orderbook.

Inputs: limit, query, active_only, response_format. Returns: count, query, markets

polymarket_xrayX-ray a Polymarket marketA
Read-onlyIdempotent

The one-shot deep look at a market: detail + executable quote + whales + recent price history + recent trade tape, all in one call (several API calls bundled). Identify by token_id OR slug + outcome.

Args:

  • token_id (string, optional) OR slug (string) + outcome (string).

  • history_interval ('1h'|'6h'|'1d'|'1w'|'1m'|'max'): default '1d'.

  • trade_limit (1-50, default 10), holder_limit (1-20, default 5).

Returns: { tokenId, outcome, slug, question, detail, quote, whales, history, tape } (sections null-tolerant).

Inputs: slug, outcome, token_id, trade_limit, +3 more. Returns: slug, tape, quote, detail, +5 more

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 23 tools

    Disambiguation4/5

    Most tools target clearly distinct resources and actions (market vs event vs orderbook vs positions). Composites like polymarket_xray and polymarket_daily_digest bundle existing tools but are explicitly described as shortcuts. Slight potential confusion between polymarket_get_quote and polymarket_get_orderbook, but descriptions clarify.

    Naming Consistency4/5

    All tools share the polymarket_ prefix and snake_case formatting. Most follow a verb_noun pattern (search_markets, get_market, find_arbitrage), but there are mixed verb styles (get_ vs search_ vs paper_ vs xray) and a few noun-first names like calibration_snapshot.

    Tool Count3/5

    At 23 tools, the set is above the typical 3–15 sweet spot and feels heavy for a read-only/paper-trading server. While each tool has a plausible role, several could be consolidated (e.g. paper status/close/delete/reset, calibration snapshot/report) without losing core functionality.

    Completeness4/5

    The surface covers market discovery, detailed data, user analytics, paper trading, arbitrage detection, calibration, and a daily digest. Missing real order execution, order cancellation, and real-time streaming, but those appear intentionally out of scope given the explicit no-real-money design.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      A Model Context Protocol (MCP) server for Polymarket prediction markets, providing real-time market data, prices, and AI-powered analysis tools for Claude Desktop integration.
      48
      MIT
    • F
      license
      A
      quality
      C
      maintenance
      AI-agent ready FastMCP server for Polymarket market discovery, wallet analytics, and public CLOB data, providing a read-only interface for querying markets, wallets, and order books.
      22
      -
    • A
      license
      A
      quality
      C
      maintenance
      A read-only MCP server exposing Polymarket's public prediction-market data. Search markets, read live odds and order books, pull historical probability time-series, and inspect public wallet positions.
      14
      35 PyPI
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      A Model Context Protocol server that enables seamless integration with Polymarket, providing tools to search markets, fetch events, analyze leaderboards, query user activity, and more via MCP-compatible clients like Claude.
      41 npm
      MIT