Skip to main content
Glama
SportWizzard MCP Server

SportWizzard MCP Server

by sportwizzard

SportWizzard MCP Server

Query live sports-betting data — odds, player props, +EV edges, arbitrage, stats and reference data from 35+ sportsbooks and DFS apps — from any MCP-capable AI agent (Claude Code, Claude Desktop, Codex, Cursor, …).

20 read-only tools over the SportWizzard REST v1 API, available two ways: a hosted remote server (zero install) and a stdio server via npx. Get a free API key at https://sportwizzard.com/account (API Keys tab — no card required).

claude mcp add --transport http sportwizzard https://mcp.sportwizzard.com/mcp \
  --header "Authorization: Bearer sw_live_your_api_key_here"
codex mcp add sportwizzard --transport http --url https://mcp.sportwizzard.com/mcp \
  --header "Authorization: Bearer sw_live_your_api_key_here"

The hosted server is a thin proxy: your key is forwarded to the SportWizzard API, which enforces auth and rate limits. All 20 tools work on both transports. (download_snapshot on the hosted server returns a CDN download URL + a ready-to-run command your agent executes locally; on stdio it writes the file directly.)

Successful authenticated live tool calls send a best-effort account-usage receipt. The measurement request contains no tool arguments or result data. For hosted download_snapshot, a successful CDN HEAD check counts because the tool has verified that the returned download URL is reachable; a failed HEAD check does not count.

Related MCP server: mcp-odds-api

Stdio (local)

npx -y sportwizzard-mcp

Claude Code:

claude mcp add sportwizzard -e SPORTWIZZARD_API_KEY=sw_live_your_api_key_here -- npx -y sportwizzard-mcp

Claude Desktop (claude_desktop_config.json — macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\):

{
  "mcpServers": {
    "sportwizzard": {
      "command": "npx",
      "args": ["-y", "sportwizzard-mcp"],
      "env": { "SPORTWIZZARD_API_KEY": "sw_live_your_api_key_here" }
    }
  }
}

Mock mode (no key, no network)

Set SPORTWIZZARD_MOCK=1 to get canned sample responses — useful for wiring up an integration before you have a key.

Configuration

Env var

Default

Purpose

SPORTWIZZARD_API_KEY

(none)

Your API key, sent as X-Api-Key.

SPORTWIZZARD_BASE_URL

https://api.sportwizzard.com

Override the API base URL.

SPORTWIZZARD_MOCK

(off)

1 = canned sample data, no network.

Tools

Tool

What it does

list_events / get_event

Events/fixtures with their participants — filter by competition, competitor, player, status, time; full detail incl. each side's score, the latest live state, weather, lineups, probable pitchers.

get_event_stats

Box score: every player's stat line + competitor results for one event.

get_odds / get_event_odds / get_player_odds / get_competitor_odds

Current prices, scoped by event, player, competitor, sportsbook, market, or competition. get_odds also takes scope: event (game markets), season (season-long futures), tournament (golf/tennis outrights); omit for all.

get_edges

+EV edges vs. devigged fair market (competition, source, min_edge filters).

get_arbitrage

Arbitrage opportunities with legs and stake fractions (two/three-way).

list_players / list_competitors / get_player_stats / get_competitor_stats

Reference data and season/historical stats.

get_player_game_logs

Bulk per-game stat rows — the model-training feed.

download_snapshot

Save the full live board to disk (tens of MB gzip). include_history: true also populates every selection's selectionPrice rows (same schema; 5 credits flat vs 1).

list_sportsbooks / list_competitions / list_markets / status

Discover source IDs, covered competitions and supported market types; check customer API availability.

get_account_usage

Your plan tier, rate limit, and monthly usage.

Every response uses the envelope { success, data, nextCursor, meta }; when nextCursor is present the tool appends a _paging hint so agents know to continue.

Participants and sides

Events, edges and arbitrage rows list who takes part as participants, ordered by side:

Event

participants

NBA: Hawks at Wizards

{side: 1, sideLabel: "home", position: 1, name: "Washington Wizards"}, {side: 2, sideLabel: "away", position: 1, name: "Atlanta Hawks"}

