fantrax-mcp
by joshwolf
README.md
# fantrax-mcp
MCP server for [Fantrax](https://www.fantrax.com/) fantasy baseball. It exposes tools to read league info, rosters, standings, free agents, and related data. The server is **league-scoped**: set one Fantrax league ID per deployment or local process.
## Requirements
- Node.js 18+
- [pnpm](https://pnpm.io/) (or use `npx` / `npm` equivalents)
## Environment
| Variable | Required | Description |
|----------|----------|-------------|
| `FANTRAX_LEAGUE_ID` | Yes | Fantrax league ID (from the league URL) |
The app does not load `.env` automatically for the stdio entrypoint; set variables in your shell or in your MCP client config (`env`).
## MCP tools
All tools use the league configured by `FANTRAX_LEAGUE_ID`. **Atomic** tools map roughly one-to-one to Fantrax data; **composite** tools combine several calls for common workflows.
### Atomic
| Tool | Description |
|------|-------------|
| `get_league_info` | Full league info: teams, roster settings, player statuses. Prefer `get_league_summary` when you only need high-level details. |
| `get_league_summary` | Lightweight league info: name, season year, start/end dates, roster and draft settings. |
| `get_standings` | Standings: rank, points, and win percentage per team. |
| `list_teams` | All teams with `teamId`, `teamName`, and rank — use before tools that require a team ID. |
| `get_all_rosters` | Every team’s roster (player IDs, positions, salary). Prefer `get_team_roster` for a single team. |
| `get_team_roster` | One team’s roster (`teamId`). |
| `get_free_agents` | Free agents with name, MLB team, position, and eligible fantasy positions. |
| `get_player_info` | MLB player ADP-style data for ranking and valuation. Optional: `position`, `limit`, `order`. |
| `get_scoring_categories` | Stats that count in this league — use when comparing or recommending players. |
### Composite
| Tool | Description |
|------|-------------|
| `get_enriched_rosters` | All rosters enriched with player names and ADP. |
| `find_trade_targets` | Trade targets by position and max ADP (`teamId`, `position`, `maxAdp`; optional status exclusions and whether to search all teams vs bottom half). |
| `get_team_overview` | One team’s roster, standings position, and league scoring categories (`teamId`). |
| `get_waiver_candidates` | Free agents ranked by ADP, with scoring categories — for add/drop decisions. |
| `compare_players` | Side-by-side comparison for two players by name, with league scoring context. |
## Run locally (stdio MCP)
Use this when your client spawns a subprocess and talks MCP over stdin/stdout (e.g. Cursor, Claude Desktop).
From the repo root:
```bash
pnpm install
export FANTRAX_LEAGUE_ID=your-league-id
pnpm mcp:stdio
```
**Cursor** (`~/.cursor/mcp.json` or project `.cursor/mcp.json`):
```json
{
"mcpServers": {
"fantrax": {
"command": "pnpm",
"args": ["mcp:stdio"],
"cwd": "/absolute/path/to/fantrax-mcp",
"env": {
"FANTRAX_LEAGUE_ID": "your-league-id"
}
}
}
}
```
Prefer the example above: it runs the lockfile-pinned `tsx` from this repo. Using `npx tsx …` for the local server works after `pnpm install`, but `npx` adds resolver/caching overhead on each spawn compared to `pnpm mcp:stdio` or `pnpm exec tsx src/mcp-stdio.ts`. If you use npm, `npm run mcp:stdio` with the same `cwd` is the analogous choice.
**Important:** Do not log to stdout in the stdio server; MCP uses stdout for the protocol.
## Run remotely (HTTP MCP)
This repo is a **Next.js** app. The MCP endpoint is served by [`mcp-handler`](https://github.com/vercel/mcp-handler) at:
`https://<your-host>/api/mcp`
Examples:
- Local dev: `http://localhost:3000/api/mcp` (after `pnpm dev`)
- Production: `https://<project>.vercel.app/api/mcp` (or your custom domain)
Clients that support **Streamable HTTP** can use the URL directly, for example:
```json
{
"mcpServers": {
"fantrax-remote": {
"url": "https://your-deployment.vercel.app/api/mcp"
}
}
}
```
If your client only supports stdio, proxy the remote server with [mcp-remote](https://www.npmjs.com/package/mcp-remote):
```json
{
"mcpServers": {
"fantrax-remote": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://your-deployment.vercel.app/api/mcp"]
}
}
}
```
## Deploy to Vercel
1. Push this repository to GitHub (or another supported Git provider).
2. In the [Vercel dashboard](https://vercel.com/new), import the project and select the Next.js preset.
3. Under **Settings → Environment Variables**, add `FANTRAX_LEAGUE_ID` for **Production** (and Preview if you want preview deployments to work).
4. Deploy. The build runs `prebuild`, which generates `src/player-ids.json` via `scripts/generate-player-ids.ts`.
Official reference: [Deploying Next.js to Vercel](https://vercel.com/docs/frameworks/nextjs).
### Scheduled rebuilds
Production is redeployed automatically every **Monday and Thursday** at approximately **6:00 AM Eastern** via [`.github/workflows/scheduled-rebuild.yml`](.github/workflows/scheduled-rebuild.yml). The workflow POSTs to a Vercel Deploy Hook, which runs a full build (including `prebuild` player ID refresh).
**One-time setup:**
1. In Vercel: **Settings → Git → Deploy Hooks** — create a hook named e.g. `scheduled-production-rebuild` on branch `main` for **Production**.
2. In GitHub: **Settings → Secrets and variables → Actions** — add `VERCEL_DEPLOY_HOOK_URL` with the hook URL.
**Manual trigger:** Actions → **Scheduled production rebuild** → **Run workflow**.
**Timezone note:** GitHub cron uses UTC only (no DST). The schedule `0 11 * * 1,4` runs at 6:00 AM EST and 7:00 AM EDT. To target 6:00 AM during daylight saving instead, change the cron to `0 10 * * 1,4` (5:00 AM in winter).
## Player data at build time
`pnpm build` runs **`prebuild`** first (`package.json`), which executes `scripts/generate-player-ids.ts`. That script **fetches** the MLB player ID catalogue from Fantrax’s public `getPlayerIds` API over HTTPS and writes `src/player-ids.json`. The build host must allow outbound network access; if the fetch fails, the build exits with an error. This step does **not** use `FANTRAX_LEAGUE_ID` (that variable is only for runtime MCP requests against your league).
## Development
| Script | Purpose |
|--------|---------|
| `pnpm dev` | Next.js dev server (remote MCP at `/api/mcp`) |
| `pnpm mcp:stdio` | Local stdio MCP server |
| `pnpm build` | Production build (`prebuild` regenerates player IDs) |
| `pnpm test` | Vitest |
| `pnpm typecheck` | `tsc --noEmit` |
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues