mcpField
D
dino.markets

dino.markets

Local
dino.marketsFinance0Updated 15w ago

About dino.markets

dino.markets is a hosted MCP server for developers and agents analyzing matched prediction markets on Kalshi and Polymarket. It provides market matches, arbitrage opportunities, and settlement and matching-confidence details.

Key features

  1. 01Search and filter matched markets
  2. 02Retrieve confirmed cross-venue arbitrage
  3. 03Inspect price gaps and market details
  4. 04Review settlement differences and match confidence
  5. 05Watch markets over WebSocket

Use cases

  1. 01Find related Kalshi and Polymarket markets
  2. 02Screen for confirmed arbitrage opportunities
  3. 03Check settlement terms and disclosed risks
  4. 04Subscribe to a real-time market stream

MCP support

The hosted Streamable HTTP MCP server exposes eight documented tools for querying markets, arbitrage, spreads, settlement data, and market watches.

Configuration

Local server config is the same for every client. Copy it into your client’s MCP config file.

mcp.json · Universal config
{
"mcpServers": {
"dino-markets": {
"command": "npx",
"args": [
"-y",
"mcp-remote"
],
"env": {
"DINO_API_KEY": "<DINO_API_KEY>"
}
}
}
}
Run commandnpx -y mcp-remote
Environment variables to set
DINO_API_KEYSecret

Local servers need a runtime on your machine (e.g. Node.js 18+). Config file locations differ by client; see your client’s docs.

Packages
npmmcp-remote

Tools

No tool list yet

Local servers expose tools only once running on your machine, and the maintainer has not provided a tool list.

Details

From the project README

dino.markets MCP

Related Kalshi and Polymarket prediction markets across sports, crypto, weather, and economics over the Model Context Protocol. The hosted server provides the matched catalog, confirmed arbitrage with confidence bands, and a real-time WebSocket stream.

At a glance

TransportStreamable HTTP
Endpointhttps://api.dino.markets/v2/mcp/ (trailing slash)
AuthX-API-Key header (Authorization: Bearer also works) — Free tier works
Documented public tools8
HostingHosted — you don't self-host

Install / connect

Add to Claude Desktop or Cursor (remote MCP over the official bridge):

{
  "mcpServers": {
    "dino-markets": {
      "command": "npx",
      "args": ["mcp-remote", "https://api.dino.markets/v2/mcp/", "--header", "X-API-Key:${DINO_API_KEY}"],
      "env": { "DINO_API_KEY": "sk_live_YOUR_KEY" }
    }
  }
}

An API key is required even on Free — there is no anonymous mode. Get one at https://dino.markets.

Plans and limits

MCP is included on every plan. REST snapshots are best-effort and about two minutes delayed on every plan.

TierPriceREST requests/monthREST requests/secWebSocket
Free$0/mo10,00010Curated sample channel, 1 connection
Basic$30/mo1,000,00010Full market stream, 3 connections
Premium$100/mo5,000,00025Full market stream, 10 connections
Pro$200/mo5,000,00025Full stream plus raw quotes and early candidates, 10 connections

The 8 documented public tools

ToolReturnsTier
find_marketsFree-text lookup by team, league, market title, or market family; returns ids for detail callsAny active key
find_arbitrageConfirmed cross-venue arbitrage between Kalshi and Polymarket as native Opportunity objects — one exact selected execution leg per outcome (venue, ask, size, contract id) — optionally filtered by sportAny active key
list_marketsThe matched cross-venue catalog; filter by sport, league, status, market_type, or signal (spread|candidates — arb is rejected explicitly, see below)Any active key
get_marketThe canonical market object for one market by id (dino_<uuid> or bare UUID), including settlement disclosure and depthAny active key
list_leaguesIn-season sports and leagues with per-sport open/live/settled counts — call this firstAny active key
get_spreadsVerified cross-venue price gaps for matched pairs classified as spread-onlyAny active key
report_bad_arbFlags a bad/incorrect arbitrage opportunity for operator reviewAny active key
watch_marketsMints a short-lived connect ticket; Free gets sample, paid plans get the full streamAny active key

list_markets defaults to moneyline,outright. market_type also accepts total, spread, team_total, advance, weather_high, crypto_above, fed_decision, econ_print, cb_decision, or all. The live tool description and product manual are the source of truth for settlement caveats.

Featured example: find_arbitrage

find_arbitrage returns a distinct Opportunity resource, not a Market object — a fired arb only ever has one selected execution leg per outcome (the venue the engine actually picked), so it can't be represented as a two-sided Market row. This is a deliberate v2 Interface change (2026-07-13): the old GET /v2/markets?signal=arb path is gone — list_markets(signal="arb") now returns a typed error directing you here.

