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
- 01Search and filter matched markets
- 02Retrieve confirmed cross-venue arbitrage
- 03Inspect price gaps and market details
- 04Review settlement differences and match confidence
- 05Watch markets over WebSocket
Use cases
- 01Find related Kalshi and Polymarket markets
- 02Screen for confirmed arbitrage opportunities
- 03Check settlement terms and disclosed risks
- 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.
Tools
Local servers expose tools only once running on your machine, and the maintainer has not provided a tool list.
Details
From the project READMEdino.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
| Transport | Streamable HTTP |
| Endpoint | https://api.dino.markets/v2/mcp/ (trailing slash) |
| Auth | X-API-Key header (Authorization: Bearer also works) — Free tier works |
| Documented public tools | 8 |
| Hosting | Hosted — 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.
| Tier | Price | REST requests/month | REST requests/sec | WebSocket |
|---|---|---|---|---|
| Free | $0/mo | 10,000 | 10 | Curated sample channel, 1 connection |
| Basic | $30/mo | 1,000,000 | 10 | Full market stream, 3 connections |
| Premium | $100/mo | 5,000,000 | 25 | Full market stream, 10 connections |
| Pro | $200/mo | 5,000,000 | 25 | Full stream plus raw quotes and early candidates, 10 connections |
The 8 documented public tools
| Tool | Returns | Tier |
|---|---|---|
find_markets | Free-text lookup by team, league, market title, or market family; returns ids for detail calls | Any active key |
find_arbitrage | Confirmed 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 sport | Any active key |
list_markets | The 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_market | The canonical market object for one market by id (dino_<uuid> or bare UUID), including settlement disclosure and depth | Any active key |
list_leagues | In-season sports and leagues with per-sport open/live/settled counts — call this first | Any active key |
get_spreads | Verified cross-venue price gaps for matched pairs classified as spread-only | Any active key |
report_bad_arb | Flags a bad/incorrect arbitrage opportunity for operator review | Any active key |
watch_markets | Mints a short-lived connect ticket; Free gets sample, paid plans get the full stream | Any 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 bydecide_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 agreesettlement.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.
| Language | Docs | MCP server |
|---|---|---|
| 日本語 | Docs | MCP |
| 한국어 | Docs | MCP |
| 简体中文 | Docs | MCP |
| Español | Docs | MCP |
Links
- llms.txt: https://dino.markets/llms.txt
- OpenAPI: https://api.dino.markets/openapi.json
- Docs: https://dino.markets/docs
- Pricing: https://dino.markets/pricing
- Sibling repo: dino-markets-skills — Agent Skills built on this MCP server
Disclaimer
This is developer data, not trading or financial advice.
Comments
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.