Skip to main content
Glama
jasonquinn77

yahoo-fantasy-mcp

by jasonquinn77

yahoo-fantasy-mcp

Local stdio MCP server for the Example League Yahoo league. It answers three questions against the live league:

  • who has a positional hole I can exploit

  • what trade would actually get accepted

  • which free agents matter this week

Built for a single private league. The design notes that drove it — why there is no roster cache, why two valuation sources, why no ML — are summarised in the comments at the top of each module.

Status

Built and tested against fixtures. Not yet connected to Yahoo — API access is a reviewed application (runbook §6) and has not been submitted. Every piece that does not need credentials is working and covered by tests.

Related MCP server: Yahoo Fantasy MCP

Layout

server.py                  7 MCP tools, stdio transport
yahoo_fantasy_mcp/
  auth.py                  OAuth 2.0 consent + transparent refresh
  yahoo_client.py          GET -> normalized JSON, refresh-on-401, retry once
  normalize.py             collapses Yahoo's fragmented JSON
  parsing.py               payloads -> domain objects; refuses to guess scoring
  league.py                league-key discovery, settings, rosters, free agents
  scoring.py               replacement level, surplus/deficit, lineup points
  trades.py                partner matching + package construction
  waivers.py               free agents ranked by value to THIS roster
  matching.py              Yahoo <-> FantasyCalc name matching
  fantasycalc.py           market values (no auth)
scripts/authorize.py       one-time consent flow
scripts/healthcheck.py     credential-path probe -> fleet ledger

Setup

python3 -m venv .venv
./.venv/bin/pip install -e ".[dev]"
./.venv/bin/python -m pytest -q

Credentials go outside the repo, at ~/.config/yahoo-fantasy-mcp/.env (mode 600):

YAHOO_CLIENT_ID=...
YAHOO_CLIENT_SECRET=...
YAHOO_REDIRECT_URI=https://localhost:8000/callback
YAHOO_LEAGUE_ID=123456

Then, once:

./.venv/bin/python scripts/authorize.py

The browser will fail to load the redirect — that is expected. Paste the address-bar URL back and the token pair is written to ~/.config/yahoo-fantasy-mcp/tokens.json (mode 600). Refresh is automatic from there.

Claude Desktop registration

The server ships as a container. Desktop spawns it per conversation over stdio and it exits when the conversation ends — nothing is left running.

docker build -t yahoo-fantasy-mcp:latest .

The build runs the full test suite in an intermediate stage and the runtime stage copies its stamp file, so a failing test produces no image. Verified: breaking the replacement-level calculation fails 5 tests and the build aborts.

{
  "mcpServers": {
    "yahoo-fantasy": {
      "command": "/usr/local/bin/docker",
      "args": [
        "run", "-i", "--rm",
        "-v", "/Users/you/.config/yahoo-fantasy-mcp:/config",
        "yahoo-fantasy-mcp:latest"
      ]
    }
  }
}

Absolute path to docker included: Desktop does not inherit your shell environment, so anything resolved from PATH will not be there.

What the container does and does not buy you

It buys a reproducible runtime — dependencies fully pinned in requirements.lock, no dependence on the host's Python — and it makes the image movable to another machine.

It does not decouple the server from Desktop. Stdio is a local pipe, so the container must run on the same machine Desktop runs on. "Move it to another machine" means moving Desktop too. Running Desktop on one host and the server on another needs an HTTP transport, a tunnel and an auth layer in front of a long-lived Yahoo refresh token — that is the trade ADR-2 declines, and it is a separate decision, not a config change.

Two operational notes:

  • Docker must be running when Desktop launches the server. This is a new failure mode the venv did not have. scripts/healthcheck.py, run in the container, exercises the same path and so reports red for this too.

  • On a Linux host, add --user $(id -u):$(id -g). macOS maps bind-mount ownership automatically (verified: a non-root container writes /config fine); Linux does not.

Running without the container

pyproject.toml and the venv still work, and are the quicker loop for tests:

./.venv/bin/python -m pytest -q

uv is supported by pyproject.toml but is not used for launching: uv run re-resolves dependencies on every invocation, which is a network round-trip and a failure opportunity at kickoff, to save a pip install needed roughly twice a year for two dependencies. The container pins them properly instead.

Monitoring

scripts/healthcheck.py exercises a real token refresh and one authenticated call, then appends an event to ~/ops/events.jsonl as JSON lines. Run it on whichever machine holds the tokens:

OPS_HOST=$(hostname -s) docker compose --profile ops run --rm healthcheck

OPS_HOST is required inside a container and the probe refuses to run without it. The ledger fingerprint hashes host + service + stage + error class; a container ID changes every run, so letting one through would give every occurrence a unique fingerprint and silently destroy recurrence counting. Refusing beats poisoning the ledger with events that can never match.

The failure it exists to catch is a silently dead refresh token. The server runs only while a question is being asked, so nothing notices between conversations — silence reads as health right up until you need an answer. Error classes are bucketed (token_refresh_failed, scoring_unavailable, http_status, http_timeout, config_missing) so repeat failures are countable rather than each looking novel.

Deliberately absent

  • No fetch_url tool. The community servers all ship one; it is the largest prompt-injection surface in the design.

  • No writes. Read-only by design, and Yahoo currently offers read access only. Every action stays a human decision.

  • No database, scheduler or ML. See ADR-1 and ADR-4.

  • No long-running container. The image exists for reproducibility, not to keep a process alive. There is no docker compose up for the server.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude to interact with Yahoo Fantasy Baseball and Basketball leagues, allowing roster analysis, matchup tracking, free agent browsing, and player stats retrieval via natural language.
    1
    -
  • F
    license
    A
    quality
    C
    maintenance
    Enables natural language interaction with Sleeper Fantasy Football API data, allowing queries about leagues, players, matchups, draft results, and trade analysis.
    13
    19
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Manages Yahoo Fantasy Baseball teams via AI, allowing natural language queries for roster updates, trade analysis, waiver wire, and league insights.
    4
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jasonquinn77/yahoo-fantasy-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server