REST equivalent:

curl -s "https://api.dino.markets/v2/arbitrage?sport=baseball" \
  -H "Authorization: Bearer $DINO_API_KEY"

MCP tool call: find_arbitrage() (no args), or find_arbitrage(sport="baseball").

Response envelope ({as_of, delay_seconds, count, opportunities:[...]}), reproduced from the REST API reference rather than a fresh live capture — this repo has no server to hit directly. An empty opportunities array with count: 0 is the normal resting state; a populated one looks like this:

{
  "as_of": "2026-07-13T08:00:05Z",
  "delay_seconds": 120,
  "count": 1,
  "opportunities": [
    {
      "id": "opp_01J2Y9M4X8",
      "market_id": "dino_8f3a1c92-47e8-4c3f-b9d2-f1a8e6c4d5f2",
      "title": "Nyy vs Bos",
      "sport": "baseball",
      "league": "MLB",
      "start_time": "2026-07-13T23:05:00Z",
      "edge_pct": 4.2503,
      "roi_pct": 4.439,
      "fees_included": true,
      "fee_model": "conservative_per_contract",
      "cost_per_payout_usd": 0.957497,
      "max_contracts": 700,
      "max_wager_usd": 670.25,
      "confidence": 1.0,
      "detected_at": "2026-07-13T08:00:00Z",
      "priced_at": "2026-07-13T08:00:05Z",
      "legs": [
        {
          "outcome": "NYY", "venue": "kalshi", "side": "yes",
          "ask_usd": 0.44, "stake_fraction": 0.480419,
          "available_contracts": 1000,
          "contract_id": "KXMLBGAME-NYY-BOS-NYY", "url": null
        },
        {
          "outcome": "BOS", "venue": "polymarket", "side": null,
          "ask_usd": 0.49, "stake_fraction": 0.519581,
          "available_contracts": 700,
          "contract_id": "tok_bos", "url": null
        }
      ]
    }
  ]
}

edge_pct and roi_pct are conservative modeled returns after fees; fees_included is explicit; fee_model: "conservative_per_contract" means the producer models one contract per selected leg and the API scales that cost to max_contracts, so quantity-level venue rounding can differ. ask_usd is USD paid per contract (payout $1 if that outcome wins); max_contracts is the snapshot executable equal contract count per outcome, and max_wager_usd is the conservative fee-inclusive capital estimate at that size. as_of is the newest priced_at in the response — use it, not request time, to judge freshness. Call list_markets (unfiltered, or with signal=spread) to see the matched catalog even when no arb is currently confirmed.

The Market signal vs. the Opportunity resource

list_markets and get_market return canonical Market objects, each carrying its own signal field re-derived on every call — never a cached label:

  • signal:"arb" is earned by decide_signal() on the two-sided catalog join: status open with 2+ confirmations, confirmed settlement parity, no high/critical risk, and every outcome priced on both venues.
  • signal:"spread" is everything else: an observed price gap (spread_pts) that hasn't cleared the arb gates — an observation, not a return you can act on.

These two signals and the find_arbitrage Opportunity are related but not identical: a fired Opportunity's ledger record stores exactly one selected venue per outcome (the side the engine actually chose to execute), while a Market's signal field requires both venues priced on every outcome to call it "arb". Because of that structural difference, get_market/list_markets can show signal:"spread" for a pair find_arbitrage is concurrently reporting as a real, live Opportunity — find_arbitrage is the authoritative collection of currently open, executable arbs. Call it directly rather than filtering list_markets for signal:"arb" (which is rejected explicitly, see above).

Settlement disclosure and confidence bands

Most aggregators give you a number. dino gives you the disclosure to verify it before trading. get_market (and GET /v2/pairs/{id}) returns:

  • settlement.parity (bool) — whether the two venues' settlement terms have been confirmed to agree
  • settlement.risks[] — any disclosed cross-venue divergence (tie handling, cancellation settlement, etc.)
  • settlement.verdict — "agree" | "diverge" | "edge_case" | null (null until the matcher has reconciled the two venues' texts — typically after the market resolves)
  • confidence.entity / confidence.resolution — the matcher's own confidence that the two venues are quoting the same real-world event and will resolve the same way

Read settlement.risks and confidence before treating any arb row as tradeable — the API surfaces the same venue text (settlement.kalshi_text / settlement.poly_text) it used to compute the verdict, so you can check it yourself rather than trust a single number.

Localized documentation

Product documentation is available in these languages. This repository remains the English MCP reference.

LanguageDocsMCP server
日本語DocsMCP
한국어DocsMCP
简体中文DocsMCP
EspañolDocsMCP

Links

Disclaimer

This is developer data, not trading or financial advice.

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.