mcp-sports-server
by mayank-nayak
README.md
# Sports-Stats MCP Server
A [Model Context Protocol](https://modelcontextprotocol.io) server that exposes a
read-only SQLite database of **real NBA game data** to LLM clients (Claude Desktop,
etc.), enabling safe natural-language querying of the data.
The dataset is FiveThirtyEight's historical
[NBA Elo dataset](https://github.com/fivethirtyeight/data/tree/master/nba-elo):
**63,157 games across 69 seasons (1947–2015)**. `npm run seed` downloads it and
loads it into a clean relational schema.
## What it does
The server registers two tools that an LLM can call:
| Tool | Description |
|------|-------------|
| `list_schema` | Returns every table with its columns and types, so the model learns the data shape before querying. |
| `run_query` | Executes a single **read-only** `SELECT` and returns the rows as JSON. |
### Safety: read-only guardrails
`run_query` validates every statement before execution and rejects:
- anything that isn't a `SELECT` / `WITH` query,
- write & DDL keywords (`INSERT`, `UPDATE`, `DELETE`, `DROP`, `ALTER`, `CREATE`, `PRAGMA`, `ATTACH`, …),
- multiple chained statements (SQL-injection style `; DROP …`).
As a second line of defense, the database itself is opened in `readonly` mode.
## Data model
Two tables derived from the source dataset (the raw CSV stores two rows per game —
one per team — which the seed collapses into one clean row per game):
```
teams(id, franchise) -- e.g. ('LAL', 'Lakers')
games(id, season, game_date, is_playoffs, neutral,
home_team_id → teams, away_team_id → teams,
home_score, away_score)
```
## Setup
```bash
npm install
npm run build # compile TypeScript -> dist/
npm run seed # download the real dataset + populate sports.db (~18 MB download, cached)
```
## Use with Claude Desktop
Add this to your Claude Desktop config
(`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS),
then restart Claude Desktop:
```json
{
"mcpServers": {
"sports-stats": {
"command": "node",
"args": ["/Users/mayanknayak/Desktop/Personal Projects/mcp-sports-server/dist/index.js"]
}
}
}
```
You'll see a tools icon appear. Now ask natural-language questions:
- "Which franchise won the most games in the 1996 season?"
- "Show the 5 highest-scoring games of all time."
- "What's the Lakers' all-time playoff win percentage?"
- "Which team had the biggest average margin of victory in the 1980s?"
Claude will call `list_schema`, then write and run a `SELECT` via `run_query`.
## Smoke test (no Claude Desktop needed)
```bash
node test-client.mjs
```
Spins up the server over stdio and verifies tool discovery, schema introspection,
a real aggregate query, and that a `DELETE` is blocked by the guard.
## Stack
TypeScript · `@modelcontextprotocol/sdk` · `better-sqlite3` · `zod`
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues