ESPN Fantasy MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ESPN Fantasy MCPWho are the top free agents in my league right now?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ESPN Fantasy MCP
A small, read-only Model Context Protocol 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.
Related MCP server: Sleeper Fantasy Football MCP
Requirements
Python 3.11+
uvor another Python package managerAn ESPN Fantasy league ID and season year
ESPN_S2andESPN_SWIDcookies for private leagues
Install
uv sync --extra dev
cp .env.example .envFill 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:
uv run espn-fantasy-mcpExample generic MCP configuration:
{
"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:
uv run pytest
uv run ruff check .Architecture
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 leaguesThe 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.
Available Tools
3 toolsget_free_agentsC
Find available free agents and waiver players. This is read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| season | Yes | ||
| league_id | Yes | ||
| positions | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description only states 'This is read-only,' which is a minimal behavioral disclosure. It does not explain what the tool actually returns, whether it filters or sorts results, or any side effects. Since there are no annotations to carry this burden, the description falls short of fully disclosing behavioral expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise and to the point. It consists of two short sentences with no redundant information. The structure is clean and easily parsed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Although an output schema exists (not shown), the description lacks contextual details about what results are returned and how parameters affect the search. It does not mention sorting, filtering, pagination, or any other behavior. Given the tool's moderate complexity (4 parameters), the description is incomplete for a user to fully understand its capabilities.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides no descriptions for parameters (0% coverage), and the description does not clarify any of them. Parameters like league_id, season, limit, and positions are left entirely unexplained. The description adds no meaning beyond the bare parameter names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Find available free agents and waiver players.' It uses a specific verb ('find') and identifies the resource (free agents/waiver players). This distinguishes it from sibling tools like get_league_snapshot and get_team_roster, which have different scopes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no explicit guidance on when to use this tool versus alternatives. It does not mention any scenarios or conditions that would make this tool preferable to get_league_snapshot or get_team_roster. The 'read-only' note is implicit but does not help in tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_league_snapshotB
Get league settings, teams, rosters, schedule, and matchup data.
This is read-only. Use the league ID visible in the ESPN Fantasy URL.
| Name | Required | Description | Default |
|---|---|---|---|
| season | Yes | ||
| league_id | Yes | ||
| scoring_period_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses that the operation is read-only, which is a key safety trait, and offers a hint on sourcing the league ID. However, it does not describe other behavioral aspects like return format, pagination, or any potential rate limits, though the output schema partially covers returns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The primary purpose is front-loaded, and the read-only note is concise. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having an output schema, the description fails to explain two of three parameters and offers no usage guidance. For a snapshot tool with multiple data types, this is insufficient to guide an agent effectively, especially without annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for all parameters. It provides a meaningful hint for league_id (source from URL) but says nothing about season or scoring_period_id, leaving their purpose and format unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get') and resource ('league snapshot') and enumerates the data types included (settings, teams, rosters, schedule, matchup data). It implicitly differentiates from siblings like get_team_roster (specific team) and get_free_agents (free agents) by covering the whole league, but does not explicitly contrast them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus the sibling tools. It only mentions that it is read-only and provides a hint about the league ID source, but does not state conditions for choosing this over get_team_roster or get_free_agents, nor any exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_team_rosterB
Get one team's normalized roster and record. This is read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| season | Yes | ||
| team_id | Yes | ||
| league_id | Yes | ||
| scoring_period_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. It discloses the read-only nature, which is a meaningful safety signal. However, it adds nothing else — no mention of data volume, normalization specifics, or failure behavior. The output schema covers return format, so the read-only disclosure is the main contribution.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero waste; the action is front-loaded and the read-only qualifier earns its place as behavioral disclosure. Could be slightly more informative without hurting conciseness, but as written it is efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 4 parameters, 0% schema coverage, and no annotations, the description is thin. The output schema documents returns, which helps, and parameter names are intuitive, but there is no guidance on parameter semantics or sibling differentiation. An agent would need to infer scoring_period_id's meaning and when this tool is preferable to the siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description adds no parameter meaning whatsoever. The parameter names (league_id, season, team_id, scoring_period_id) are self-explanatory, which mitigates the gap somewhat, but scoring_period_id's role and the semantics of 'normalized' roster are left entirely to inference.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get one team's normalized roster and record'), with scope clarified by 'one team's.' The 'normalized' qualifier adds specificity about the data transformation. It distinguishes from siblings by scope (a single team's data vs a league snapshot or free agents), though it doesn't name them explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The usage context is implied by the description — an agent can infer this is for retrieving a specific team's roster rather than league-wide or free-agent data. However, there is no explicit when/when-not guidance or named alternatives, so the agent must reason from the sibling tool names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
get_free_agents - First observed
get_league_snapshot - First observed
get_team_roster
TDQS
Scored across 3 tools
Each tool has a clearly distinct purpose: league-wide snapshot, specific team roster, and free agent list. No meaningful overlap in functionality.
All tool names follow the same 'get_' + noun pattern with snake_case, making them predictable and consistent.
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.
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
Related MCP Connectors
Read-only ESPN, Sleeper, and Fantrax fantasy leagues for Claude, ChatGPT, and other AI tools.
Read-only fantasy analysis for ESPN, Yahoo, and Sleeper leagues via MCP
- NFL MCPOAuthcom.nflmcp
NFL analytics tools for AI agents: stats, fantasy, injuries, schedules, and advanced analysis.
ESPN MCP — keyless multi-sport live scores, teams, and news via ESPN's public site API.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceProvides read-only access to Sleeper fantasy football leagues, enabling team snapshots, available players, matchups, trade context, and league history through standardized MCP tools.MIT
- AlicenseAqualityCmaintenanceA read-only MCP server that supplies live context from Sleeper fantasy-football leagues, including rosters, trade analysis, draft picks, and league settings via Sleeper's public API.11MIT
- AlicenseNot gradedqualityCmaintenanceProvides read-only, league-aware Sleeper fantasy football draft context to AI assistants, including live picks, rosters, and player availability over Streamable HTTP MCP.62 npmMIT
- FlicenseNot gradedqualityCmaintenanceRead-only MCP server that provides access to public Sleeper NFL fantasy data, including leagues, rosters, matchups, waivers, drafts, and player information. It enables AI clients to retrieve fantasy football details without requiring authentication or account modifications.-