Flaim - Fantasy Sports AI Connector

by jdguggs10

384 downloads
Not rated
GitHub

About

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. Works with Claude, ChatGPT, and Gemini.

Details

Author
jdguggs10
Downloads
384
Categories
AI

- Chrome extension for automatic ESPN credential capture
- Auto-discovery of leagues and past seasons
- Direct MCP protocol access with OAuth 2.1
- Live ESPN data via a dedicated client worker
- Multi-league and multi-season support

Setting up with Highlight

This MCP is not yet compatible with Highlight’s one-click setup. However, you can still use it with Highlight by following these steps:

  1. Download and install Highlight from highlightai.com/download
  2. Navigate to the plugins tab and select "Add Custom Plugin"
  3. Configure the plugin with the settings below
    Plugin Name Flaim - Fantasy Sports AI Connector
    Command (node, npx, python, etc.)

    Please refer to the README for specific instructions on how to obtain API keys or other required environment variables.

  4. Enable "Start Automatically" if you want the plugin to start when Highlight launches

From the repository

Create a Clerk account, sync your ESPN credentials via the Chrome extension or manually on the Flaim website, then let Flaim auto-discover your leagues and past seasons. Select a default league, add Flaim as a custom MCP connector in your AI using the URL https://api.flaim.app/mcp, and start asking questions about your fantasy data.

get_user_session

Use this alone for user-specific connection, league, or account-status questions, and use it as the first data tool when a request needs the user's connected fantasy league data. Do not call for Flaim capability, permission, or generic setup how-to questions, and do not call for generic coding, scraping, weather, travel, betting, sports news, or other requests that do not need connected league data. For a normal selected-league request, call this once before any other data tool. For an explicit refresh request, call refresh_leagues first and then call this tool after success; call it again even if it ran earlier in the chat. Returns the user's full league landscape: allLeagues (all active leagues), defaultLeagues (per-sport defaults), and defaultLeague (populated only when a single league exists or defaultSport matches). For vague singular prompts, use defaultLeague when present; otherwise use the relevant sport entry in defaultLeagues. For explicit plural or comparative prompts (each, all, compare, across leagues/platforms), enumerate every matching league in allLeagues and call the target tool once per league. For a selected active league, call get_league_info next before the requested league-specific data tool. Skip get_league_info only when answering from session data alone or branching to get_ancient_history. season_year always represents the start year of the season. Read-only.

refresh_leagues

Refresh connected fantasy leagues by asking Flaim to rediscover leagues through connected ESPN, Yahoo, and Sleeper accounts. Use only when the user explicitly asks to refresh or after the user presses the widget refresh button. This is non-destructive, but repeated refreshes can update Flaim registry timestamps and provider metadata; it does not change provider lineups or rosters, add or drop players, submit waiver claims or trades, or modify league settings. If this call succeeds, call get_user_session again to show the updated league list. If it fails, follow the error retry guidance and any retry_after value; do not retry in a loop.

get_ancient_history

Use this only after get_user_session, and only when the user is clearly asking about a non-current season or an inactive league. This is the historical branch: it returns past seasons and historical leagues outside the current season view. Use for last season, older seasons, inactive leagues, or historical performance. Read-only.

get_league_info

For a selected active league, call this immediately after get_user_session and before the requested standings, matchup, roster, free-agent, player, or transaction tool. Skip it only when answering from session data alone or branching to get_ancient_history. This provides the baseline league context for analysis: league name, settings, scoring type, roster configuration, and team/owner context, plus schedule or season-window metadata when the platform provides it. When fanning out across multiple leagues, call this once per league. The exact team fields vary by platform but all include ownerName. Use values from get_user_session. Read-only. Current date is 2026-08-20.

get_standings

