Skip to main content
Glama
dwooods

fantasypros-mcp

by dwooods

fantasypros-mcp

A remote MCP server on Cloudflare Workers that wraps the FantasyPros v2 API (injury news, player lookup, consensus rankings, projections) so an MCP client (Claude, etc.) can call it as proper tools instead of you running PowerShell one-offs.

Your FantasyPros API key lives only as a Cloudflare Worker secret — it never appears in chat, source control, or client config again.

Tools this exposes

  • get_injury_news — latest injury newswire, optionally filtered to one player

  • get_player_news — any-category news for one player by fpid

  • get_player — look up a player's name/team/position by fpid

  • get_consensus_rankings — expert consensus rankings by position/week (also the most reliable way to find a player's fpid — the full /players list is truncated on the free tier, rankings lists aren't)

  • get_projections — weekly or season-long fantasy point projections

Related MCP server: sleeper-caffeine MCP

How it works

sequenceDiagram
    participant C as Claude (MCP client)
    participant W as Worker (fantasypros-mcp)
    participant KV as Workers KV (FP_CACHE)
    participant FP as FantasyPros API

    C->>W: tool call over /mcp<br/>header x-api-key: MCP_AUTH_TOKEN
    alt key doesn't match MCP_AUTH_TOKEN
        W-->>C: 401 Unauthorized
    else key valid
        W->>KV: get(cacheKey)
        alt cache HIT
            KV-->>W: cached JSON
        else cache MISS
            W->>FP: GET /public/v2/...<br/>header x-api-key: FANTASYPROS_API_KEY
            FP-->>W: JSON
            W->>KV: put(cacheKey, JSON, ttl)
        end
        W-->>C: tool result
    end

