> ## Documentation Index
> Fetch the complete documentation index at: https://docs.therundown.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Data MCP

> Connect Codex, Claude, Cursor, or VS Code to six read-only sports data tools through TheRundown's hosted Streamable HTTP endpoint or the local stdio MCP server, using your own API key.

The data MCP lets an AI assistant fetch TheRundown Product API data through six read-only tools, using your own API key. Use the hosted Streamable HTTP endpoint for zero-install access, or run the local stdio scaffold with Node.js 22+ when you want a local install that does not depend on the hosted MCP endpoint. The local 0.2.3 server supports keyless MCP metadata discovery: initialization, tool and resource listings, and the exact `therundown://brief` read do not call the Product API. Product tool calls still require your key, and your plan's data delay, coverage, entitlements, and data-point billing still apply.

<Info>
  **Official sources:** the hosted endpoint at `https://mcp.therundown.io/mcp`
  and [TheRundown/data-mcp](https://github.com/TheRundown/data-mcp) (source and
  versioned bundle, for the local stdio install below) are both official. The
  `aigeon-ai/therundown` repository is unofficial, and there is still no
  published npm package. The existing [documentation MCP](/documentation-mcp)
  at `https://docs.therundown.io/mcp` searches documentation only.
</Info>

## Hosted endpoint

The same six tools are also available over a hosted, authenticated Streamable HTTP endpoint. No local install or Node.js runtime is required:

```text theme={null}
https://mcp.therundown.io/mcp
```

MCP calls must be `POST`; a plain `GET` correctly returns `405`. A request carrying any `Origin` other than the endpoint's own is rejected with `403`, so do not call it from a web page, which would also expose your key. Send your Product API key in exactly one header, never both. Use the recommended `X-TheRundown-Key` header, which matches [Authentication](/authentication):

```text theme={null}
X-TheRundown-Key: YOUR_API_KEY
```

Only if your client can send nothing but a bearer token, use this alternate instead:

```text theme={null}
Authorization: Bearer YOUR_API_KEY
```

The Claude Code, Cursor, and Codex examples read the key from `THERUNDOWN_API_KEY` in the environment that launches the client, so the key never appears in the config file or in command-line arguments. Claude Code expands `${THERUNDOWN_API_KEY}` in a project `.mcp.json` when it connects; Cursor's equivalent is `${env:THERUNDOWN_API_KEY}`; Codex maps the request header to the variable with `env_http_headers`. Populate the variable from a secret manager or a silent prompt such as `read -rs THERUNDOWN_API_KEY && export THERUNDOWN_API_KEY`, not by typing the key into a command your shell records in its history. VS Code can instead prompt for the key and store it securely as an input value.

<CodeGroup>
  ```json Claude Code (.mcp.json) theme={null}
  {
    "mcpServers": {
      "therundown-data": {
        "type": "http",
        "url": "https://mcp.therundown.io/mcp",
        "headers": {
          "X-TheRundown-Key": "${THERUNDOWN_API_KEY}"
        }
      }
    }
  }
  ```

  ```json Cursor theme={null}
  {
    "mcpServers": {
      "therundown-data": {
        "url": "https://mcp.therundown.io/mcp",
        "headers": {
          "X-TheRundown-Key": "${env:THERUNDOWN_API_KEY}"
        }
      }
    }
  }
  ```

  ```toml Codex (~/.codex/config.toml) theme={null}
  [mcp_servers.therundown-data]
  url = "https://mcp.therundown.io/mcp"
  env_http_headers = { "X-TheRundown-Key" = "THERUNDOWN_API_KEY" }
  ```

  ```json VS Code (user mcp.json) theme={null}
  {
    "inputs": [
      {
        "type": "promptString",
        "id": "therundown-api-key",
        "description": "TheRundown Product API key",
        "password": true
      }
    ],
    "servers": {
      "therundownData": {
        "type": "http",
        "url": "https://mcp.therundown.io/mcp",
        "headers": {
          "X-TheRundown-Key": "${input:therundown-api-key}"
        }
      }
    }
  }
  ```

  ```bash curl (reachability check) theme={null}
  curl -i https://mcp.therundown.io/mcp
  # a plain GET returns 405 Method Not Allowed; the endpoint requires POST
  ```
</CodeGroup>

