Skip to main content
Glama
tlo1216

espn-fantasy-mcp

by tlo1216

espn-fantasy-mcp

A local MCP server that reads and writes ESPN fantasy sports (football, basketball, baseball) using your own ESPN session cookies. It replaces manually driving a browser pane for ESPN: Claude Code or Codex can call its tools directly. No web UI, no cloud, no server — one Node process talking stdio to your AI client, and HTTPS to ESPN.

It does not propose, accept, or reject trades. That's out of scope permanently.


Setup (do this once)

These steps are written to be followed exactly, in order — copy-paste the commands.

1. Prerequisites

  • Node.js 20 or newer (node --version)

  • An ESPN account that's a member of the fantasy league you want to control

  • Git and (optionally) the GitHub CLI (gh) if you're cloning from a private repo

2. Clone and install

git clone <this-repo-url> espn-fantasy-mcp
cd espn-fantasy-mcp
npm install
npm run build

npm run build compiles src/ to dist/index.js, which is what your MCP client will actually launch.

3. Get your ESPN cookies

ESPN's fantasy API isn't public — it authenticates the same way your browser does, with two cookies. There is no username/password step; you copy these two values once and they last about a month.

  1. Log into https://fantasy.espn.com in any browser, and open your league.

  2. Open DevTools (F12 or right-click → Inspect).

  3. Go to Application (Chrome/Edge) or Storage (Firefox) → Cookieshttps://fantasy.espn.com.

  4. Find the cookie named espn_s2 — copy its whole value (it's long).

  5. Find the cookie named SWID — copy its value including the curly braces, e.g. {ABCDEF12-3456-7890-ABCD-EF1234567890}.

Never paste these into a chat with an AI assistant, an issue, or a commit. They go in one place only: your local .env file, which is already listed in .gitignore.

4. Configure

cp .env.example .env

Edit .env:

ESPN_S2=<paste the espn_s2 value>
ESPN_SWID=<paste the SWID value, with braces>
ESPN_SPORT=ffl          # ffl = football, fba = basketball, flb = baseball
ESPN_SEASON=2026
ESPN_LEAGUE_ID=<your league id — the number in your league's ESPN URL>
ESPN_TEAM_ID=<your team id in that league>
WRITES_ENABLED=false    # leave false until you've checked dry runs look right

Your league id and team id are both visible in the URL when you're looking at your team on fantasy.espn.com (...leagueId=XXXXXXX...&teamId=N).

5. Sanity-check it runs

node dist/index.js

You should see espn-fantasy-mcp running (sport=..., season=..., writes disabled (dry run only)) printed to stderr, and the process will sit waiting for stdio input — that's correct for an MCP server. Ctrl+C to stop it. If you see an error about ESPN_S2 and ESPN_SWID are not set, go back to step 4.


Related MCP server: sleeper-mcp

Connect it to your AI client

Claude Code

claude mcp add espn-fantasy -- node /absolute/path/to/espn-fantasy-mcp/dist/index.js --scope user

--scope user makes it available in every Claude Code session on this machine, not just the current project. Alternatively, drop this in a project's .mcp.json:

{
  "mcpServers": {
    "espn-fantasy": {
      "command": "node",
      "args": ["/absolute/path/to/espn-fantasy-mcp/dist/index.js"]
    }
  }
}

Codex

Add to Codex's MCP server config (~/.codex/config.toml or equivalent):

[mcp_servers.espn-fantasy]
command = "node"
args = ["/absolute/path/to/espn-fantasy-mcp/dist/index.js"]

Restart Claude Code / Codex after adding the server.


Tools

Every tool takes sport, season, league_id (all default from .env if omitted). Write tools also take team_id.

Reads (no confirmation needed, rate-limited to 2/sec, not logged)

Tool

What it does

get_league

Settings: scoring, roster slots, acquisition/waiver settings, schedule, trade settings, current scoring period

get_teams

Team ids, names, owners, records, waiver rank

get_rosters

Every team's roster (or one team_id): player id, name, position, pro team, eligible slots, lineup slot, injury status, lock state, projections

get_free_agents

Free agents / waiver wire, filterable by slot, sorted by ownership or projection

get_matchups

A scoring period's matchups: totals and live projections

get_boxscore

A scoring period's per-player actuals

get_transactions

Executed transactions (adds, drops, trades, draft picks), most recent first, resolved to player names. Paginated (limit/offset) — a full season's draft alone can be 100+ records

get_pending

Pending waiver claims and trade proposals (read-only — this server never acts on trades)

get_player

Look up a player by id or name search

snapshot

League state in the line-oriented text format used by frontoffice-manager's tools/diff-snapshot.mjs

optimal_lineup

Suggests a starting lineup (fills the most restrictive slots first, then best remaining projection), ranked by season or a specific scoring period. A heuristic suggestion only — apply it yourself via set_lineup if you agree with it

Writes (rate-limited to 1 per 5 sec, every real send logged to logs/writes.jsonl)

Every write tool takes dry_run (default true). A dry run validates and reports what would be sent without sending it. Setting dry_run: false only actually executes if WRITES_ENABLED=true in .env — otherwise it's still treated as a dry run. After a real write, the tool re-reads the affected state and returns it so you can confirm the change landed.

Tool

What it does

set_lineup

Apply a batch of {player_id, to_slot} moves. Validates roster membership, slot eligibility, lock state, and the league's slot-count limits before sending anything.

add_free_agent

Add an unclaimed free agent, optionally dropping another player

waiver_claim

Submit a waiver claim, optional conditional drop, optional FAAB bid

cancel_claim

Cancel a pending waiver claim by transaction id

move_to_ir

Move a player to IR/IL (a lineup move to the IR slot)

activate_from_ir

Move a player out of IR/IL into an active or bench slot

Not implemented, ever: proposing, accepting, or rejecting trades.


Known limits — read before relying on this

  • This uses an undocumented API. ESPN can change response shapes or payloads at any time without notice; nothing here is officially supported.

  • Cookies expire, typically after about a month. When a request that used to work starts returning a clear "refresh your cookies" error, go back to step 3 above. The server never retries a 401 and never prints cookie values, even in error messages or logs.

  • set_lineup (and the move_to_ir / activate_from_ir tools built on it) can execute real writes — the lineup-move payload was captured live on 2026-09-10 (see The lineup-move payload below) and is implemented in buildLineupBody in src/espn/writes.ts, verified in dry run against a real roster.

  • Rate limits are conservative and process-local (2 reads/sec, 1 write per 5 sec) — fine for one interactive AI client, not built for concurrent callers.

  • The read/write endpoint split matters: reads go to lm-api-reads.fantasy.espn.com, writes to lm-api-writes.fantasy.espn.com. Mixing them up produces confusing errors.

The lineup-move payload

Captured live on 2026-09-10 from a real bench↔FLEX swap. ESPN's lineup UI sends the move as a ROSTER transaction with one LINEUP item per player whose slot changed — a two-way swap is two items, each carrying that player's own prior slot as fromLineupSlotId:

{
  "isLeagueManager": false, "teamId": 5, "type": "ROSTER",
  "memberId": "{SWID}", "scoringPeriodId": 1, "executionType": "EXECUTE",
  "items": [
    {"playerId": 4429023, "type": "LINEUP", "fromLineupSlotId": 20, "toLineupSlotId": 23},
    {"playerId": 4568490, "type": "LINEUP", "fromLineupSlotId": 23, "toLineupSlotId": 20}
  ]
}

Implemented in buildLineupBody in src/espn/writes.ts. If ESPN ever changes this shape, re-capture it the same way:

  1. Open a fantasy.espn.com team page in a logged-in browser, on your team's roster tab.

  2. Open DevTools Console and paste an interceptor, then press Enter. Note: ESPN's lineup-move request is sent via XMLHttpRequest, not fetch — a fetch-only interceptor (like the one used for the waiver-claim/cancel-claim payloads) will silently miss it. Wrap both:

    (function(){
      const of = window.fetch;
      window.fetch = async function(u,o){ try{ if(String(u).includes('lm-api-writes')){ const a=JSON.parse(sessionStorage.ffcap||'[]'); a.push({kind:'fetch',u:String(u),m:o&&o.method,b:o&&o.body}); sessionStorage.ffcap=JSON.stringify(a);} }catch(e){} return of.apply(this,arguments); };
      const open = XMLHttpRequest.prototype.open, send = XMLHttpRequest.prototype.send;
      XMLHttpRequest.prototype.open = function(method,url){ this.__cap_url=url; this.__cap_method=method; return open.apply(this,arguments); };
      XMLHttpRequest.prototype.send = function(body){ try{ if(this.__cap_url && String(this.__cap_url).includes('lm-api-writes')){ const a=JSON.parse(sessionStorage.ffcap||'[]'); a.push({kind:'xhr',u:String(this.__cap_url),m:this.__cap_method,b:body}); sessionStorage.ffcap=JSON.stringify(a);} }catch(e){} return send.apply(this,arguments); };
    })();
  3. Make one lineup move in the UI (drag a player, or use Move/Here) and confirm it.

  4. Run sessionStorage.ffcap in the console and copy the result.

  5. Redact espn_s2 and SWID from anything captured before sharing or committing it.


Slot id reference

Football (ffl): 0 QB, 2 RB, 4 WR, 6 TE, 23 FLEX, 16 D/ST, 17 K, 20 Bench, 21 IR.

Basketball (fba): 0 PG, 1 SG, 2 SF, 3 PF, 4 C, 5 G, 6 F, 7 SG/SF, 8 G/F, 9 PF/C, 10 F/C, 11 UTIL, 12 Bench, 13 IR.

Baseball (flb): 0 C, 1 1B, 2 2B, 3 3B, 4 SS, 5 OF, 6 2B/SS, 7 1B/3B, 8 LF, 9 CF, 10 RF, 11 DH, 12 UTIL, 13 P, 14 SP, 15 RP, 16 Bench, 17 IL, 19 IF.

Full tables (including pro-team and stat-id maps) are in src/espn/constants.ts.


Development

npm run build   # compile TypeScript
npm test        # run unit tests (lineup validator, snapshot formatter)
npm start        # run the compiled server directly
npm run dev      # run from source with tsx, no build step

Project layout: src/index.ts (tool registration and output schemas), src/espn/client.ts (HTTP, cookies, rate limiting, 401 handling), src/espn/constants.ts (slot/team/position tables), src/espn/reads.ts / src/espn/writes.ts (API calls and payload building), src/lineup.ts (local lineup-move validation), src/optimalLineup.ts (the optimal_lineup suggestion algorithm), src/snapshot.ts (the text snapshot format), test/ (unit tests, no network).

Credits

The ESPN v3 fantasy API is undocumented; this project leans on prior reverse-engineering work rather than starting from scratch:

  • cwendt94/espn-api (Python) — the slot/position/pro-team/stat-id constant tables in src/espn/constants.ts are ported from here, and the lineupLocked roster-entry field used for lock detection was confirmed from its player-parsing code.

  • mkreiser/ESPN-Fantasy-Football-API (JavaScript) — read-endpoint client for cross-reference.

  • KBThree13/mcp_espn_ff — an existing Python MCP server for ESPN football reads, referenced for tool naming.

  • dylancharris's ESPN fantasy basketball MCP (LobeHub listing) — referenced for basketball tool coverage.

  • stmorse's ESPN fantasy v3 API notes and the ffscrapr R package's endpoint vignette — view/endpoint documentation.

  • tlo1216/frontoffice-manager's tools/ scripts (snapshot-fetch.js, espn-cookie-fetch.mjs, diff-snapshot.mjs, and the espn-*-cheatsheet.md files) — the source for the exact snapshot line format and the cheat-sheet facts this README and src/espn/constants.ts are cross-checked against.

  • MCP TypeScript SDK@modelcontextprotocol/sdk, used directly.

License

MIT. See LICENSE.

Uses your own ESPN session. Not affiliated with, endorsed by, or supported by ESPN. ESPN's fantasy API is undocumented and unofficial, and automating it may be against ESPN's terms of service. You run this at your own risk.

Available Tools

17 tools
activate_from_irActivate From IRA

Move one player out of the IR/IL slot into an active or bench slot, as a lineup move.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
dry_runNoDefault true: validates and reports what would be sent without sending it. Set false to actually execute (still a no-op if WRITES_ENABLED=false in .env).
team_idNo
to_slotYesDestination slot id (e.g. bench). Must not be the IR slot itself.
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456
player_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
sentNo
dryRunYes
responseNo
wouldSendNo
validationYes
verificationNo
blockedReasonNo

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=false, so the description's implied mutating behavior is consistent. The phrase 'lineup move' adds mild context, but the description does not disclose operational details such as dry_run defaults or environment-dependent execution, which are left to the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single clear sentence with no filler. The core action is front-loaded and every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema, parameter defaults, and sibling context, the definition provides enough for an agent to understand and invoke the tool. It is slightly thin on operational behavior, but the schema compensates for most of that gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 71%, and key parameters like dry_run, sport, season, and league_id are already documented in the schema. The description adds little semantic value beyond the schema, though 'active or bench slot' loosely reinforces the meaning of to_slot.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Move') with a clear resource ('one player out of the IR/IL slot') and destination ('into an active or bench slot'). It uniquely distinguishes this operation from siblings like move_to_ir and set_lineup.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrasing establishes the clear context: a player currently in the IR/IL slot should be moved into an active/bench spot as a lineup adjustment. It does not explicitly name alternatives or exclusions, but the intended use case is not ambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_free_agentAdd Free AgentA

Add an unclaimed free agent (not a waiver-wire player — use waiver_claim for those), optionally dropping another player in the same move.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
dry_runNoDefault true: validates and reports what would be sent without sending it. Set false to actually execute (still a no-op if WRITES_ENABLED=false in .env).
team_idNo
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456
add_player_idYes
drop_player_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
sentNo
dryRunYes
responseNo
wouldSendNo
verificationNo
blockedReasonNo

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already convey that this is a non-read-only, non-destructive operation, so the safety profile is covered. The description adds useful context about targeting unclaimed free agents and optionally dropping another player, but it does not go deeper into side effects or transaction behavior. The dry-run behavior is documented in the schema, so the description does not repeat it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence that states the action, the exception, the sibling tool to use instead, and the optional drop behavior. There is no filler or redundant restating of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and schema documentation for dry_run, sport, season, and league_id, the agent has most of what it needs. The description routes the agent to the correct sibling and clarifies add/drop semantics. The remaining gap is the ambiguous team_id parameter, but required add_player_id and defaults make invocation feasible.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 57%, so the schema handles sport, season, dry_run, and league_id. The description helps clarify drop_player_id with 'optionally dropping another player,' and add_player_id is inferable from the tool's purpose. However, team_id remains undocumented in both schema and description, leaving an ambiguity for the agent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific action ('Add') and resource ('unclaimed free agent'), and explicitly distinguishes it from waiver-wire players by pointing to waiver_claim. It also discloses the optional drop behavior, which clearly differentiates it from sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when NOT to use this tool ('not a waiver-wire player') and names the alternative ('use waiver_claim for those'). This gives the agent a clear decision rule without needing to inspect other tool definitions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cancel_claimCancel ClaimA
DestructiveIdempotent

Cancel a pending waiver claim by its transaction id (from get_pending).

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
dry_runNoDefault true: validates and reports what would be sent without sending it. Set false to actually execute (still a no-op if WRITES_ENABLED=false in .env).
team_idNo
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456
transaction_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
sentNo
dryRunYes
responseNo
wouldSendNo
verificationNo
blockedReasonNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false; the description adds that only pending waiver claims are affected and that the claim is identified via get_pending. This clarifies what is being acted on beyond the annotation flags, although it does not discuss reversibility or post-cancel effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One concise, front-loaded sentence contains the action, target, and parameter source with no filler. Every element contributes to the agent's understanding of what to call and how.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With defaults documented in the schema, an output schema available, and destructive behavior covered by annotations, the description plus schema provides everything needed to call the tool correctly. The get_pending workflow dependency is explicitly named, so the required context is not missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 67%, and the description compensates for the undocumented required transaction_id by saying it comes from get_pending. Other parameters such as sport, season, dry_run, and league_id are already documented in the schema; team_id remains minimally described but is a defaulted integer with low ambiguity.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Cancel') and resource ('a pending waiver claim'), and identifies the key identifier ('transaction id (from get_pending)'). This distinguishes it from siblings like waiver_claim or add_free_agent, which perform different actions, without merely restating the tool name.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly ties usage to a pending claim retrieved via get_pending, which provides clear when-to-use context. It does not name alternatives or list exclusions, but the workflow dependency is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_boxscoreGet BoxscoreA
Read-onlyIdempotent

Per-player actual stats for a scoring period, for both teams in each matchup.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456
scoring_period_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the description correctly adds scope semantics: 'actual stats' distinguishes from projected stats and 'both teams in each matchup' clarifies coverage. No contradiction exists between the description and annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence with no filler: the key concepts 'per-player actual stats', 'scoring period', and 'both teams in each matchup' appear in order of importance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema, strong annotations, and defaults documented in the input schema, the description covers the essential scope. A small gap is not naming an alternative for projected stats, but that is not required for invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 75% (sport, season, and league_id are documented), and the description reinforces scoring_period_id via 'scoring period'. It does not add new meaning beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description identifies the resource as per-player actual stats for a scoring period and scopes it to both teams in each matchup, which distinguishes it from get_matchups (matchup-level data) and get_player (single-player data). It lacks an explicit verb like 'Retrieve', but the meaning is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'actual stats' implies use when real boxscore data is needed rather than projections or rosters, but no sibling tools or when-not-to-use conditions are mentioned. The usage context is inferable from the description but not explicitly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_free_agentsGet Free AgentsA
Read-onlyIdempotent

Free agents and waiver-wire players, sorted by ownership percent (default) or projection. Optionally filter by lineup slot id (see get_league for slot ids, or the README's slot tables).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax players to return.
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
sort_byNoowned
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456
position_slot_idNoFilter to one lineup slot id, e.g. 2 for RB in football.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and non-destructive behavior, so the safety profile is fully covered. The description adds useful behavioral context about the default sort order and the projection sort option, but does not detail what qualifies as a free agent vs waiver-wire player or any response characteristics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler; the primary behavior and default sorting are front-loaded, and the optional filtering note is placed at the end. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With rich annotations, a complete input schema covering defaults and valid values, and an output schema present, the description covers all that an agent needs to invoke the tool correctly. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is high (83%), and the description reinforces the meaning of sort_by and position_slot_id. It uniquely adds the cross-reference to get_league/README for slot IDs, which helps an agent supply valid values for position_slot_id.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('free agents and waiver-wire players') and clarifies sorting by ownership percent or projection. It is clearly distinct from sibling mutation tools like add_free_agent or waiver_claim, which operate on this same player pool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use—browsing available unrostered players—is clear from the description, and the optional filter is explained. It does not explicitly state when not to use it or compare against get_player/get_transactions, but the context is strong enough that an agent can select it correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_leagueGet League SettingsA
Read-onlyIdempotent

League settings: scoring format, roster slot counts, acquisition (waiver) settings, schedule, trade settings, draft/keeper settings, and the current scoring/matchup period.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456

Output Schema

ParametersJSON Schema
NameRequiredDescription
nameNo
leagueIdYes
seasonIdYes
teamCountNo
draftSettingsNo
tradeSettingsNo
rosterSlotCountsNo
scheduleSettingsNo
acquisitionSettingsNo
currentMatchupPeriodNo
currentScoringPeriodNo

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the read-only/idempotent safety profile. The description adds value by revealing the breadth of returned settings, including the current scoring/matchup period, beyond what the annotations encode. No behaviors contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence lists the settings in a compact, scannable colon list with no filler. Every item earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema, annotations, and complete parameter schema, the description covers what the tool returns and its safety profile. A slightly more explicit 'returns/retrieves' verb would make it fully self-contained, but nothing critical for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All three parameters are fully documented in the schema with descriptions, defaults, and an enum for sport. The description adds no parameter-specific meaning, which is acceptable because schema coverage is 100%.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Title and first words identify the resource as league settings, and the description enumerates concrete setting categories (scoring, roster slots, waivers, schedule, trades, draft/keepers, periods). This separates it from sibling roster/team/matchup tools, though the description itself relies on the 'Get League Settings' title for the action verb.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The category list makes it plain that this tool is for league-level configuration data, offering implied guidance for when to use it. However, it does not name alternatives or state when not to use it, so an agent must infer selection from the sibling names rather than explicit guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_matchupsGet MatchupsA
Read-onlyIdempotent

Matchups for a scoring period: home/away team ids, live/final totals, and live projections.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456
scoring_period_idYesWeek (football) or day (basketball/baseball).

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is known. The description adds value by specifying the content of the response (home/away IDs, totals, projections), which is not conveyed by annotations. No contradictions, and the added detail helps set expectations without overstepping.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence that front-loads the core purpose and then lists the key output fields. Every word contributes value; there is no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has an output schema and comprehensive parameter schema, the description is sufficient. It covers the essential return content and does not omit critical calling details. It could mention pagination or sorting, but these are not expected for a straightforward matchup list, so a 4 is appropriate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all four parameters, including the meaning of scoring_period_id ('Week (football) or day (basketball/baseball)'). The description does not add any parameter-specific guidance beyond what the schema already provides, so the baseline score of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('get'), the resource ('matchups'), and the scope ('for a scoring period'), and enumerates the specific data returned (home/away team ids, live/final totals, live projections). This distinguishes it from siblings like get_teams or get_boxscore by focusing on the matchup-level summary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context (scoring period) but does not explicitly state when to prefer this tool over alternatives such as get_boxscore or get_teams. No exclusions or alternative routing are provided; an agent would have to infer when matchups are needed vs. a single game's details.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_pendingGet Pending TransactionsA
Read-onlyIdempotent

Pending waiver claims and trade proposals, with items resolved to player names. Trades are read-only here — this server never proposes, accepts, or rejects trades.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, and the description adds useful clarification that trades are read-only and that the server never proposes, accepts, or rejects trades. This prevents an agent from assuming it can act on the returned trade proposals through this tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The first sentence front-loads the resource and output behavior, and the second adds a critical read-only clarification that earns its place. Nothing extraneous is included.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with zero required parameters, fully documented schema, rich safety annotations, and an output schema present, the description is complete. Nothing an agent needs to correctly invoke this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with each parameter (sport, season, league_id) having a clear description and default value. The description adds no parameter-specific information, so the schema carries the full burden, matching the baseline for high coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description names a specific verb and resource: 'Pending waiver claims and trade proposals.' It also distinguishes itself from the broader sibling get_transactions by explicitly scoping to pending items, so an agent knows exactly what this tool returns.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes clear this is the read-only view of trades and waiver claims, contrasting with mutation siblings like waiver_claim or cancel_claim. It does not explicitly name alternative tools, but the context is strong enough that an agent can infer when to use get_pending versus mutation or broader transaction tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_playerGet PlayerA
Read-onlyIdempotent

Look up one player by ESPN player id, or by a case-insensitive name substring search across rosters and free agents.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNo
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456
name_searchNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
nameYes
lockedNo
teamIdNo
proTeamYes
positionYes
injuryStatusNo
lineupSlotIdNo
percentOwnedNo
periodActualNo
lineupSlotNameNo
eligibleSlotIdsYes
periodProjectionNo
seasonProjectionYes
eligibleSlotNamesYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds behavioral context: the name search is case-insensitive and searches across both rosters and free agents. It also implies the tool returns a single player ('one player'), which is useful. It doesn't mention edge cases like no match or multiple matches, but the output schema likely covers the return shape.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that front-loads the primary lookup method (id) and then adds the secondary method (name substring). Every word earns its place, and it's appropriately sized for a simple lookup tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema, so return values are documented elsewhere. The description covers the two lookup modes and the search scope. It doesn't specify behavior when both id and name_search are provided, or what happens with no matches, but these are minor gaps given the output schema and annotations. The tool is simple enough that the description is nearly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 60%, so the schema documents sport, season, and league_id with defaults. The description adds meaning for 'id' and 'name_search' by explaining they are the two lookup methods, but it doesn't add detail beyond what the schema provides for the other parameters. The description doesn't explain the relationship between id and name_search (e.g., are they mutually exclusive? what if both are provided?). Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Look up one player by ESPN player id, or by a case-insensitive name substring search across rosters and free agents.' It specifies the resource (player), the lookup methods (id or name substring), and the scope (rosters and free agents). This distinguishes it from sibling tools like get_rosters or get_free_agents, which list collections rather than look up a single player.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use this tool: when you need a single player by id or name. It doesn't explicitly state when not to use it or name alternatives, but the context of siblings (get_rosters, get_free_agents) makes the distinction clear. It could be improved by explicitly saying 'use get_rosters to list all players' but the current wording is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_rostersGet RostersA
Read-onlyIdempotent

Every team's roster, or one team's roster if team_id is given. Each player includes id, name, position, pro team, eligible slots, current lineup slot, injury status, lock state, and season/period projections.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
team_idNoLimit to one team id.
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, covering the safety profile. The description adds behavioral scoping (team_id limits to one team) and enumerates the returned fields (position, injury status, lock state, etc.), which goes beyond the annotations and gives the agent a clearer picture of what to expect. This exceeds the minimal baseline for annotation-covered tools.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with zero filler. The first sentence front-loads the core purpose and scoping, the second succinctly lists the player fields. Every word earns its place, and the length is appropriate for the tool's simplicity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is a simple read operation with all parameters optional and fully described in the schema, an output schema is present (so return format is covered), and annotations cover safety. The description adds the team_id scoping and field list, which is enough for an agent to call it correctly. No critical gaps exist.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for all 4 parameters, so the baseline is 3. The description adds meaning to team_id by clarifying that it limits results to one team, which is a meaningful semantic beyond the schema's 'Limit to one team id.' The other parameters (sport, season, league_id) are already well-described in the schema, so the description's additional value is moderate but sufficient to warrant a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns rosters, with an explicit scoping condition ('or one team's roster if team_id is given'). It distinguishes from siblings like get_teams (teams vs. rosters) and get_free_agents (free agents vs. rosters) by naming the specific resource (rosters) and the player fields included. This is a specific verb+resource with clear scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a usage condition for team_id ('if team_id is given') but does not explicitly state when to use this tool over alternatives like get_teams or get_free_agents, nor does it mention exclusions. The usage context is implied but not explicit, so it falls short of providing clear alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_teamsGet TeamsA
Read-onlyIdempotent

All teams in the league: id, name, owners, record, and waiver rank.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false, so the safety profile is fully covered. The description adds the specific fields returned, which is useful context, but it doesn't mention any behavioral nuances like pagination, ordering, or potential response size. Since annotations carry the load, a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, efficient sentence with zero filler. The key action and resource are front-loaded ('All teams in the league'), followed by the returned fields. No unnecessary words or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description doesn't need to detail the return structure. The high-level summary of fields, combined with full schema coverage and annotations for safety, gives an agent everything needed to invoke this tool correctly. Nothing is missing for a straightforward read operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with each parameter (sport, season, league_id) having a clear description and defaults. The tool description adds no additional parameter-level information beyond what the schema already provides. Baseline 3 is correct when the schema is exhaustive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

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 ('teams'), and lists the exact fields returned (id, name, owners, record, waiver rank). It clearly distinguishes this from sibling tools like get_rosters (which would return roster data) and get_league (which would return league settings). No ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: it returns all teams in the league. It doesn't explicitly mention when not to use it, but the scope is obvious and it doesn't conflict with any sibling. For a simple read-only getter, this level of guidance is sufficient, though it could have named alternatives for contrast.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_transactionsGet TransactionsA
Read-onlyIdempotent

Executed transactions (adds, drops, trades, lineup moves, draft picks), most recent first, with items resolved to player names. Paginated — a full season's draft alone can be 100+ records, so use limit/offset rather than expecting everything at once. Response includes total/count/offset/hasMore.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax transactions to return.
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
offsetNoNumber to skip, for paging through more.
seasonNoSeason year. Defaults to ESPN_SEASON.
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456

Output Schema

ParametersJSON Schema
NameRequiredDescription
countYes
totalYes
offsetYes
hasMoreYes
transactionsYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark it read-only, idempotent, and non-destructive; the description adds the pagination envelope (total/count/offset/hasMore), ordering, and player-name resolution, none of which is visible in annotations or schema. No contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences carry all the meaningful behavioral information with no filler. The core act is front-loaded and the pagination warning is placed immediately where the agent will need it.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only paginated list tool with 100% schema coverage, full annotations, and an output schema, the description covers everything an agent needs to select and call it correctly. It even preempts the common failure mode of expecting all records in one response.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains limit, offset, sport, season, and league_id. The description reinforces that limit/offset are necessary for paging, but adds no new parameter-level detail beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Executed transactions') with categories (adds, drops, trades, lineup moves, draft picks), a defined ordering (most recent first), and a transformation trait (items resolved to player names). The qualifier 'executed' distinguishes it from the sibling get_pending without needing to open that tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit operational guidance: it is paginated and limit/offset should be used because a season's draft alone can be 100+ records. It stops short of explicitly naming an alternative such as get_pending for pending/unprocessed transactions, so the when-not-to-use guidance is implied rather than direct.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

move_to_irMove to IRA

Move one player into the IR/IL slot, as a lineup move. Refuses if the player isn't eligible for IR or is locked.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
dry_runNoDefault true: validates and reports what would be sent without sending it. Set false to actually execute (still a no-op if WRITES_ENABLED=false in .env).
team_idNo
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456
player_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
sentNo
dryRunYes
responseNo
wouldSendNo
validationYes
verificationNo
blockedReasonNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=false, destructiveHint=false, idempotentHint=false. The description adds that the tool refuses if the player isn't eligible or is locked, and the dry_run parameter in the schema adds safety context. It doesn't contradict annotations. It could mention whether it's reversible, but the refusal conditions and dry_run default provide meaningful behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action and scope, followed by refusal conditions. No wasted words. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema, so return values are covered. The description covers the core behavior, refusal conditions, and the dry_run safety mechanism is in the schema. It doesn't explicitly mention the relationship to activate_from_ir, but the sibling list and description are sufficient for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 67%, and the description doesn't add much parameter-level detail beyond what the schema provides. The dry_run parameter is well-documented in the schema. The description's mention of 'refuses if not eligible' relates to player_id semantics but doesn't add new parameter meaning. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Move one player into the IR/IL slot'), the resource (player), and the context (as a lineup move). It also distinguishes itself from siblings by mentioning IR/IL eligibility and lock refusal, which differentiates it from activate_from_ir and set_lineup.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use it: when a player is IR-eligible and the user wants to make a lineup move. It doesn't explicitly name alternatives like activate_from_ir, but the context and sibling list make the use case clear. It also states refusal conditions (not eligible or locked), which helps an agent decide when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

