sportsdata-mcp
The sportsdata-mcp server exposes ~500 read-only tools across 28+ sports-data providers, enabling AI agents to compare odds, fetch live scores and stats, analyse racing form, access prediction markets, and retrieve content from official league APIs.
Cross-bookmaker odds comparison – Compare prices across 11+ bookmakers (Sportsbet, TAB, Ladbrokes/Entain, PointsBet, BetR, Unibet, Pinnacle, Betfair Exchange, Dabble, FanDuel) using capability-tagged tools (e.g. sport.event_markets) for direct cross-provider comparison.
Real-time sports data – Fixtures, results, standings, player/team stats, and match details for:
AFL, NRL, NBA, MLB, Premier League, LaLiga, Serie A, NBL, WTA, Cricket Australia
Formula 1 (OpenF1): lap timing, pit stops, telemetry, race control messages
ESPN: scoreboard, standings, news across any sport/league ESPN covers
Racing (thoroughbred, greyhound, harness) – Race meetings, racecards, form guides, tote pools, price fluctuations, market movers, and next-to-jump feeds from Sportsbet, TAB, PointsBet, BetR, Betfair, FanDuel Racing, and Racing and Sports.
Prediction markets – Query Kalshi (CFTC-regulated) and Polymarket (crypto) for market catalogues, order books, price history, and trades.
Fantasy & analytics – SuperCoach projections, ownership, and prices across 7 sports (AFL, NRL, EPL, NBA, NBL, NFL, BBL); Data Golf skill ratings, strokes-gained breakdowns, pre-tournament/in-play predictions, and DFS projections.
Content & social – News, video, photos, and articles from AFL and Cricket Australia APIs; Twitter/X tweet search, user timelines, and trends (requires Bearer token).
Discovery & configuration – Meta-tools (list_available_groups, list_tools_by_capability) let models discover enabled providers and find comparable tools. Enable only the tool groups you need via YAML config or environment variables; specs can be refreshed OTA without reinstalling.
Allows retrieval of Contentful CMS entries (e.g., promotions, major-event navigation) via the Entain/Ladbrokes provider.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@sportsdata-mcpcompare AFL odds for Collingwood vs Essendon across Sportsbet and Entain"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
sportsdata-mcp
Ask your AI which bookmaker is paying more — and get a real answer.
Free & open source (MIT). ~500 tools across 28 providers in Claude Desktop,
Cursor, or any MCP client. uvx sportsdata-mcp serve and you're done.
You: Which book has the best price on Parramatta v Penrith, and how big is the spread?
Claude queries five books at once and comes back with:
Book | Eels | Panthers |
Betfair | 1.18 | 6.20 |
BetR | 1.17 | 5.00 |
PointsBet | 1.17 | 4.80 |
Pinnacle | 1.17 | 4.78 |
Sportsbet | 1.19 | 4.75 |
Real captured odds. The same bet on Penrith pays $6.20 at Betfair and $4.75 at Sportsbet — a 30% spread on identical risk. That gap is invisible unless something is reading every book at once.
What this one is for: comparing prices, not just fetching scores. Plenty of sports MCP servers will get you fixtures and standings. This one is built around disagreement between books — eleven bookmakers, the Betfair exchange, and two prediction markets (Kalshi, Polymarket) side by side on the same market, plus fourteen official league/stats feeds. Deep on AU/NZ books (Sportsbet, TAB, Ladbrokes, PointsBet, BetR, Dabble) and on racing — thoroughbred, greyhound and harness with tote pools and exchange money — which most catalogues skip entirely. Capability tags make providers interchangeable, so "compare odds across books" is one question rather than twenty-eight integrations.
Built on this server
Two live terminals, both open source, both running on nothing but these tools:
sportsdata-ai.com/sports — prediction markets + exchange as a de-vigged sharp line, every book measured against it.

sportsdata-ai.com/board — racing money flow: which runners are firming, fair price vs the field, win%/ROI scorecard.