Two different x-api-key headers are in play here and it's easy to conflate them: the inbound one (Claude → Worker) is checked against MCP_AUTH_TOKEN and just gates the Worker so it isn't an open proxy; the outbound one (Worker → FantasyPros) is your actual FANTASYPROS_API_KEY and is what FantasyPros bills against. The KV cache sits in between so a cache HIT never touches FantasyPros (and doesn't count against your 50-requests/day free-tier quota) — only a MISS does.

1. Prerequisites

2. Install

npm install
npx wrangler login

wrangler login opens your browser and asks you to approve access to your Cloudflare account (an OAuth consent screen) — log in there if you aren't already, click Allow, and come back to the terminal. This is a one-time step per machine; Wrangler caches the token afterward.

If this is a brand-new Cloudflare account with no Workers deployed yet, visit the Workers & Pages section of the dashboard (https://dash.cloudflare.comWorkers & Pages) once before continuing. Loading that page the first time is what provisions your account's workers.dev subdomain (e.g. yourname.workers.dev), which wrangler deploy needs in step 5. Skipping this isn't fatal — Wrangler will usually prompt you to pick a subdomain interactively during deploy instead — but on some account states it fails outright with You need a workers.dev subdomain in order to proceed and no direct link to fix it, so it's faster to just visit the dashboard once up front.

3. Set secrets

Two secrets — never put these in wrangler.jsonc or commit them anywhere:

npx wrangler secret put FANTASYPROS_API_KEY
# paste your FantasyPros key when prompted

npx wrangler secret put MCP_AUTH_TOKEN
# paste a random token you generate yourself, e.g.:
#   openssl rand -hex 32
# this locks the Worker down so it isn't an open proxy for your
# FantasyPros key (and your 50 req/day free-tier budget) to anyone
# who finds the URL

4. Create the KV cache

Tool responses are cached in Workers KV so repeated questions in a chat (or across a few chats the same day) don't burn through the FantasyPros free tier's 50 requests/day. Create the namespace and wire it into wrangler.jsonc:

npx wrangler kv namespace create FP_CACHE

This prints something like:

[[kv_namespaces]]
binding = "FP_CACHE"
id = "abcd1234..."

Copy that id into the kv_namespaces entry already stubbed out in wrangler.jsonc (replacing REPLACE_WITH_KV_NAMESPACE_ID).

Cache TTLs are set per endpoint in CACHE_TTL_SECONDS in src/index.ts — 2 minutes for news (it moves fast), 15 minutes for rankings/projections, an hour for player lookups. Adjust there if you want fresher or longer-lived data. The KV free tier (100k reads/day, 1k writes/day, 1 GB storage) is far more than this project will ever need.

5. Deploy

npx wrangler deploy

This prints your Worker's URL, something like: https://fantasypros-mcp.<your-subdomain>.workers.dev

If you skipped the dashboard visit in step 2 and this is your first Worker ever, Wrangler may prompt you here to choose a workers.dev subdomain — or, on some accounts, fail with You need a workers.dev subdomain in order to proceed. If you hit that error, go to dash.cloudflare.com → Workers & Pages, let the page load once (this provisions the subdomain), then re-run npx wrangler deploy.

npx wrangler dev

Then, in another terminal, point the official MCP inspector at it:

npx @modelcontextprotocol/inspector

Connect to http://localhost:8787/sse, adding an x-api-key: <your MCP_AUTH_TOKEN> header in the inspector's connection settings (just the raw token value, no "Bearer" prefix). You should see the five tools listed and be able to call them.

7. Connect it to Claude

Add it as a custom MCP connector, pointing at:

https://fantasypros-mcp.<your-subdomain>.workers.dev/mcp

(This is the Streamable HTTP endpoint, and the one actually used to build and test this project. The Worker also serves /sse for clients that only speak the older SSE transport, but /mcp is the one to reach for by default.)

You'll need to attach x-api-key: <your MCP_AUTH_TOKEN> (just the raw token value, no "Bearer" prefix) as a custom header on the connection — not Authorization, which Claude's custom-connector UI reserves for its own OAuth flow and won't let you set as a plain header under "No sign-in" mode; that's why this Worker checks x-api-key instead. Check what the connector-setup UI you're using actually supports — some custom-connector flows only support OAuth or no auth at all, not an arbitrary custom header. If that's the case here, your options are:

  • Put the Worker behind Cloudflare Access (Zero Trust) instead of the in-code bearer check, and let Access handle auth at the edge.

  • Temporarily strip the bearer check in src/index.ts while you confirm everything else works, then re-add real auth before leaving it deployed (an unauthenticated Worker is a public proxy for your API key).

Sharing this with someone else

Two ways to let another person use it, depending on how much you want them sharing your FantasyPros quota vs. running independently:

Option A — give them the URL and the token (simplest). Anyone with https://fantasypros-mcp.<your-subdomain>.workers.dev/mcp and your MCP_AUTH_TOKEN can add it as their own custom MCP connector, same as you did in step 7. Fastest option for a handful of trusted people (family league, friends), but it's your Worker and your FantasyPros key underneath — everyone shares the same 50-requests/day budget (the KV cache helps here, since overlapping questions across people get served from cache) and anyone with the token can call it indefinitely. To cut someone off, rotate the token:

npx wrangler secret put MCP_AUTH_TOKEN

This invalidates the old value for everyone — you'd need to hand out the new one to anyone who should keep access.

Option B — give them the code, they deploy their own. Send them this repo (zip, GitHub, whatever). They run steps 1–7 themselves with their own FantasyPros API key and their own generated MCP_AUTH_TOKEN. More setup work for them, but full independence — their own quota, their own secret, nothing shared with you. Better if you're handing this to more than a few people, or to someone you don't want holding a live credential to your Worker.

For a small trusted group, Option A is the practical choice — just be aware it's a shared quota and a shared secret, not per-user access.

Notes / gotchas

  • The /public/ path segment is required. api.fantasypros.com/v2/... 404s or 403s even with a valid key — it must be api.fantasypros.com/public/v2/.... This code already has that right.

  • Free tier = 50 requests/day, truncated responses. Responses are now cached in Workers KV (see step 4) with per-endpoint TTLs, so repeated questions in a session reuse the cached copy instead of hitting FantasyPros again. Only a genuine cache miss (or an expired TTL) counts against the daily quota.

  • wrangler kv namespace create can fail with Authentication error [code: 10000] even when you're logged in and your token has the right scopes (workers_kv (write) etc.). This is a known flaky spot in Wrangler's OAuth flow, not a real permissions problem — wrangler deploy can work fine in the same session where kv namespace create errors out. Workaround: create the namespace from the Cloudflare dashboard instead (Storage & databases → KV → Create Instance), then copy the printed Namespace ID into wrangler.jsonc by hand. The ID isn't shown on the namespace's Settings tab in the current dashboard — read it out of the browser URL while viewing the namespace (.../workers/kv/namespaces/<id>/...), or from the KV list view.

  • Don't trust the KV dashboard for real-time verification. Both the Metrics tab (read/write counts) and the KV Pairs tab (live key listing) can lag or appear stale for longer than you'd expect right after a write — neither is a reliable "did my cache actually work" signal. The fpFetch helper logs [cache] HIT/MISS/WROTE <key> on every call; watch those with npx wrangler tail while triggering a tool call for ground truth on whether a request was served from cache.

  • Rotate secrets if exposed. If either secret ever leaks (posted in chat, committed by accident, etc.), reset it: npx wrangler secret put FANTASYPROS_API_KEY (or MCP_AUTH_TOKEN) to overwrite it — no redeploy needed.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides read-only access to Sleeper fantasy football leagues, enabling team snapshots, available players, matchups, trade context, and league history through standardized MCP tools.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables Claude to interact with Sleeper fantasy football leagues via MCP tools for roster, waiver, matchup, and transaction queries, plus a dashboard for daily reports, live scoring, and game-day alerts.
    72 npm
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides read-only access to Sleeper fantasy football data including user info, leagues, rosters, matchups, and NFL state through MCP tools.
    72 npm
    MIT