Tennis singles

{side: 1, position: 1, name: "Brandon Nakashima"}, {side: 2, position: 1, name: "Matteo Berrettini"} (no label: order is arbitrary, as in MMA and esports)

Tennis doubles

two players per side, position 1 and 2

Golf

the whole field, {name} only, no sides

get_event adds each side's final score and, when a source reported one, the latest live state ({status, period, clock, side1Score, side2Score, source, observedAt}).

Each odds row is one outcome of a selection:

  • side: 1 or 2, the event side the outcome is about; absent for totals, draws, "neither" and futures.

  • outcomeCode: SportWizzard's fixed list: OVER, UNDER, YES, NO, WIN (a moneyline leg is WIN with its side), DRAW, NEITHER, WIN_OR_DRAW, EITHER, ODD, EVEN, SCORE (read side1Score/side2Score), RANGE, OTHER, LABEL (a categorical answer only the selection label explains).

  • statType: the fixed stat list (points, rush_yards, …).

  • outcomeParticipants: [{kind: "competitor" | "player", name}], names exactly as the sportsbook sent them. An outcome about a side with no name has none; read the event participant on that side.

Markets carry phase (PRE or LIVE). With include_history, each selection's selectionPrice is a list of rows, oldest first, one per run of an unchanged price:

{"observedAt": "2026-11-03T12:31:02Z", "lastObservedAt": "2026-11-03T12:40:15Z", "priceAmerican": -110, "priceDecimal": 1.9091}

A row may also carry dfsMultiplier, suspended: true and, on exchanges, liquidityTier.

IDs depend on your key: with an API key on a paid plan, each participant and outcome participant also has competitorId (a team) or playerId (a person), and odds, edge and arbitrage rows carry playerId and source references. Without a key, or on the Free plan, you get names and sides. competitor_id and player_id filters match events where that competitor or player is a participant.

Futures (season-scope markets)

get_odds with scope=season returns season-long futures — division/conference/championship winners, award odds, team win totals, season leaders and full-season player props. Three orthogonal axes describe them:

  • marketScope — which anchor the market hangs off: SEASON or TOURNAMENT. Omitted entirely on ordinary game rows.

  • period — the window within that anchor: REG_SEASON (settles at the end of the regular season) or FULL (runs through the playoffs).

  • segment — which slice of the competition: AFC_EAST, NL, SEC, … Present only when the market is segment-scoped, and load-bearing: all 32 NFL DIVISION_WINNER selections share one season-anchor eventId, so without segment they read as a single 32-team race instead of 8 divisions.

Notes: winner/award markets are categorical (one YES selection per competitor, no side, usually no NO side); eventStartTime on a futures row is the season anchor / settlement date, not a kickoff; every book's futures for a competition share the same season eventId; and futures are deliberately excluded from get_edges / get_arbitrage (they never enter de-vig or edge math). Scope matching is exact — season does not include TOURNAMENT — and an invalid value returns HTTP 400 naming the valid ones.

From source

git clone https://github.com/sportwizzard/sportwizzard-mcp.git
cd sportwizzard-mcp && npm install && npm run build
SPORTWIZZARD_MOCK=1 node dist/index.js   # or set SPORTWIZZARD_API_KEY

Maintainers

This README ships inside the npm package, so keep it free of internal hostnames, keys and private notes (the repository is public).

Layout. src/index.ts is the stdio entry (dist/index.js, the npm bin); src/httpServer.ts is the hosted Streamable HTTP entry (stateless, one request per POST; Host allow list and bearer-key handling); src/auth.ts validates the caller's key against the API, caches it and applies the per-key rate limit; src/tools.ts and src/server.ts define and register tools; src/client.ts is the REST client and src/mock.ts the SPORTWIZZARD_MOCK=1 data. tests/stdio-smoke.mjs and tests/http-smoke.mjs are end-to-end smokes against a loopback mock API (no credentials, no production calls).

Build and verify (the PR check, .github/workflows/ci.yml, runs the same pack-and-smoke plus a no-push container build):