Try these once it's installed
"Compare head-to-head odds across every book for tonight's NRL games."
"Which AFL games have the biggest price disagreement between bookmakers?"
"What does Betfair imply for the Panthers vs what Sportsbet is offering?"
"Show me Pinnacle's line on every MLB game today."
"Pull the ladder and last five results for Hawthorn."
An MCP server that exposes sports-data APIs (bookmakers, league/governing-body feeds, aggregators) as tools, configurable so you only load the tool groups you need. A capability-tag system makes tools from different providers interchangeable wherever they answer the same question — so the model can compare odds across bookies or stats across data sources with one discovery call.
The catalogue spans bookmakers, league/governing-body feeds, and stats
aggregators, and it keeps growing. New providers are added by dropping a YAML
spec into src/sportsdata_mcp/specs/ — the engine needs no code changes — so
the exact provider and tool counts move over time. Run sportsdata-mcp list-groups for the live inventory, and three meta-tools (group discovery,
capability lookup, resource listing) are always on regardless of what you
enable.
Install
One-liner (any MCP client config, via uv):
uvx sportsdata-mcp serve # or: pip install sportsdata-mcpPrebuilt app (no Python needed): grab the latest
release
(macOS + Windows), unzip, and run sportsdata-mcp setup — it writes the config
for Claude Desktop / Cursor for you. The macOS build is unsigned for now:
right-click → Open the first time.
From source:
git clone https://github.com/DanielTomaro13/sportsdata-mcp.git
cd sportsdata-mcp
pip install -e . # add ".[dev]" for the test + lint toolchainRelated MCP server: AltSportsData MCP Server
Quickstart
sportsdata-mcp version # print version info
sportsdata-mcp list-groups # see every available tool group
sportsdata-mcp lint # validate the packaged specs
sportsdata-mcp doctor # probe enabled groups for reachability + auth
sportsdata-mcp serve # start the MCP stdio server (default command)
sportsdata-mcp update-specs # OTA-refresh provider specs (signed bundle); --clear revertsProvider endpoints drift (e.g. Entain rotates its GraphQL persisted-query hashes).
update-specs fetches a signed spec bundle and applies it into an overlay under
~/.sportsdata/spec-overlay, which the loader prefers over the packaged copy — so a drift
fix doesn't need a whole new app build. The bundle is Ed25519-verified against a baked key
(a product build refuses an unsigned/forged bundle; anti-rollback refuses a stale replay).
Publish one with scripts/publish-spec-bundle.py; point --url / $SPORTSDATA_SPEC_FEED_URL
at the asset. Restart the server after applying.
Enable tool groups with a config file or the SPORTSDATA_MCP_GROUPS env var:
SPORTSDATA_MCP_GROUPS="afl.public.core,sportsbet.racing,entain.graphql" sportsdata-mcp serveSee examples/ for Claude Desktop / Claude Code config snippets,
a worked cross-bookie odds-comparison prompt,
and an NBA shot-chart + box-score walkthrough that
shows the nba_stats_call dispatcher pattern end to end.
Configuration
Config is resolved in this order (first hit wins):
--config <path>flag$SPORTSDATA_MCP_CONFIG./sportsdata-mcp.yaml~/.config/sportsdata-mcp/config.yamlbuilt-in defaults
# sportsdata-mcp.yaml
enabled_groups:
- afl.public.core
- sportsbet.racing
- entain.graphql
providers: # all optional; sensible defaults apply
sportsbet:
request_timeout_seconds: 30
rate_limit_rps: 10 # sustained requests/sec (token bucket)
max_response_bytes: 0 # 0 = no cap (default); set a positive byte count to guard context
secrets: {} # for authenticated providers; prefer env vars in prodA provider whose auth reads env: SOME_VAR is satisfied by the real environment
variable first, then by a secrets: { SOME_VAR: "..." } entry of the same name
(a local-dev convenience — keep real secrets in the environment in production).
Environment variables
Variable | Effect |
| Comma-separated group list; overrides |
| Path to a config file (see resolution order above). |
| Global response-size cap in bytes for every provider that doesn't set its own |
| Dormant — the product is free; nothing requires a licence. The signed-entitlement machinery remains for anyone self-hosting gated premium feeds (see below). |
| Only relevant with the dormant entitlement gate above. Normally unset. |
The (dormant) entitlement gate
This project used to be a paid product. It's free now — no licence exists or is
needed, and every group serves by default — but the signed-entitlement machinery
(Ed25519-verified feed grants, offline caching, 15-min revalidation) is kept dormant
rather than deleted: it's tested, harmless when unset, and useful to anyone
self-hosting this server who wants to gate premium feeds for their own users. Set
SPORTSDATA_LICENSE + SPORTSDATA_ENTITLEMENT_URL against your own issuing service
to activate it; leave them unset (the default) and nothing changes.
Keyed feeds. A few providers need an upstream credential you supply yourself —
e.g. DATAGOLF_KEY for DataGolf, X_BEARER_TOKEN for Twitter/X. Everything else
needs no key at all.
Meta-tools (list_available_groups, list_tools_by_capability, list_resources)
are always registered regardless of what is enabled, so a fresh install can still
guide the model to turn groups on.
On the response-size cap. There is no cap by default — every tool returns
whatever the upstream API sends. If you want to guard the model's context window you
can opt in to a cap: precedence is providers.<id>.max_response_bytes >
SPORTSDATA_MCP_MAX_BYTES > the default (0, unlimited). Be aware that very large
payloads (e.g. Sportsbet's full *_event_markets firehose, ~2 MB) won't fit in
Claude's ~200 K-token context regardless — for those, prefer a narrower tool such as
sportsbet_sports_card with includeTopMarkets: true.
Tool groups
Run sportsdata-mcp list-groups for live counts and descriptions.
AFL — api.afl.com.au
Group | Tools | Notes |
| 22 | Competitions, seasons, rounds, fixtures, ladders, match stats |
| 9 | Broadcast regions, guides, providers |
| 8 | News/articles, videos, photos |
| 1 | CFS premium ops — needs the anonymous |
| 1 | StatsPro ops — needs the |
| 1 | HLS video URL signing |
Sportsbet — sportsbet.com.au
Group | Tools | Notes |
| 15 | Race meetings, racecards, results, futures, SRMs |
| 14 | Sport events, markets, prices, SGMs |
| 12 | Live status, commentary, ladders, promos, video |
| 2 | Resulted events by date |
| 1 | Persisted GraphQL gateway ( |
Entain / Ladbrokes — ladbrokes.com.au
Group | Tools | Notes |
| 13 | Navigation quick-links and REST surfaces |
| 1 | 127 persisted GraphQL ops ( |
| 1 | Contentful CMS entries (promotions, major-event nav) |
PointsBet — pointsbet.com.au
Group | Tools | Notes |
| 10 | Sports catalogue, competition/event feeds, full event markets, in-play, search |
| 11 | Meetings, racecards, results, futures, SRMs, tips, form |
| 3 | Promotions, promo-code splash, + |
TAB — tab.com.au
Group | Tools | Notes |
| 9 | Dates, meetings, racecards (fixed + parimutuel), form, next-to-go, jackpots, futures |
| 9 | Sports/competitions tree, full match markets + SGM, focused match markets, next-to-go, results, multi-builder |
| 4 | Featured/live recommendations + |
Unibet — unibet.com.au
Group | Tools | Notes |
| 1 |
|
| 3 |
|
BetR — betr.com.au (BlueBet platform)
Group | Tools | Notes |
| 8 | Next-to-jump, today's/grouped racecards, race card, form, fluctuations, movers |
| 7 | Event types, competition categories, event markets, match detail, popular SGMs |
| 4 | Promotions + featured racing + popular market links |
Pinnacle — pinnacle.com (sharp odds)
Group | Tools | Notes |
| 13 | Sports/leagues, full + highlighted + live + per-league matchups, carousel, matchup detail, straight + parlay markets (American-odds prices) |
| 4 | Enums, market-label dictionary, teaser definitions, API status |
Betfair Exchange — betfair.com.au (exchange odds)
Group | Tools | Notes |
| 3 |
|
| 1 |
|
| 5 | Live scores, event details, timeline (single + batch), scores+broadcast |
Dabble — dabble.com.au (iOS app backend)
Group | Tools | Notes |
| 5 | Discover any competition (active list / name lookup / sports), then its fixtures (embedded markets + decimal odds) + the full per-fixture book (400+ markets + Pick'em props) |
The Australian social-betting app's backend, read directly. Reached by posing
as the iOS app — the spec bakes the app's User-Agent + x-device-id +
x-app-version so the public feeds return JSON anonymously. AU-only and
Cloudflare-fronted (403s from non-AU IPs, like the other AU books). Works for
any competition — dabble_active_competitions lists the ~269 currently-bettable
ones across all sports. Read-only odds — no bet placement.
Composes with the other books via sport.event_markets / sport.prices.
SuperCoach — supercoach.com.au (News Corp / Champion Data fantasy)
Group | Tools | Notes |
| 6 | One uniform surface across all 7 games (afl/nrl/epl/nba/nbl/nfl/bbl) × 2 modes ( |
News Corp / Champion Data's salary-cap fantasy game. Every feed lives under
/{year}/api/{sport}/classic/v1/… — pass sport (one of the seven) and year
(the season key: current calendar year for afl/nrl, currently 2025 for the
others, which run across the new year). No auth, not geo-blocked (runs in CI).
The core supercoach_players feed is per-round and large (~1–3 MB); use ppts1
(the real projection), not ppts. Adds the fantasy / projections angle via
stats.fantasy_projections alongside Data Golf. See
documentation/SuperCoach.md.
NBL — nbl.com.au (Australian National Basketball League)
Group | Tools | Notes |
| 14 | Seasons, teams, ladder, schedule (scores), players + rosters, per-player season stats + game-log box scores, team stats, season stat leaders (sortable), and news |
The league's own site data API — a Redis-cached proxy ("rosetta") over Genius
Sports stats at prod.rosetta.nbl.com.au/get/…. No token, but referer-gated
(403s without an nbl.com.au Origin + Referer — both baked into the spec). Every
response is enveloped {type, count, source, data:[…]}. Season-scoped by year
(the season start year: 2025 = NBL26, current); stat-leaders takes the season UUID
from nbl_seasons. Distinct from the SuperCoach nbl fantasy feed — this is the
official box-score source. See documentation/NBL.md.
WTA — wtatennis.com (Women's Tennis Association, official)
Group | Tools | Notes |
| 8 | Official WTA API: singles/doubles rankings, player catalogue + profiles + match history, tournament calendar + per-edition results + entry lists (seeds) |
The WTA's official data API (api.wtatennis.com/tennis/…) — public Spring REST,
no auth/key, no geo-block, runs in CI. Rankings need type+metric
(rankSingles+singles or rankDoubles+doubles); tournaments are keyed by
tournamentGroup.id + year (Australian Open = group 901). Fills the tennis gap on
the stats side, composing with the bookmakers' live tennis markets. See
documentation/WTA.md. (ATP has no equivalent open API —
atptour.com is Cloudflare bot-protected — so it isn't modelled.)
Racing and Sports — racingandsports.com.au
Group | Tools | Notes |
| 3 | Today's race meetings (all codes, verified) + sports match list + per-race odds (token) |
Data Golf — datagolf.com (needs a key)
Group | Tools | Notes |
| 3 | Player list, tour schedule, current event field |
| 11 | DG rankings, pre-tournament (+ archive) + in-play model probabilities, skill + approach-skill ratings, player/live SG decompositions, live strokes-gained, live hole stats, DFS projections |
| 3 | Outright + matchup + all-pairings odds across ~13 books (incl. model line) |
| 9 | Archived raw round data, event-level results (finishes/earnings/points), historical bookmaker odds (outrights + matchups) and DFS results |
Needs a Data Golf API key in the DATAGOLF_KEY env var (a personal subscription
key — sourced via the static_query auth scheme, never stored in the repo).
FanDuel — fanduel.com (US)
Group | Tools | Notes |
| 4 |
|
| 2 |
|
NRL — mc.championdata.com
Group | Tools | Notes |
| 4 | Champion Data match centre: competitions, fixture, per-match player stats, app settings |
Plus the nrl://stats/definitions resource (dictionary of every NRL stat code).
NBA — cdn.nba.com + stats.nba.com
Group | Tools | Notes |
| 5 | Open CDN JSON: today's scoreboard, full schedule, live box score + play-by-play, odds |
| 2 |
|
nba_stats_call fronts the whole stats.nba.com /stats/ analytics surface (player/team
dashboards, box scores v2+v3, shot charts, play-by-play, leaders, standings, draft, hustle,
tracking, …). Browse every operation, its required params and its defaults in the
nba://stats/operations resource.
ESPN — espn.com JSON feeds
Group | Tools | Notes |
| 5 | Site API convenience endpoints: scoreboard, teams, standings, game summary, news |
| 1 |
|
| 1 |
|
| 1 |
|
| 1 |
|
All ESPN tools are parametric over sport + league slugs (e.g. football/nfl,
basketball/nba, soccer/eng.1), so the five groups cover every league ESPN
carries. Browse each dispatcher's operations in its espn://{site,core,web,cdn}/operations
resource.
OpenF1 — api.openf1.org (Formula 1, no key)
Group | Tools | Notes |
| 3 | Grand Prix weekends (meetings), sessions (the fixtures feed), driver roster |
| 5 | Session classification, starting grid, drivers'/constructors' championship standings, overtakes |
| 5 | Per-lap sector + speed-trap timing, pit stops, tyre stints, live gaps/intervals, track position |
| 2 | Car telemetry (speed/throttle/brake/gear/RPM/DRS) + (x,y,z) location at ~3.7 Hz |
| 3 | Race-control messages (flags/SC/incidents), team-radio clips, weather |
Free, no-auth public REST surface (auth: none). Scope feeds by session_key /
meeting_key (both accept the literal latest) and driver_number; discover keys
with openf1_sessions / openf1_meetings first.
Cricket Australia — cricket.com.au (no key)
Group | Tools | Notes |
| 7 | Fixtures (the |
| 3 | Full scorecard (innings batting/bowling/wickets), run-graph series, live video streams |
| 2 | Pulselive CMS: video/text/audio/playlist content list + curated playlists |
Two no-auth hosts (apiv2.cricket.com.au/web + the Pulselive CMS). The apiv2
endpoints carry jsconfig=eccn:true by default so they return the documented
camelCase shape; flow is cricketaustralia_fixtures → cricketaustralia_scorecard?fixtureId= →
cricketaustralia_players?playerIds=.
MLB — statsapi.mlb.com (official Stats API, no key)
Group | Tools | Notes |
| 22 | Sports/leagues/divisions/conferences, teams (+ single, affiliates, history, uniforms), rosters, alumni, coaches, personnel, players (profile, batch, search, season catalogue, changes feed), venues, seasons (current + full history) |
| 5 | Games by date / range / team, plus postseason (schedule, series, tune-in) and tied games |
| 10 | Boxscore, linescore, play-by-play, v1.1 |
| 9 | Standings, season stats, one-player stats, league + team leaders, team-season stats, game pace, high/low records |
| 15 | Draft (+ prospects), awards (catalogue + recipients), attendance, transactions, free agents, jobs (umpires/datacasters/scorers), Home Run Derby, All-Star ballots |
| 1 |
|
The official MLB Stats API the MLB-StatsAPI library wraps, read directly (no key) —
comprehensive coverage of the public surface. sportId=1 is MLB; discover ids
with mlb_teams / mlb_schedule / mlb_player_search, then drill into a game or
player. Most tools accept the API's hydrate string to embed related objects in one
call.
Premier League — premierleague.com (no key)
Group | Tools | Notes |
| 7 | Competitions, season structure, awards, the league table, current gameweek, geo |
| 10 | Teams (+ batch), squads, form (single + all-teams), team stats, next fixture, club metadata |
| 8 | Fixtures/results feed + match centre: detail, events, lineups, team stats (~200 Opta metrics), officials, commentary |
| 8 | Player directory, profiles (basic/career/season), batch lookup, season + competition stats, metadata |
| 2 | Player + team stat leaderboards (sort by any Opta metric) |
| 8 | Editorial content/search, latest+popular news/video, broadcasting schedule |
The private JSON APIs that power premierleague.com, read directly (no key,
no cookies) across three hosts (the SDP stats platform, the editorial/
broadcast api.premierleague.com, and static config on resources.premierleague.com).
Underlying data is Opta. Premier League = competition 8; season id is the
starting year (2025 = 2025/26). Flow: pl_teams → pl_matches → a match id →
pl_match/pl_match_stats; pl_standings for the table. Unofficial/undocumented —
respect the ~5 rps rate limit. The SDP wire params (_limit, _sort,
kickoff>/kickoff<) are exposed under clean tool names (limit, sort,
kickoff_after/kickoff_before).
LaLiga — apim.laliga.com (public key shipped)
Group | Tools | Notes |
| 6 | Competitions, season instances (subscriptions), league table, rounds/matchweeks |
| 3 | Season team list, single team, club squad |
| 3 | Every-player season stats (≈749, full Opta metrics), player profile + stats |
| 2 | Matches feed + single-match detail |
The private JSON API behind laliga.com (Azure APIM), read directly. Underlying
data is Opta. A public Ocp-Apim-Subscription-Key is shipped as a
working default, so it runs out of the box — but the key rotates; override it
with LALIGA_SUBSCRIPTION_KEY (env or secrets:) when reads start 401-ing
(re-harvest from laliga.com's __NEXT_DATA__). A "subscription" is a season
instance (slug laliga-easports-2025 = 2025/26); detail endpoints are keyed by
slug. Pairs with the Premier League provider for cross-league football
comparison via the shared stats.ladder / sport.fixtures_by_date /
stats.player_season tags.
Serie A — api-sdp.legaseriea.it (no auth)
Group | Tools | Notes |
| 3 | All competitions, the 41-season catalogue, single-season detail |
| 6 | League table (overall/home/away), the 20 teams, every-player + team Opta stats (paginated), all 380 matches, match lineups |
The public SDP JSON API behind legaseriea.it, read directly (no auth).
Underlying data is Opta. The Serie A competition id is baked in, so you only
ever supply a seasonId (discovered from seriea_seasons; seasonName like
2025/2026). Player stats return identity and ~279 Opta metrics in one call
(no squad endpoint), paginated 30/page with category=General|Goalkeeping.
Completes the big-three football leagues alongside Premier League + La Liga via
the shared stats.ladder / sport.fixtures_by_date / stats.player_season tags.
Kalshi — kalshi.com (prediction markets, no key)
Group | Tools | Notes |
| 6 | Market catalogue + detail, order book, public trades, OHLC candlesticks (single + batch) |
| 9 | Events, series catalogue (by category), single series, milestones, MVE combo collections, entity registry |
| 3 | Exchange status, trading schedule, announcements |
The CFTC-regulated US event-contract exchange. Market data is public — no
key required; optionally set KALSHI_API_KEY_ID + KALSHI_PRIVATE_KEY(_PATH)
and every request is RSA-signed for Kalshi's higher authenticated rate limits
(needs pip install "sportsdata-mcp[kalshi-auth]"). Trading surfaces stay out
of scope (read-only provider). Id chain:
kalshi_series_list(category) → kalshi_events → kalshi_markets →
orderbook/trades/candles by ticker. Prices are dollar-denominated.
Polymarket — polymarket.com (prediction markets, no key, geo-gated)
Group | Tools | Notes |
| 9 | Markets/events/series/sports/tags catalogue + site search (the discovery plane) |
| 6 | Order book, best price, midpoint, spread, price history, CLOB catalogue |
| 2 | Public trade tape + top holders |
The largest crypto prediction market. All read endpoints are anonymous —
the wallet keys Polymarket's SDKs use are for order placement only (out of
scope). ⚠️ Geo-gated: Polymarket drops connections at the network edge
from restricted jurisdictions (verified: AU IPs time out on every host) — run
from an unrestricted region or VPN. Flow: polymarket_events → a market's
clobTokenIds → polymarket_book / polymarket_price_history.
X (Twitter) — api.x.com (needs a Bearer token)
Group | Tools | Notes |
| 7 | 7-day search, volume counts, post lookup (batch + single), quote/repost/like engagement |
| 6 | Profile lookup (handle/id, batch), user timelines, mentions |
| 2 | Trends by location (WOEID) + project usage/cap monitor |
The X API v2 read surface — no anonymous tier, so a Bearer token is
required: env X_BEARER_TOKEN first (an operator can ship a deployment-wide
token for all its users), then the config secrets: block (each user their
own). The env var holds the bare token; the spec adds Bearer . Mind your
tier's monthly read cap (twitter_usage); the spec throttles ~0.5 req/s and
never auto-retries 429s. Write/user-context surfaces (posting, DMs, follows)
are out of scope. Flow: twitter_user_by_username("AFL") → id →
twitter_user_tweets; search with X operators ("Storm" lang:en -is:retweet).
Cross-provider comparison
Every tool is tagged with provider-agnostic capability slugs (e.g.
sport.event_markets, racing.race_card). Tools sharing a slug answer the same
question and are directly comparable across providers. The discovery flow:
list_tools_by_capability("sport.event_markets")→ every enabled tool exposing itCall each provider's tool concurrently with the resolved event ids
Compare the raw snapshots (schemas are not normalised — the model reconciles them)
See examples/comparator-prompt.md for a full
"compare Storm v Cowboys odds across bookies" walkthrough.
Per-provider notes
Sportsbet — anonymous public APIs; no secrets needed. REST events are keyed by integer
eventId; a persisted-GraphQL gateway is exposed viasportsbet_graphql_call(browsesportsbet://graphql/operations).Entain / Ladbrokes — a persisted-GraphQL gateway; the model supplies an operation name + variables (discover them in
entain://graphql/operations). Hashes can drift when the front-end bundle ships; refresh them withsportsdata-mcp refresh-hashes entain.AFL —
afl.public.*is anonymous.afl.premium.*mints an anonymousx-media-mis-tokenautomatically; some premium endpoints still return 401 for anonymous callers.NRL — the anonymous Champion Data match-centre CDN (
mc.championdata.com), the same static JSON the official nrl.com match centre reads. No secrets, no cache-buster params needed. Resolve acompetitionIdfromnrl_competitions(e.g. 12999 = 2026 NRL Premiership), amatchIdfromnrl_fixture, then pull per-player match stats fromnrl_match; decode stat codes vianrl://stats/definitions.NBA — two surfaces, no secrets.
cdn.nba.comis wide open (it even serves JSON astext/plain, which the client accepts).stats.nba.comsits behind Akamai, which black-holes any request missing a full browser header bundle — the spec ships that bundle inprovider.default_headers, so it just works. Akamai also rate-limits hard, so the spec'sdefaultsblock throttles NBA to ~1 req/2.5 s, sets a 45 s timeout, and retries transient429/5xxwith exponential backoff (all overridable viaproviders.nba.*). The/stats/family is one dispatcher (nba_stats_call): pick anoperation(the path segment, e.g.leaguedashplayerstats) and passquery_params— each operation already carries NBA's full default param set, so you override only what matters. Most responses are column-oriented (resultSets:[{name, headers, rowSet}]}); v3 box scores are nested.ESPN — four public hosts, no auth, no API key:
site.api.espn.com(scores, teams, standings, news, summaries),sports.core.api.espn.com(the canonical$ref-linked model — odds, win-probability, plays, venues, drafts, coaches),site.web.api.espn.com(search + athlete views) andcdn.espn.com(the live core feed, needs?xhr=1). Nearly every URL is.../sports/{sport}/{league}/{resource}, so the tools takesport+leagueas parameters and cover every ESPN league parametrically — NFL, NBA, MLB, NHL, college, soccer (eng.1,esp.1, …), golf, racing, tennis, MMA and more. Discovery:espn_scoreboard(sport, league)→ aneventid →espn_game_summaryor the deepespn_core_call(event_*)ops. The spec throttles to ~5 req/s and retries transient429/5xx(overridable viaproviders.espn.*). Note the core API path usesleagues/{league}(plural); core list responses are lazy{count, items:[{$ref}]}envelopes — follow the refs for detail.PointsBet — anonymous public APIs, no secrets.
api.au.pointsbet.comserves the sportsbook (sports + racing);pointsbet.com.auserves static CMS/nav assets via thepointsbet_content_calldispatcher. Sports discovery:pointsbet_sport_competitions(sportKey)→ a competition key →pointsbet_event(eventKey)for the full market book. Racing:pointsbet_racing_meetings(startDate, endDate)→ araceId→pointsbet_racing_race. Many feeds return a top-level JSON array.TAB (Tabcorp) — anonymous public data, no secrets.
api.beta.tab.com.ausits behind Akamai (the spec ships a browser header bundle + ~2.5 rps throttle, like NBA);cmsapi.tab.com.auserves CMS feeds viatab_cms_call. Every endpoint needs ajurisdiction(defaults toNSW). The API is HATEOAS and name-based — paths embed sport/competition/match/venue names with spaces (…/AFL Football/competitions/AFL/matches/Adelaide v Geelong), which the HTTP layer percent-encodes; pass raw names. Racing:tab_racing_meetings(date)→raceType+venueMnemonic→tab_racing_race. Sports:tab_sport→tab_competition→tab_matchfor the full market book.Unibet — anonymous AU data, no secrets, two surfaces. Racing is persisted-GraphQL (
unibet_racing_call, thegraphql_persisteddispatcher) atrsa.unibet.com.au— race ids areeventKeys like202606040200.T.AUS.hawkesbury.1; the endpoint enforces Apollo CSRF so aContent-Type: application/jsonheader is sent. Sport is the Kambi offering API (unibet_kambi_callover*.kambicdn.com, market AU): group tree, events, bet offers, in-play, bet-builder. Browse ops inunibet://{racing,sport}/operations.BetR — anonymous AU data, no secrets. BetR runs on the BlueBet platform, so the API is
web20-api.bluebet.com.au— a flat REST surface covering racing (next-to-jump, grouped racecards, race cards, form, fluctuations) and sport (event types → categories → markets, SGMs). Thebetr.com.auNext.js_next/data/{buildHash}blobs are skipped (fragile per-deploy hash; the API serves the same data).Racing and Sports —
www.racingandsports.com.auracing/form data, no auth.racingandsports_todays_racing(/todays-racing-json-v2) is the verified feed — today's meetings across thoroughbred/harness/greyhound, by country. The site is behind Cloudflare, which whitelists that feed but JS-challenges the other paths from datacenter IPs (they work from a residential/browser IP); the form/fields/ results are HTML pages, andGetOddsneeds a per-race token, so only the JSON feeds are modelled.Betfair Exchange — anonymous, the open read-only web APIs keyed by the public
_akquery param. The crown jewel isbetfair_market_prices(ero …/bymarket) — exchange back/lay prices, the sharpest reference odds. Discover market ids by walkingbetfair_navigation(scan …/bynode, e.g.EVENT_TYPE:7= Horse Racing) down to MARKET nodes; live scores/details come from theipsin-play service.string_csvid params take a list. (Theapiedsracing widgets are Cloudflare-gated from datacenter IPs and theappsyncGraphQL needs a session, so they're out of scope — racing is covered via navigation→bymarket.)Pinnacle — anonymous, no key. The Arcadia "guest" API (
guest.api.arcadia.pinnacle.com) — the open feed the web sportsbook reads. Sports only (sharp-odds book, no racing); prices are American odds. Flow:pinnacle_sports→pinnacle_sport_matchups(sportId)→pinnacle_matchup_markets(matchupId). The provider sends Pinnacle's public web-clientX-API-Key, which unlocks the full per-sport + per-league matchup lists and the parlay markets.FanDuel (US) — anonymous US data, no secrets, two surfaces under one provider. Racing is the first full-query GraphQL provider:
fanduel_racing_callPOSTs the literal query text (thegraphql_querydispatcher kind, sibling to the persisted-hashgraphql_persisted), with boilerplate variables (brand/product/device/profile) baked as per-opdefault_variables— most calls need none, override only what varies ({results: 12},{trackCode, raceNumber}). Sportsbook is REST (fanduel_sb_call) keyed by the static public_akweb key, region NJ. The two halves need differentOriginheaders, so the sportsbook dispatcher overridesOrigin+x-sportsbook-regionover the racing-origin provider default. Browse ops infanduel://{racing,sportsbook}/operations. (US data — composes with other US sources via capability tags.)
CLI reference
Command | Purpose |
| Start the MCP stdio server (default when no subcommand) |
| Print every group with tool count + description |
| Validate specs against the schema + capability catalogue (nonzero on failure) |
| Per-provider reachability + auth + REST-contract probe (nonzero on failure) |
| Refresh persisted-query hashes from the live front-end bundle ( |
| Print version info |
-v / --verbose enables DEBUG logging (and un-silences httpx/httpcore).
Contributing
See documentation/ADDING_A_PROVIDER.md for
the full guide, with separate playbooks for adding a bookmaker vs a sports website /
data API. In short, adding a provider is a spec-only change in the common case:
Write
src/sportsdata_mcp/specs/<provider>.yaml(copy an existing spec).Tag each tool with capability slugs from
specs/_capabilities.yaml; add a new slug there if none fits (two providers sharing a slug makes them comparable).sportsdata-mcp lint— must pass.sportsdata-mcp doctor(with the new groups enabled) — probes it live.pytest -m "not live"— offline suite; drop the marker filter to run live tests.Add a row to
tests/contract/test_api_contracts.pyso the new provider's documented response shape is verified live on every PR (see below).
pip install -e ".[dev]"
pytest -m "not live" # offline suite (the CI gate)
pytest -m contract # live response-contract checks (see below)
ruff check .CI
Every push/PR runs three jobs (.github/workflows/ci.yml):
test — ruff,
sportsdata-mcp lint, and the offline suite (pytest -m "not live") across Python 3.11–3.13. The deterministic gate.contract —
pytest -m contract: live response-contract checks that hit each upstream API and assert it still returns the documented shape (top-level keys, and the documented keys on list items). It is resilient by design — it skips on anything outside our control (network errors,5xx,401/403/429, geo-blocks, a missingDATAGOLF_KEY, or an empty feed) and only fails on a genuine shape regression or a broken spec (wrong path/params →4xx). Bookmaker APIs that geo-block GitHub's runners simply skip there.package — builds the wheel and proves the CLI loads the packaged specs from a clean install.
License
Proprietary and confidential. Copyright (c) 2026 Daniel Tomaro. All rights
reserved. No use, copying, modification, or distribution is permitted without the
owner's prior written consent — see LICENSE.
mcp-name: io.github.DanielTomaro13/sportsdata-mcp
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server that exposes the Storm cross-venue prediction-market intelligence API, enabling LLM clients to read canonical events, spreads, venue catalog, and alerts as native tool calls.Last updated732MIT
- AlicenseBqualityDmaintenanceMCP-compatible server that gives AI agents access to alternative sports data across 30+ leagues — odds, events, probabilities, settlement, and futures for prediction markets, DFS platforms, and sportsbooks.Last updated2932MIT
- AlicenseAqualityAmaintenanceA unified MCP server that aggregates 32 sports API providers into a single service, providing 336 tools for scores, stats, odds, esports, and more across 70+ sports.Last updated1008415MIT
- Flicense-qualityDmaintenanceA unified MCP server that combines The Odds API and SportMonks Football API v3 to provide 28 tools for sports data like odds, scores, fixtures, standings, and predictions, enabling Claude to interact with a wide range of sports information.Last updated1
Related MCP Connectors
The Odds API MCP — sportsbook odds across 70+ books, 30+ leagues
Sports Game Odds MCP — wraps the Sports Game Odds API (sportsgameodds.com)
MCP server exposing the Backtest360 engine API as tools for AI agents.
Appeared in Searches
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/DanielTomaro13/sportsdata-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server