optimal_lineupOptimal Lineup SuggestionA
Read-onlyIdempotent

Suggests a starting lineup for one team: fills the most restrictive slots first (fewest eligible roster players), then the best remaining projection for each slot — the same approach the cheat sheets describe by hand. A heuristic, not a guaranteed-optimal assignment. Ranks by season projection by default, or by a specific scoring period's projection if scoring_period_id is given (a bye-week/no-game player ranks 0 for that period, not by season total). Locked players keep their current slot. This is a suggestion only — pass the resulting moves to set_lineup yourself if you want to apply them.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
team_idNo
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456
scoring_period_idNoRank by this period's projection instead of season total.

Output Schema

ParametersJSON Schema
NameRequiredDescription
benchYes
startersYes
usingPeriodProjectionYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the near term read-only/idempotent/destructive annotations, it adds critical behavioral detail: this is a heuristic, not guaranteed optimal; bye-week/no-game players rank 0 for a given scoring period; locked players keep their slot; and it is a suggestion that does not modify. This is rich context that a caller must know to trust the output.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense run-on-style paragraph that front-loads the mechanism, then gives heuristics and cautions. It is not overly bloated—each sentence carries a distinct fact (algorithm, non-optimality, ranking period, locked players, apply-offloading). A tiny bit more line break would improve scannability, but it's far from verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With output schema present and safety annotations already in place, the description fills all functional gaps: what it suggests, how it picks slots, what numbers it uses (season vs scoring period), how locked players behave, and how to apply the result. No missing information that would prevent a correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents sport, league, etc. The description adds meaningful behavior for scoring_period_id (ranks by that period, modifies bye-week behavior) and overall ties the heuristic to 'best projection'. It doesn't explain team_id's enumeration but the default of 1 and the 'one team' wording make it adequate; the description adds value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ("suggests") and a specific resource ("a starting lineup for one team"), and it goes further by contrasting its purpose with set_lineup ("pass the resulting moves to set_lineup yourself"). This clearly differentiates it from siblings like get_rosters and set_lineup.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says the tool is a non-committal suggestion and that the caller should invoke set_lineup to apply the moves. It also tells the agent when to add scoring_period_id (when ranking by a specific period) and clarifies the two different projection modes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_lineupSet LineupA

Apply a batch of lineup moves to one team. Validates every move locally first (player is on the roster, target slot is eligible, player isn't locked, and the resulting lineup respects the league's slot counts) before sending anything. Rejected moves are reported with a reason and never sent.

ParametersJSON Schema
NameRequiredDescriptionDefault
movesYes
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
dry_runNoDefault true: validates and reports what would be sent without sending it. Set false to actually execute (still a no-op if WRITES_ENABLED=false in .env).
team_idNo
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456

Output Schema

ParametersJSON Schema
NameRequiredDescription
sentNo
dryRunYes
responseNo
wouldSendNo
validationYes
verificationNo
blockedReasonNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes beyond annotations by revealing the local validation phase, noting that validations happen before anything is sent, and stating that rejected moves are reported with a reason and never sent. Annotations already indicate this is a non-read operation, so this context meaningfully adds to the behavioral model.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded. Every sentence carries distinct information: what the tool does, how validation works, and what happens with rejected moves. There is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is adequate considering the rich schema (defaults, dry_run behavior, slot ID references) and the annotation set. It could be clearer on whether valid moves are sent if any rejected ones exist, but the schema, output schema, and annotation hints fill most remaining gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is about 67%, and the description adds real meaning to the 'moves' parameter by enumerating validation rules: player must be on the roster, slot eligibility, player not locked, and lineup must respect slot counts. It also clarifies that this is a batch operation, which is not in the schema itself.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource, 'Apply a batch of lineup moves to one team,' and clearly differentiates this from sibling tools like add_free_agent, move_to_ir, or activate_from_ir. It communicates both the batch nature and the one-team scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when the user wants to set or adjust a lineup, but it does not explicitly contrast with alternatives or say what it's not for. There is no explicit 'when to use vs. not use' guidance, only indirectly derived from the operation name and wording.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

snapshotLeague SnapshotA
Read-onlyIdempotent

The league in the exact line-oriented text format used by frontoffice-manager's tools/diff-snapshot.mjs: teamId|playerId|name|injury|seasonProj roster rows, FA|...|pctOwned free-agent rows, a SETTINGS line, a WAIVERORDER line, and a PEND: line, wrapped in SNAPSTART/SNAPEND markers.