For VS Code, open the user-level MCP configuration with **MCP: Open User Configuration**, paste the entry, and start the server. Keep a personal key out of a shared `.vscode/mcp.json`. See [VS Code's MCP configuration reference](https://code.visualstudio.com/docs/agents/reference/mcp-configuration) and [OpenAI's Codex MCP documentation](https://developers.openai.com/codex/mcp) for the client-specific fields above.

Per key, one request may be in flight; the process also caps overall concurrent requests and returns `429` with `Retry-After: 1` when full. Request bodies are capped at 64 KiB, and the request deadline defaults to 20 seconds. Sanitized errors carry structured `error.data` — `status`, `plan`, `missing_entitlement`, `required_plan`, `retry_after`, `remaining_points`, `monthly_remaining_points`, and `limit_reason` — so a client can react programmatically. Keep real keys out of prompts, source files, URLs, and logs, the same as the REST API's [`X-TheRundown-Key` header](/authentication).

Metadata discovery is intentionally separate from Product data access. With the local 0.2.3 stdio server, `initialize`, the initialized notification, `tools/list`, `resources/list`, and `resources/read` for exactly `therundown://brief` work without a key and do not validate a key or entitlement. A local Product tool call without a key returns a sanitized `missing_credentials` error before any upstream request. For the hosted endpoint, configure the documented key header before connecting. An otherwise-valid unauthenticated MCP `POST`/JSON-RPC request for a Product tool returns HTTP `401` with structured `error.data`; a plain `GET` remains the separate transport probe with HTTP `405`, and transport or Origin guard failures have their own transport status.

Choose the hosted endpoint for zero local install, or the local stdio install below when you want a process that runs on your machine and does not call the hosted MCP endpoint. The local server still makes HTTPS calls to the Product API with your key.

## Install from source

This is the local-install path: a stdio server that runs on your machine and does not call the hosted MCP endpoint. It still makes HTTPS Product API calls with your key, so it is not suitable for a fully offline or network-isolated environment. Download the [versioned source bundle](https://therundown.io/downloads/therundown-data-mcp-0.2.3.zip), extract it locally, and install the locked dependencies. The [official public source repository](https://github.com/TheRundown/data-mcp) is the canonical source; GitHub access is not required when using the bundle. The archive includes the server, dependency lockfile, design, and offline tests:

```bash theme={null}
cd /absolute/path/to/therundown-data-mcp-0.2.3
npm ci --ignore-scripts
npm test
```

The server uses the official MCP SDK over stdio. It exposes no listening HTTP port. Keep the process environment and local client configuration private.

To check the download before extracting it, download its [SHA-256 checksum](https://therundown.io/downloads/therundown-data-mcp-0.2.3.sha256) into the same directory and run `sha256sum -c therundown-data-mcp-0.2.3.sha256` (Linux) or `shasum -a 256 -c therundown-data-mcp-0.2.3.sha256` (macOS). The expected archive SHA-256 is `cb0a0841aa040f049ffddec5b5fa2436cb9de721a30a3bd53270132db7204025`. The archive also contains `MANIFEST.json` with its version and individual file hashes.

## Connect an MCP client

These configurations connect a client to the local stdio install above; see [Hosted endpoint](#hosted-endpoint) for the zero-install alternative. Replace both paths below with the absolute Node.js 22+ executable and extracted `server.mjs`. An absolute Node path also works when a desktop app does not inherit your terminal's Node version. Keep real keys in private local configuration or the client's supported secret/environment mechanism.

### Claude Desktop

Use this entry in `claude_desktop_config.json`, then restart Claude Desktop. This source ZIP is not a `.mcpb` desktop extension. See the [official local-server configuration guide](https://modelcontextprotocol.io/docs/develop/connect-local-servers).

```json theme={null}
{
  "mcpServers": {
    "therundown-data": {
      "command": "/absolute/path/to/node",
      "args": ["/absolute/path/to/therundown-data-mcp-0.2.3/server.mjs"],
      "env": {
        "THERUNDOWN_API_KEY": "YOUR_API_KEY"
      }
    }
  }
}
```

### Cursor

Add this entry to the global `~/.cursor/mcp.json`. Make `THERUNDOWN_API_KEY` available in the environment that launches Cursor, then reload its MCP servers. The environment reference keeps the key value out of the JSON. See [Cursor's MCP instructions](https://cursor.com/docs/mcp).

```json theme={null}
{
  "mcpServers": {
    "therundown-data": {
      "type": "stdio",
      "command": "/absolute/path/to/node",
      "args": ["/absolute/path/to/therundown-data-mcp-0.2.3/server.mjs"],
      "env": {
        "THERUNDOWN_API_KEY": "${env:THERUNDOWN_API_KEY}"
      }
    }
  }
}
```

### Codex

Set or export `THERUNDOWN_API_KEY` privately in the environment that launches Codex. Add this entry to `~/.codex/config.toml`, replacing the two absolute paths with the Node.js 22+ executable and extracted `server.mjs` paths from the setup above:

```toml theme={null}
[mcp_servers.therundown-data]
command = "/absolute/path/to/node"
args = ["/absolute/path/to/therundown-data-mcp-0.2.3/server.mjs"]
env_vars = ["THERUNDOWN_API_KEY"]
```

`env_vars` forwards the named environment variable to the MCP server without copying its value into TOML. See [OpenAI's Codex MCP documentation](https://developers.openai.com/codex/mcp) for client configuration details.

Start a new Codex session from that environment and confirm that it exposes the [six tools](#tools). Follow [First conversation](#first-conversation), then [Verify a real request](#verify-a-real-request) to check API access.

The server reads `THERUNDOWN_API_KEY` from its environment and sends it to the Product API in `X-TheRundown-Key`. Tool arguments never accept credentials, arbitrary URLs, or custom headers. Without a key, metadata discovery and the exact `therundown://brief` read remain available, while Product tool calls return `missing_credentials` without making a network request. Never commit a client configuration containing a real key.

## Brief, scope, and outcomes

Read the `therundown://brief` resource before asking for data; the hosted
endpoint and the local server both expose it. It starts
with four rules: resolve the event first; every price carries event, market,
affiliate, line, and `updated_at` evidence; missing stays missing; and IDs come
from the API at runtime, with retired identities excluded.

Requests are scoped to the selected public IDs and filters. An empty result
means no data for that scope, not that an event, source, or market is universally
unavailable. Preserve a returned null line value as null. Treat a sanitized
`401`, `403`, or `429` response separately from an empty result, and use the
documented header-based Product API key boundary rather than a query key.

## Tools and output schemas

Each tool has a human-readable title and advertises an object-root structured
output schema. Successful results use the common envelope
`{source_url, retrieved_at, usage, data}`; empty results add `empty`, and
sanitized failures add the documented error fields. The six titled `data`
schemas are:

| Title | Tool | Structured `data` shape |
| - | - | - |
| List sports | `list_sports` | `{ sports: [{ sport_id, sport_name }] }` |
| List affiliates | `list_affiliates` | `{ affiliates: [{ affiliate_id, affiliate_name }] }` |
| List markets | `list_markets` | `{ items: [{ id, name, description, period_id, live, live_variant_id, sports }], total, page, limit, next_page }` |
| List events | `list_events` | `{ items: [{ event_id, sport_id, event_date, score, teams, market_ids }], total, page, limit, next_page }` |
| Get main lines | `get_main_lines` | `{ event, items: [{ market_id, market_name, period_id, participant, line_id, line_value, affiliate_id, price, is_main_line, updated_at }], total, page, limit, next_page }` |
| List futures | `list_futures` | `{ events: [{ event_id, sport_id, event_date, settle_by, event_status, schedule, settlement, market_ids, main_lines }], meta: { count, total, has_more, next_cursor } }` |

Fields shown as nullable or optional by the server remain absent or `null` as
returned. The schemas describe the curated public projection, not the full
Product API response.

## Tools

| Tool | Input | Result |
| - | - | - |
| `list_sports` | None | Canonical sport IDs and names. |
| `list_affiliates` | None | Currently published affiliate IDs and names. Retired affiliate 27 is excluded. |
| `list_markets` | Optional catalog filters; or required `sport_id` plus `date` and optional offset | Catalog definitions, or markets available for that sport/date. Date-based discovery rejects `live`. |
| `list_events` | `sport_id`, `date`; optional filters, offset, and pagination | Event IDs, teams, score, date, and available market IDs. |
| `get_main_lines` | `event_id`; optional filters and pagination | Open main-line prices with participant, affiliate, line value, and `updated_at`. |
| `list_futures` | `sport_id`; optional future market/book filters, limit, opaque cursor, and `include_settled` | Ultra+ competition page with public schedule/settlement fields, open per-affiliate main lines, and honest cursor metadata. |

The dated event tools default to `market_ids: [1, 2, 3]` and `affiliate_ids: [19, 23]`. They always request `main_line=true&hide_closed=true&include=all_periods`. `list_futures` defaults to `market_ids: [1141]` and the same affiliates; its response keeps only open per-affiliate main lines and public competition schedule/settlement fields. Pass live IDs `41,42,43` explicitly for in-play moneyline, spread, and total. Discover other markets instead of guessing IDs.

Both transports accept at most 12 market IDs and 10 affiliate IDs per call. Pages contain at most 200 items; the default is 50. Catalog, date-market, event, and main-line pagination happens inside the MCP server: another page fetches another full filtered API response, incurs its normal usage, and may reflect a newer snapshot. `list_futures` instead forwards the API's opaque cursor and page limit; each cursor page is still metered, and `has_more` means the response is only a partial competition listing. Reduce market/book filters to reduce billing; lowering a local page size only reduces tool output.

## First conversation

```text theme={null}
Use TheRundown to list current sports and affiliates. Find MLB (sport 3).
For today's UTC date, list events with market_ids [1,2,3]
and affiliate_ids [19,23]. Select an event ID from that response and
call get_main_lines with the same filters.
Show the source URL, each book's line value and price updated_at,
and the returned usage headers. Explain empty results without inventing odds.
```

Results carry `source_url`, `retrieved_at`, `usage`, and `data`. `retrieved_at` is the HTTP retrieval time, not the freshness of an individual price. Use the price's `updated_at` and your key's delay entitlement. A sport or affiliate catalog entry does not guarantee an open offer for a particular event.

## Verify a real request

This check is for the local install. On the hosted endpoint, run [First conversation](#first-conversation) from your connected client instead; a non-empty `get_main_lines` result confirms your key and entitlement end to end.

After setting `THERUNDOWN_API_KEY` privately in your environment, run:

```bash theme={null}
npm run smoke
```

This opt-in check makes metered requests. Ordinary `npm test` is offline. By default, the smoke check uses sport ID 3, affiliate IDs 19/23, and pre-match markets `1,2,3`, so it does not request live access on a Free key. Free covers delayed pre-match odds within its published allowance; it excludes live odds, props/alternates, and history. Check [current entitlements](/rate-limits) for your key.

With an eligible key, explicitly include live markets `41,42,43`:

```bash theme={null}
THERUNDOWN_SMOKE_LIVE=1 npm run smoke
```

Require `status: "ok"`, `tools: 6`, and positive `events` and `main_lines` counts. The script verifies the exact six tool names before making data requests. Set `THERUNDOWN_SMOKE_SPORT_ID` and `THERUNDOWN_SMOKE_DATE=YYYY-MM-DD` for a dated scope. With an eligible Ultra+ key, set `THERUNDOWN_SMOKE_FUTURES=1` for one bounded future page using market `1141`, affiliates `19,23`, and the selected sport; lower tiers may return a documented 403 entitlement result. The script has a 60-second deadline. A positive response is a snapshot check, not a latency or all-source coverage benchmark.

## Limits and next steps

Both transports allow one in-flight API call (per process locally, per key on the hosted endpoint), use a 15-second upstream timeout and a 4 MiB upstream response limit, reject redirects, and never retry automatically. The hosted endpoint adds its own 64 KiB request-body cap, 20-second request deadline, and overall concurrency cap; see [Hosted endpoint](#hosted-endpoint). On `429`, follow the returned `retry_after` and [usage headers](/rate-limits). API errors are sanitized before reaching the assistant.

Both transports provide REST snapshots. Streaming, bet placement, account changes, OAuth, and package publication are out of scope. Read the [design and release criteria](/data-mcp-design) before operating a shared service.

For a pasteable API integration brief, see [Build with AI](https://therundown.io/build-with-ai). For the underlying contracts, use the [OpenAPI specification](https://docs.therundown.io/openapi.yaml), [authentication guide](/authentication), and [market reference](/reference/markets).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.