npm ci --ignore-scripts && npm run build
release_dir="$(mktemp -d)"
npm pack --ignore-scripts --pack-destination "$release_dir"
npm install --prefix "$release_dir/consumer" --omit=dev --ignore-scripts --no-audit --no-fund "$release_dir"/*.tgz
npm run smoke -- "$release_dir/consumer/node_modules/sportwizzard-mcp/dist/index.js" "$release_dir/smoke.json" "$release_dir"/*.tgz
npm run smoke:http -- "$release_dir/consumer/node_modules/sportwizzard-mcp/dist/httpServer.js" "$release_dir/http-smoke.json"
rm -rf "$release_dir"

The stdio smoke checks tools/list, get_odds scope=season forwarding and a snapshot download with history; the HTTP smoke checks /healthz, key rejection, the Host allow list, tools/list, key forwarding and a clean SIGTERM exit. Both prove transport and packaging, not live data quality.

Releasing.

  • Hosted server: publish-container.yml publishes a SHA-tagged GHCR image on every push to main. It deploys only when that digest is promoted in the Ops deployment/releases/api.yaml row, which owns placement, limits and credential references.

  • npm package: bump version in package.json, run npm install --package-lock-only, sync server.json, merge to main, then run the manual Publish npm package workflow (publish-npm.yml). It builds once, smokes the packed tarball and publishes those exact bytes through npm trusted publishing (OIDC; no npm token). Publishing npm does not update the hosted container.

Gotchas. Hosted runtime settings are MCP_HTTP_PORT (default 8091), MCP_ALLOWED_HOSTS, AUTH_CACHE_TTL_MS, RATE_LIMIT_PER_MIN, SPORTWIZZARD_SNAPSHOT_URL and SPORTWIZZARD_SNAPSHOT_HISTORY_URL, plus the customer settings above. download_snapshot writes a file on stdio but returns a CDN URL and a command on the hosted server. Never print or commit ~/.npmrc. Open work goes in GitHub issues in this repository.

License

MIT © SportWizzard LLC

Available Tools

20 tools
download_snapshotAInspect

Download the FULL live board — every market from every sportsbook (tens of MB gzip, 80k+ markets) — and save it to a file on disk instead of returning it (it would not fit in a context window). Provide an absolute save_path: a path ending in .gz keeps the gzip; any other path writes decompressed JSON. Returns the saved path, byte count and ETag. Re-poll cheaply by passing the returned etag: unchanged data returns not_modified without downloading.

Inputs: save_path (required), etag.

get_account_usageAInspect

Your API plan and usage: plan tier, per-minute rate limit, monthly usage/cap where metered. Works without a key (shows the effective anonymous plan).

Inputs: no named parameters.

get_arbitrageAInspect

Arbitrage scanner: cross-book opportunities with a guaranteed profit, including each leg (source, selection, odds) and the optimal stake fractions. Filter by type (two_way | three_way) and minimum profit %. Paginate with cursor.

Inputs: type, limit, cursor, min_profit.

get_edgesAInspect

SportWizzard's edge finder: DFS/book offers that are +EV versus the devigged fair market, with the edge %, the book(s) setting fair value, and per-book odds. Filter by league, source (DFS/book), minimum edge, or a single event. Paginate with cursor.

Inputs: limit, cursor, league, source, +2 more.

get_eventAInspect

Full detail for a single event: teams, start time, status, league, venue, season year, final scores (when final), and rich game context — weather, confirmed/projected lineups, probable pitchers, and officials where the league provides them. The model-builder's pre-game context endpoint. Use an event id from list_events.

Inputs: event_id (required).

get_event_oddsAInspect

Get every sportsbook price for a single event: one flat row per book x market x selection, with american+decimal price, line, side, player/team, and SportWizzard's devigged fair odds where available. Use an event id from list_events.

Inputs: event_id (required).

get_event_statsAInspect

The box score for a single event: every player's stat line (e.g. batting_stats/pitching_stats JSON per player) plus the team-level result row (scores, team stats). Use an event id from list_events; works for final and in-progress events that have stats.

Inputs: event_id (required).

get_oddsAInspect

Core odds query. Returns a flat array of book prices scoped by any combination of event_id, player_id, team_id, sportsbook, market and league. Called unscoped it paginates hard — prefer scoping to at least one entity. Paginate with cursor.

Inputs: limit, cursor, league, market, +4 more.

get_player_game_logsAInspect

Bulk per-game player stat rows (game logs) filtered by player, team, or event — the model-training data feed. At least one of player_id / team_id / event_id is required. Each row is one player-game with the raw stat JSON. Paginate with cursor.

Inputs: limit, cursor, team_id, event_id, +1 more.

get_player_oddsAInspect

All current book prices for a single player across events and markets (player props). Use a player id from list_players. Paginate with cursor.

Inputs: player_id (required), limit, cursor.

get_player_statsAInspect

Historical / season statistics for a single player. Use a player id from list_players; optionally scope to one season.

Inputs: player_id (required), season.

get_team_oddsAInspect

All current book prices for a single team across its events and markets. Use a team id from list_teams. Paginate with cursor.

Inputs: team_id (required), limit, cursor.

get_team_statsAInspect

Per-game team stats and results for a single team (scores, result, team stat JSON per event). Use a team id from list_teams; optionally scope to one season.

Inputs: team_id (required), season.

list_eventsAInspect

List sporting events / fixtures (the spine of the API). Each event carries home/away team, start time, status and whether live odds exist (hasOdds). Filter by league, team, status or start-time window, then use the returned event id with get_event_odds. Paginate with cursor.

Inputs: limit, cursor, league, status, +3 more.

list_leaguesAInspect

List the leagues currently covered (with live markets). Reference/discovery — call this to learn valid league filter values.

Inputs: no named parameters.

list_marketsAInspect

List the market types SportWizzard supports, each with a live market count. Reference/discovery — call this to learn valid market filter values.

Inputs: no named parameters.

list_playersAInspect

List players (reference resource). Filter by league and/or team. Returns player UUIDs to use with get_player_odds and get_player_stats. Paginate with cursor.

Inputs: team, limit, cursor, league.

list_sportsbooksAInspect

List the sportsbooks and DFS platforms SportWizzard tracks, with a live market count each. Reference/discovery — call this to learn valid sportsbook filter values.

Inputs: no named parameters.

list_teamsAInspect

List teams (reference resource). Filter by league. Returns team UUIDs to use with list_events(team_id), get_team_odds and get_team_stats. Paginate with cursor.

Inputs: limit, cursor, league.

statusAInspect

Platform status: total live markets and number of sportsbooks currently ingesting. A cheap health/coverage check.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 20 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes, but there is some overlap between the generic get_odds and the specialized get_event_odds, get_player_odds, and get_team_odds. The descriptions help differentiate them, but agents might still be confused when selecting between them.

    Naming Consistency4/5

    The majority of tools follow a verb_noun pattern (get_*, list_*), but 'status' is a single noun and 'download_snapshot' uses a different verb. This slight inconsistency prevents a perfect score.

    Tool Count5/5

    With 20 tools, the server covers all necessary operations for a sports odds data API: discovery, odds retrieval, stats, and utilities. The count is well-scoped and each tool serves a distinct purpose.

    Completeness5/5

    The tool set is comprehensive for a read-only data API, covering discovery, odds, stats, arbitrage, edges, and platform status. There are no obvious missing operations for the stated domain.

    Maintenance

    ActivityMaintained
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      B
      maintenance
      Enables AI assistants to access sports betting odds data from 265+ bookmakers across 34 sports, including events, odds, historical data, arbitrage, and value bets.
      33
      1,057 npm
      2
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables fetching sportsbook odds, live scores, and event information across 70+ books and 30+ leagues, with tools to list sports, get scores, and discover events.
      297 npm
      1
      MIT
    • A
      license
      B
      quality
      C
      maintenance
      Provides AI agents with live, grounded sports data including model probabilities, track records, and European soccer and tennis arbitrage opportunities, so they answer from real numbers instead of stale guesses.
      13
      53 npm
      1
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI agents to query live sports betting odds, best prices, arbitrage, +EV bets, and middles directly through Model Context Protocol tools.
      9
      103 npm
      MIT