ParametersJSON Schema
NameRequiredDescriptionDefault
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false, covering safety and idempotency. The description adds valuable context about the exact output format, including the line structure and markers, which goes beyond annotations and helps the agent understand what the tool returns. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense sentence that packs all essential information: the output format, the file reference, and the components. It is concise with no filler, though it could be slightly restructured to front-load the action (e.g., 'Generates a league snapshot in...') for even quicker comprehension.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description fully specifies the output format, listing all line types and markers. All three parameters are optional with defaults, so there are no ambiguous inputs. The tool's read-only nature is covered by annotations, and the output is thoroughly described, leaving nothing an agent needs to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so each parameter (sport, season, league_id) is already documented with defaults and enums. The description adds no parameter-specific meaning beyond what the schema provides, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly specifies the resource (the league) and the output format (line-oriented text with specific rows and markers). It distinguishes this tool from siblings like get_teams or get_league, which return structured data, by emphasizing the exact text format used for diffing. The title 'League Snapshot' reinforces the purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for diffing via the reference to 'frontoffice-manager's tools/diff-snapshot.mjs', but it does not explicitly state when to use this tool instead of alternatives like get_league or get_rosters. It lacks explicit exclusions or conditions, leaving the decision to the agent's inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

waiver_claimWaiver ClaimB

Submit a waiver claim, optionally with a conditional drop. bid is only used in FAAB leagues (see get_league's acquisitionSettings.acquisitionType); leave it unset in priority-waiver leagues.

ParametersJSON Schema
NameRequiredDescriptionDefault
bidNo
sportNoffl (football), fba (basketball), or flb (baseball). Defaults to ESPN_SPORT.ffl
seasonNoSeason year. Defaults to ESPN_SEASON.
dry_runNoDefault true: validates and reports what would be sent without sending it. Set false to actually execute (still a no-op if WRITES_ENABLED=false in .env).
team_idNo
league_idNoESPN league id. Defaults to ESPN_LEAGUE_ID.123456
add_player_idYes
drop_player_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
sentNo
dryRunYes
responseNo
wouldSendNo
verificationNo
blockedReasonNo

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=false, so the write nature is known. The description adds only that it's a waiver claim with optional drop, but doesn't disclose side effects like pending status, processing time, or failure conditions. With openWorldHint=true, more behavioral context is expected but missing. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with zero redundancy. The core purpose is front-loaded, and the bid clarification is placed after. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a claim tool with 8 parameters, the description covers the essential action but misses sibling differentiation (e.g., when to prefer add_free_agent) and doesn't mention that claims are processed asynchronously. Output schema exists, so return values are covered, but the context around claim lifecycle is incomplete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 50%, and the description compensates partially: it explains bid's league-type dependency and hints at the conditional drop. However, add_player_id, drop_player_id, and team_id are left undocumented in both schema and description, leaving gaps for a new agent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb and resource: 'Submit a waiver claim, optionally with a conditional drop.' This is specific and distinguishable from general roster actions. However, it doesn't explicitly contrast with sibling tools like add_free_agent, so it doesn't fully differentiate in purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives such as add_free_agent or cancel_claim. It does offer a parameter-specific tip about bid usage in FAAB vs priority-waiver leagues, which is helpful for invoking correctly, but not for choosing the tool. No when-not-to-use or alternative references.

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.

  1. 17 tool updatesv0.1.0
    • First observedactivate_from_ir
    • First observedadd_free_agent
    • First observedcancel_claim
    • First observedget_boxscore
    • First observedget_free_agents
    • First observedget_league
    • First observedget_matchups
    • First observedget_pending
    • First observedget_player
    • First observedget_rosters
    • First observedget_teams
    • First observedget_transactions
    • First observedmove_to_ir
    • First observedoptimal_lineup
    • First observedset_lineup
    • First observedsnapshot
    • First observedwaiver_claim

TDQS

A3.9/5.0

Scored across 17 tools

Disambiguation5/5

Each tool targets a distinct resource or action: rosters vs. teams vs. player lookup, free-agent adds vs. waiver claims, and IR moves are clearly separated. The only near pair is add_free_agent vs. waiver_claim, but their descriptions explicitly distinguish unclaimed free agents from waiver-wire players.

Naming Consistency4/5

Read operations consistently use get_* (get_teams, get_league, get_rosters, etc.), and mutations use action_noun patterns like set_lineup, add_free_agent, cancel_claim, and move_to_ir. Two outliers, snapshot and optimal_lineup, break the verb-first pattern, but they are still recognizable and not confusing.

Tool Count4/5

Seventeen tools is slightly above the typical well-scoped range, but the count is justified by the variety of fantasy-football operations: league info, roster management, waivers, transactions, matchups, and IR handling. Each tool covers a meaningful need with little redundancy.

Completeness4/5

The surface covers the full roster-management lifecycle: viewing teams/rosters, adding/dropping players, submitting/canceling claims, setting lineups, and handling IR. The main gap is trade management, which is explicitly read-only via get_pending, so agents cannot propose or execute trades; otherwise the domain is well covered.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Connect ESPN & Yahoo fantasy leagues to AI assistants via MCP. Read-only tools for rosters, standings, matchups, free agents, and league info across football and baseball.
    19
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI models to manage and query fantasy sports leagues through the Sleeper API, supporting tasks like player lookups, league activity, and draft management.
    72 npm
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Autonomous ESPN Fantasy Baseball manager that optimizes lineups, handles waivers, and proposes trades using live stats.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables reading and scoring Fleaflicker fantasy football leagues, including rosters, standings, matchups, boxscores, draft boards, and stat line scoring using league-specific rules, with no authentication required.
    MIT