# dino.markets MCP server

Matched Kalshi and Polymarket markets across sports, crypto, weather, and economics over MCP.

## Links
- Registry page: https://www.getdrio.com/mcp/markets-dino-mcp
- Website: https://dino.markets

## Install
- Endpoint: https://api.dino.markets/v2/mcp/
- Auth: Not captured

## Setup notes
- Remote endpoint: https://api.dino.markets/v2/mcp/

## Tools
- list_markets - List the matched, unified cross-venue catalog as canonical market objects. Each object has id, slug, title, category, market_type, typed context, status, signal, spread_pts, potential_arb_pct, coverage, outcomes (with kalshi/polymarket prices), links, and more. Filter by category and valid context fields, status (open/live/resolving/closed/settled — resolving means the game has ended and settlement is pending), signal (spread or candidates). Sort by start_time (default) or -spread_pts. Arbitrage is a distinct native Opportunity shape, so signal=arb is rejected explicitly; call find_arbitrage instead. Sports support sport+competition (sport keys: baseball, basketball, football, hockey, soccer, tennis, cricket, lol, dota2, valorant, cs2, r6, ow, mma); weather supports location; crypto supports asset; economics supports indicator or institution. market_type (comma-separated: moneyline, outright, total, spread, team_total, advance, weather_high, weather_low, crypto_above, fed_decision, econ_print, cb_decision, or 'all') opts into the derivative families; the default stays moneyline+outright. weather_high/weather_low/crypto_above/fed_decision/econ_print/cb_decision rows are LADDER markets (own row, no game anchor) with per-leg relation (EXACT|OVERLAPS|DERIVED); every ladder row's kalshi_ladder serves the full priced Kalshi bucket axis alongside the served outcomes. weather_high/weather_low: temperature buckets, kalshi_span discloses a 1°F bracket offset, basis discloses the settlement station. crypto_above: cumulative price-threshold legs (not mutually exclusive), band REVIEW always (venues fix at different times off different sources, boundary semantics differ). fed_decision/cb_decision: fixed 5-way rate-decision enum, band REVIEW pending cancellation-handling verification. econ_print: Polymarket bucket axis; relation DERIVED marks a leg whose only Kalshi backing is the cumulative ladder — it serves the Polymarket price alone (kalshi null, never fabricated); factors.poly_leg_coverage/uncovered_legs disclose gaps. Settlement risk detail is in get_market's settlement block. Call list_categories first to discover valid category/context values. This REST snapshot is best-effort and about two minutes delayed on every tier — NOT execution-grade. The real-time, gapless, execution-grade feed is the WebSocket push (Basic/Premium/Pro get the full market stream; Free gets a curated `sample` taste); use watch_markets to get a stream ticket. `has_more` is an upstream page hint — a status-filtered page may be empty even when `has_more=true` (no cursor pagination). Free to any active dino.markets key. Endpoint: https://api.dino.markets/v2/mcp/
- find_arbitrage - Find current confirmed cross-venue arbitrage opportunities between Kalshi and Polymarket. Mirrors GET /v2/arbitrage and returns Opportunity objects, not Market objects: one exact selected execution leg per outcome with ask_usd, stake_fraction, available_contracts, contract_id, and URL. edge_pct and roi_pct include venue fees under fee_model='conservative_per_contract'; max_wager_usd is a conservative fee-inclusive capital estimate because quantity-level venue rounding can differ. The envelope includes as_of and delay_seconds. All values remain snapshot observations, not guarantees. Optionally filter by sport (broad key: baseball, basketball, football, hockey, soccer, tennis, cricket, lol, dota2, valorant, cs2, r6, ow, mma). This REST snapshot is best-effort and about two minutes delayed on every tier — NOT execution-grade. The real-time, gapless, execution-grade feed is the WebSocket push (Basic/Premium/Pro get the full market stream; Free gets a curated `sample` taste); use watch_markets to get a stream ticket. Free to any active dino.markets key. Endpoint: https://api.dino.markets/v2/mcp/
- get_market - Fetch the canonical market object for a single market by its id. Accepts `dino_<uuid>` (from list_markets or find_arbitrage.market_id), a bare UUID, or a persisted slug — the same id resolution as get_settlement. Returns the full canonical object with settlement disclosure (settlement.parity, settlement.risks[]), venue ids, and depth (if priced). Cache this aggressively — settlement changes only when the matcher re-analyses the live text (updated_at moves). Prices change frequently (priced_at). Known limitation: a currently fired arb can still appear as signal='spread' here because this canonical Market view requires both venue prices for every outcome while the arb ledger stores only the selected execution venue per outcome. Use find_arbitrage for the native opportunity shape. Returns 404 if the market is not found. Mirrors GET /v2/pairs/{id}. Free to any active dino.markets key. Endpoint: https://api.dino.markets/v2/mcp/
- get_settlement - Fetch the identity + settlement view of a single market: `{id, slug, title, status, settlement}`. Accepts `dino_<uuid>`, a bare UUID, or a persisted slug. Skips the price join get_market does — settlement is static fine print (parity, risks[], venue text, verdict), not a live quote, so this is cheaper to call and cacheable until updated_at moves. Never returns the raw per-venue Kalshi winner, only the cross-venue agree/diverge verdict. Returns 404 if the market is not found. Mirrors GET /v2/pairs/{id}/settlement. Free to any active dino.markets key. Endpoint: https://api.dino.markets/v2/mcp/
- list_categories - List normalized market categories, market types, and category-valid contextual facets. Call this first to discover valid filters for the other tools. Free to any active dino.markets key. Endpoint: https://api.dino.markets/v2/mcp/
- find_markets - Free-text market/event lookup by team, competition, context, or market title. This is the AGENT FRONT DOOR: call find_markets FIRST to resolve a team or competition name (e.g. 'Yankees', 'EPL', 'Lakers vs Celtics') into a market id before calling get_market, list_markets, or get_spreads — an agent that can't find a market can't use anything else. Matches case-insensitively against team, category, contextual facets, market_type, slugs, and native venue ids. Returns lean canonical market objects (identity only, no live prices, same shape as list_markets) so lookups stay fast; hand the returned id to get_market for pricing and settlement detail. Paginated (page/page_size, max 50 per page). Filter by category, sport, and status (open/live/resolving/closed/settled — default open,live). Mirrors GET /v2/search. Free to any active dino.markets key. Endpoint: https://api.dino.markets/v2/mcp/
- get_spreads - Cross-venue price-gap view over matched pairs whose resolution rule marks them spread-only (never arb-fireable) but that carry a live, disclosed cross-venue price gap. Only verified-band (EXACT/HIGH) rows are returned — this tool inherits the /v2/spreads band allowlist verbatim and never re-filters it. Optionally filter by category, its explicit context fields, and a minimum spread_pts gap (min_gap), capped by limit. Call find_markets first if you need to resolve a team, competition, or context name into a market id to cross-reference a specific game. Mirrors GET /v2/spreads. Free to any active dino.markets key, no tier-specific gate. Endpoint: https://api.dino.markets/v2/mcp/
- get_coverage - Internal coverage census for the matched feed. Most integrations want find_markets instead. Endpoint: https://api.dino.markets/v2/mcp/
- report_bad_arb - Flag a bad or incorrect arbitrage opportunity for operator review. For opp_id, pass the Opportunity id returned by find_arbitrage. Include at least one of: opp_id, reason, sport, market, or detail. Mirrors POST /v2/report-bad-arb. Free to any active key. Endpoint: https://api.dino.markets/v2/mcp/
- watch_markets - Mint a short-lived (~120s) connect ticket for the real-time WebSocket market stream and return the ws_url plus your tier's allowed channels. The agent (or a client SDK) opens the WebSocket; this tool does not hold the connection. Your tier's allowed channels come back in `allowed.channels` (the source of truth; the v2 markets:{sport} channel renaming ships with the WS reshape). Every active subscription gets a ticket — Free is entitled to the curated `sample` + `status` channels only; Basic/Premium/Pro get the full market stream. Channels above your tier come back in `locked` (name, what it carries, which tier unlocks it, price) so what you are not receiving is visible rather than silently absent. A lapsed/inactive key gets a 402 with an upgrade URL. Endpoint: https://api.dino.markets/v2/mcp/

## Resources
Not captured

## Prompts
Not captured

## Metadata
- Owner: markets.dino
- Version: 2.0.0
- Runtime: Streamable Http
- Transports: HTTP
- License: Not captured
- Language: Not captured
- Stars: Not captured
- Updated: Jul 14, 2026
- Source: https://registry.modelcontextprotocol.io
