ESPN Fantasy MCP
by michaelc143
README.md
# ESPN Fantasy MCP
A small, read-only [Model Context Protocol](https://modelcontextprotocol.io/)
server for ESPN Fantasy Football. It gives an MCP-compatible LLM access to
normalized league snapshots, team rosters, and free-agent data.
This project calls ESPN's undocumented Fantasy read API. It is not an ESPN
official developer integration, so endpoints and response shapes may change.
Use it only with an account and leagues you are authorized to access, and
review ESPN's terms before distributing or hosting it for other users.
## What is included
The initial vertical slice exposes three read-only tools:
- `get_league_snapshot`: settings, teams, rosters, schedule, and status.
- `get_team_roster`: one normalized team and roster.
- `get_free_agents`: free agents and waiver players, with a bounded result set.
Write operations such as adding, dropping, trading, or setting a lineup are
intentionally not included. ESPN's mutation requests are undocumented and can
make irreversible league changes; they should be added only with a preview,
explicit confirmation, and strong validation.
## Requirements
- Python 3.11+
- `uv` or another Python package manager
- An ESPN Fantasy league ID and season year
- `ESPN_S2` and `ESPN_SWID` cookies for private leagues
## Install
```bash
uv sync --extra dev
cp .env.example .env
```
Fill in `.env` with your own values. Do not commit `.env` or put cookie values
in prompts, tool arguments, logs, or source control.
For a private league, the cookies are the values named `espn_s2` and `SWID`
in your authenticated ESPN browser session. The server reads them only from
environment variables. Public leagues may work without them.
## Run
For a local MCP host that launches stdio servers:
```bash
uv run espn-fantasy-mcp
```
Example generic MCP configuration:
```json
{
"mcpServers": {
"espn-fantasy": {
"command": "uv",
"args": [
"run",
"--directory",
"/absolute/path/to/EspnMCP",
"espn-fantasy-mcp"
],
"env": {
"ESPN_S2": "your-cookie-value",
"ESPN_SWID": "your-cookie-value",
"ESPN_BASE_URL": "https://lm-api-reads.fantasy.espn.com"
}
}
}
}
```
The server does not need to know a default league: tools receive `league_id`
and `season` explicitly, which makes accidental cross-league access less
likely.
## Test and lint
The tests mock ESPN and never contact the live service:
```bash
uv run pytest
uv run ruff check .
```
## Architecture
```text
MCP host / LLM
|
v
src/espn_mcp/server.py Tool schemas and MCP transport
|
v
src/espn_mcp/espn.py ESPN HTTP adapter and normalization
|
v
ESPN Fantasy read API Undocumented, cookie-authenticated for private leagues
```
The adapter isolates ESPN-specific payloads from the MCP layer. If ESPN
changes hosts, views, filters, or response shapes, update `espn.py` and its
fixtures rather than changing tool contracts.
TDQS
B3.4/5.0
Scored across 3 tools
Disambiguation5/5
Each tool has a clearly distinct purpose: league-wide snapshot, specific team roster, and free agent list. No meaningful overlap in functionality.
Naming Consistency5/5
All tool names follow the same 'get_' + noun pattern with snake_case, making them predictable and consistent.
Tool Count4/5
With only 3 tools, the set is minimal but fits a narrow read-only fantasy football use case. It is not bloated, though it borders on sparse.
Completeness3/5
The surface covers core read operations (league, team roster, free agents) but misses obvious fantasy football needs like standings, player details, or transaction history, leaving the domain partially incomplete.
Maintenance
ActivityMaintained
ResponsivenessNo issues