MCP server
A native Model Context Protocol server, so a coding agent can read the matched feed and the live opportunities without writing a client. Free on every plan.
The API is also a native Model Context Protocol server. A coding agent like Claude or Cursor can call the matched feed, the opportunities, and the rest of the catalog as tools, with no client code. The server is free on every plan: the tool listing is open to any key, and the data each tool returns is gated by your key's tier.
The server runs over Streamable HTTP at https://api.dino.markets/v2/mcp/ (note the trailing slash — strict MCP clients/scanners can 502 on the no-slash /v2/mcp → /v2/mcp/ redirect).
Connect
Authenticate with your API key as a bearer token, the same key the REST API uses. Most MCP clients connect through mcp-remote, which bridges your local client to the HTTP endpoint:
{
"mcpServers": {
"dino-markets": {
"command": "npx",
"args": [
"mcp-remote",
"https://api.dino.markets/v2/mcp/",
"--header",
"Authorization:Bearer ${DINO_API_KEY}"
],
"env": { "DINO_API_KEY": "sk_live_..." }
}
}
}
A client that speaks Streamable HTTP directly can point at the URL and send Authorization: Bearer sk_live_... itself, without mcp-remote.
Tools
Each tool mirrors a REST endpoint. Five read the catalog and are free to any active key; watch_markets mints a stream ticket and needs a paid plan. There is no separate pair-list tool in v2; pair detail is folded into get_market.
| Tool | Does | Plan |
|---|---|---|
list_markets | The matched cross-venue catalog as canonical market objects, filterable by sport, league, status, and signal. Mirrors GET /v2/markets. | Any active key |
find_arbitrage | Confirmed cross-venue arbitrage opportunities, filterable by sport. Returns canonical market objects where signal is "arb": confirmed parity, no blocking settlement risk, potential_arb_pct populated. Mirrors GET /v2/markets?signal=arb. | Any active key |
get_market | The canonical market object for one market by id (dino_<uuid> or bare UUID, from list_markets or find_arbitrage), with settlement disclosure, venue ids, and depth. Read this before trading. Mirrors GET /v2/pairs/{market_id}. | Any active key |
list_leagues | The sports and leagues in season, with per-sport open/live/settled counts. Mirrors GET /v2/leagues. | Any active key |
get_coverage | The venue-coverage census: every head-to-head league on Kalshi (wired or not) with its aggregation status, plus the sport-level Polymarket surplus. Mirrors GET /v2/coverage. | Any active key |
report_bad_arb | Flag an opportunity that looks wrong. opp_id takes the market's id value. Mirrors POST /v2/report-bad-arb. | Any active key |
watch_markets | Mint a ticket for the real-time WebSocket stream and return the ws_url plus your tier's allowed channels. Treat allowed.channels in the result as the source of truth; Basic and Pro tokens get the v2 markets:* matched-feed channels. Mirrors POST /v1/stream/token (unchanged in v2). | Basic, Pro |
The data a tool returns matches its REST endpoint, so find_arbitrage and list_markets both return market objects (signal, potential_arb_pct, outcomes). Settlement detail is each venue's own; call get_market (or the REST /v2/pairs/{market_id} endpoint) for the full disclosed-risk detail if your agent needs to inspect divergences before executing.
How tiering shows up
An MCP tool returns data, not an HTTP status, so when your key is not entitled the tool still answers, with the status in the body. A Free key calling watch_markets gets back a 402 and the upgrade URL rather than an error the agent cannot read. That way the agent can branch on the result and tell you to upgrade.
For an agent-readable overview of the whole product, point your agent at /llms.txt.