Get season standings and outcome snapshot; includes verified season-outcome fields when available. Returns team records, rankings, and points summaries. The rank field is a standings sort position (1 = best): on ESPN and Sleeper it is computed by Flaim from win percentage; on Yahoo it is passed through from Yahoo's own standings API. It is NOT a verified postseason finish. For verified postseason outcome, use finalRank and championshipWon instead. Also returns seasonPhase (regular_season/playoffs_in_progress/season_complete), seasonComplete, and per-team outcome fields: finalRank, championshipWon, playoffOutcome, outcomeConfidence, madePlayoffs, playoffSeed. Outcome fields are null when not verifiable — do not infer championship from rank or team name. outcomeConfidence is 'explicit' when the platform reports final ranks, or 'derived' when the champion and runner-up were determined from the final winners-bracket matchup (ESPN historical seasons may omit final ranks); a tied championship game is resolved using the league's playoff tie rule (ESPN's default advances the higher seed). Note: playoffOutcome returns 'in_progress' on Sleeper for teams in active playoffs; ESPN and Yahoo return null for that state. ESPN may also include projected-rank fields. Best used after get_user_session and after get_league_info for the specified league so team names and league context are already established. For multi-league comparisons, call once per league. For historical finish questions, call get_ancient_history first to discover seasons, then call this tool per season for verified outcomes. Read-only. Current date is 2026-08-20.

get_matchups

Get matchups/scoreboard for a specific week or the current week. Best used after get_user_session and after get_league_info for the specified league so the model already knows the league's team names, owner/team mapping, and league context before interpreting the matchup. For multi-league comparisons, call once per league. Read-only. Current date is 2026-08-20.

get_roster

Get roster details for a specific team — current by default, historical on request. Exact payload varies by platform: ESPN and Yahoo return player entries with lineup/position context, while Sleeper returns starters, bench, reserve, taxi, and record metadata for the selected roster. Historical snapshots: pass week for football (all platforms) and Sleeper basketball (matchup week), or as_of_date (YYYY-MM-DD) for ESPN/Yahoo baseball, basketball, and hockey — never both; an invalid selector returns a corrective error naming the right one. Every response includes a snapshot block identifying what was returned (current vs week vs date); historical responses may add limitation flags (acquisitionMetadataAvailable, reserveAndTaxiClassificationAvailable) when provider history omits those details. For "roster during matchup week N" questions in daily sports, ask the user for a specific date rather than guessing — one matchup spans several daily rosters. Best used after get_user_session and after get_league_info for the specified league so the model already knows the league's team names, owner/team mapping, league settings, and roster context before interpreting this roster. Requires authentication except on Sleeper's public API. Read-only. Current date is 2026-08-20.

get_free_agents

Get players available to acquire in the specified fantasy league, optionally filtered by position. This is fantasy-league availability, not professional-contract status. Pass a requested count exactly from 1 through 100; for more than 100, state the limit and ask the user to narrow the request or accept 100. Prefer the canonical fields: every response carries leagueId, seasonYear, position, count, ordering, capabilities, and ownershipScope; entries carry team (real-life club, null when none) and id (platform player id as a string, when supplied) on every platform, and ESPN entries add acquisitionState ("free_agent", "waivers", or null when the platform cannot determine the subtype) plus waiverClearsAt (ISO time); legacy platform fields remain alongside for compatibility and should not be re-explained. ownershipScope "platform_global" means percentOwned/percentStarted cover all leagues on that platform — never ownership within the selected league. An ESPN-wide started rate is never conditional on the player being rostered. Label every reported percentage as an ESPN-wide roster/start rate or Yahoo-wide market rate. Translate ownership scope silently into that provider-wide wording; never print the ownershipScope key, platform_global enum, or get_free_agents tool name. If capabilities marks rates unavailable, write "[Provider] market ownership rate: not provided"; do not print a missing response field name or null value, call get_players, or offer a lookup. When acquisitionState is null or not present, call rows "available players," never specifically free agents or waivers, and do not promise an immediate add. A returned player is already confirmed available in that league. Use get_roster only when the current request separately asks who owns a player; never offer it after an available-player result. Do not include injuryStatus or any injury detail unless the user asks for it; when asked, verify current web evidence and translate provider codes into plain language. State acquisition status in plain language from acquisitionState ("a free agent", "on waivers"); never print raw codes — neither provider codes such as FREEAGENT or WAIVERS nor canonical values like free_agent verbatim. Use current web evidence before adding analysis or pickup recommendations. Follow get_user_session then get_league_info for the selected league; fan out once per league for comparisons. Requires authentication on ESPN/Yahoo; Sleeper uses the public API. Read-only. Current date is 2026-08-20. Hard stop: after satisfying a returned-list or field-explanation request, end the answer immediately after the requested facts. Remove every closing question or offer to do more work, including roster checks, lineup-fit checks, comparisons, rankings, recommendations, role or health analysis, trends, or outlooks; never append "if you want", "tell me which player", or a similar invitation unless the user's current request explicitly asks for that additional work.

get_players

Search for player identity by name. Always returns identity fields, but ownership context varies by platform. ESPN and Yahoo return market/global ownership and can also populate league ownership fields when credentials and league context are available. Sleeper returns identity plus ownership_scope="unavailable" with market_percent_owned=null. For a selected active league, call this after get_user_session and get_league_info so league-specific ownership and team names can be resolved. League ownership fields: league_status ("ROSTERED" = on a team, "FREE_AGENT" = available, null = unavailable), league_team_name (fantasy team name if rostered), league_owner_name (team owner if rostered). When those league fields are absent, null, or unavailable, fall back to get_roster to verify manually. Use values from get_user_session. Read-only. Current date is 2026-08-20.

get_transactions

Get recent league transactions including adds, drops, waivers, and completed trades. Best used after get_user_session and usually after get_league_info so the model already knows the league's team names and owner/team mapping before summarizing activity. Each normalized transaction includes a date field (YYYY-MM-DD), type, status, week, and optional team_ids. When presenting results, organize by time period (today, yesterday, this week, older) AND by team within each period so the user can see both when moves happened and what each team did. Week handling is platform-specific: ESPN week always means matchup period, including daily sports where one matchup spans several provider scoring periods; week 0 is ESPN preseason, and omitting week selects the current and previous matchup periods. Sleeper accepts positive matchup weeks starting at 1; omit week for its current and previous week. Yahoo uses a recent 14-day timestamp window and ignores explicit week. ESPN serves rows from its structured transaction source (source mTransactions2) with FAAB bid amounts, directional trade_sides, and full trade-lifecycle and failed-bid coverage; trades missing directional detail are filled from the activity feed (source mTransactions2_with_activity_trade_details). If the structured source is unavailable, ESPN falls back to its completed-activity feed (source activity_feed) where failed-bid and trade-lifecycle filters are unavailable. Inspect source/limitations/window metadata before claiming completeness. ESPN responses include a teams map (team ID to display name) to resolve numeric team_ids. Yahoo and Sleeper generally rely on get_league_info for team-name resolution. Use values from get_user_session. Read-only. Current date is 2026-08-20.

Claude Desktop / Cursor

Paste into your MCP client config file to install this server.

{
    "mcpServers": {
        "flaim - fantasy sports ai connector": {
            "flaim": {
                "url": "https://api.flaim.app/mcp"
            }
        }
    }
}

McpServers

{
    "flaim": {
        "url": "https://api.flaim.app/mcp"
    }
}

Flaim - Fantasy League AI Connector

Doc routing: see docs/INDEX.md.

Flaim connects your ESPN fantasy leagues to AI assistants like Claude, ChatGPT, and Gemini CLI. It's an MCP (Model Context Protocol) service that gives AI tools access to your live fantasy data.

How It Works

1. Create a Clerk account & sign in — This is where your ESPN credentials and league info are stored
2. Sync ESPN credentials — Install the Chrome extension to sync automatically, or enter them manually
3. Leagues auto-discovered — Extension finds all your leagues + past seasons and saves them
4. Pick a default — Select which league to use by default in AI conversations
5. Connect your AI — Add Flaim as a custom MCP connector in Claude, ChatGPT, or Gemini CLI using the MCP URL
6. Use MCP tools — Ask about your roster, matchups, standings, etc. directly in your AI

Bring your own LLM subscription. Flaim provides the data bridge.

Automation vs Manual (Quick Clarification)

- Extension (automatic): Auto-pulls ESPN s2/swid and saves to supabase. Runs only when the user clicks Sync / Re-sync. It discovers leagues + past seasons and can set a default.
- Site (manual): /leagues is independent. Users can add leagues by ID and manually trigger season discovery.

What Flaim Is

Flaim is an authentication and data service for fantasy sports AI integrations:

- MCP Server: Exposes fantasy league data to Claude and ChatGPT via the Model Context Protocol
- OAuth Provider: Handles secure authentication between AI clients and your ESPN data
- Credential Manager: Securely stores and manages ESPN session cookies

Flaim is not a chatbot or AI product itself — it's the bridge that lets you use your preferred AI tool with your fantasy data.

Features

- Chrome Extension (v1.5.0): Auto-capture ESPN credentials without manual cookie extraction
- Auto-Discovery (v1.2.1+): Fan API-based discovery of leagues + past seasons, with granular status messaging and default selection
- Claude + ChatGPT + Gemini CLI: Direct access via MCP protocol (OAuth 2.1)
- Live ESPN Data: espn-client worker with real-time stats
- Multi-League + Multi-Season Support: Store multiple seasons per league and discover past seasons

About

Flaim is a solo indie project — built with care, maintained for the long term. The focus is on reliability, security, and doing one thing well. No VC funding, no growth pressure, just a useful tool for fantasy sports fans who use AI.

Season Years

Season year defaults are deterministic and use America/New_York time:

- Baseball (flb): Defaults to the previous year until Feb 1, then switches to the current year
- Football (ffl): Defaults to the previous year until Jul 1, then switches to the current year

MCP Tools

The unified gateway (https://api.flaim.app/mcp) exposes these tools:

| Tool | Description |
|------|-------------|
| get_user_session | User's leagues across all platforms with IDs |
| get_ancient_history | Historical leagues and seasons (2+ years old) |
| get_league_info | League settings and members |
| get_roster | Team roster with player stats |
| get_matchups | Current/upcoming matchups |
| get_standings | League standings |
| get_free_agents | Available free agents |

All tools take explicit parameters: platform, sport, league_id, season_year.

Architecture

Chrome Extension → flaim.app → Auth Worker → Supabase
                      ↓
Claude/ChatGPT/Gemini CLI → Fantasy MCP Gateway → ESPN Client → ESPN API

- Chrome Extension: Captures ESPN cookies, syncs to Flaim
- Web App (Next.js): User dashboard, OAuth endpoints, league management
- Auth Worker (Cloudflare): Token validation, rate limiting, credential storage
- Fantasy MCP Gateway (Cloudflare): Unified MCP endpoint for all sports
- ESPN Client (Cloudflare): ESPN API calls (internal, called by gateway)
- Supabase: User data, OAuth tokens, ESPN credentials

---

For Contributors

Solo developer, hobby project. Keep it simple and stable.

- Small changes — 1-2 hour tasks, one new concept at a time
- Boring tech — Stick to the stack (Next.js, Vercel, Clerk, Cloudflare, Supabase)
- Official docs first — Copy from examples before inventing patterns

Documentation

| Document | Description |
|----------|-------------|
| Architecture | System design, deployment, troubleshooting |
| Current Execution State | What is done, in progress, and next |
| Changelog | Release history |
| Web App | Next.js routes, components, environment |
| Workers | Cloudflare Workers, MCP tools, ESPN API |
| Manual OAuth Runbooks | Claude, ChatGPT, and Gemini verification checklists |
| Extension | Chrome extension build, Sync Host, CWS |

Quick Start (Development)

git clone https://github.com/jdguggs10/flaim.git
cd flaim && npm install
cp web/.env.example web/.env.local  # add keys
npm run dev

---

Getting Help

This is a solo indie project with best-effort support. I'll do my best to respond, but it may take time.

- Issues: GitHub Issues
- Discussions: GitHub Discussions

License

MIT License - see LICENSE.

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.