FSPN

Connect Claude to FSPN (MCP)

FSPN's analytics are available as tools inside Claude through a hosted MCP server: ask Claude about your week, your matchup, a trade, the waiver wire or a player, and it calls the same engines the app runs on, scoped to your league. Everything the app can work out, Claude can work out with you, in your own words. This page is the step-by-step; the wire-level detail (rate limits, error codes, the JSON API alongside it) is in the API reference, and the rest of the app is in the user guide.

What you need

Tokens and connected apps never reach the Account, billing or Ops pages, so a leaked token cannot change your plan or mint more tokens — but it can read your league, so treat it like a password and revoke it from the same card if it gets out.

Claude Desktop and the connector directories (OAuth)

This is the path with nothing to paste. It works in Claude Desktop's Add custom connector dialog, in the Claude web app's connector settings, from the Claude and OpenAI connector directories once FSPN is listed there, and in any MCP client that supports OAuth.

  1. Add a connector with the URL https://fspn.ragealley.com/mcp (in Claude Desktop: Settings → Connectors → Add custom connector, name it FSPN). No header, no token.
  2. The client discovers FSPN's authorization server by itself and opens a browser window on FSPN. Sign in if you are not already — the page brings you straight back afterwards.
  3. The consent page names the app (Claude Desktop, ChatGPT, …) and what it may do: read your leagues, teams, projections and the player data; never change your roster, run console commands, see billing or manage tokens. Press Approve (or Deny — the app is told and nothing is stored).
  4. Back in the client, the connector is connected; ask something that needs your league.

The app receives an access token that lives an hour and a refresh token that renews it for up to 30 days of inactivity, silently. Approving the same app again replaces its earlier connection; you can hold up to ten connected apps. Disconnect from Account → API & MCP — the row is labelled connected app and Revoke cuts it off at once; the client will ask you to connect again next time. If you see Sync + API needed instead of the consent page, the account approving has no plan that includes the API — get it on the Account page and connect again. A connected app is read-only by design; if you want Claude to change rosters or run jobs, use a read_write personal token in Claude Code instead (a write scope for connected apps is not offered yet).

Claude Code

  1. Register the server with the current CLI syntax for streamable HTTP with a header — keep it exactly, replacing sa_… with your token:
claude mcp add --transport http fspn https://fspn.ragealley.com/mcp --header "Authorization: Bearer sa_…"
  1. Start (or restart) Claude Code and run /mcp. fspn should be listed as connected, with its tools.
  2. Ask something that needs your league:
What's my win probability this week, and is there a bench swap that improves it?

Claude calls get_my_week (and simulate_matchup if it wants the distribution) and answers from your league's own numbers. A token is scoped to your first league unless you say otherwise; to point it at another of your leagues, register the URL with ?league=<league_id> on the end (GET /api/me with the same header lists your leagues and their ids).

Claude Desktop with a personal token (the bridge)

The connector dialog above is the way to go on Desktop. If you would rather use a personal token there — for a read_write scope, or on a machine where the browser sign-in is awkward — the connector goes through the mcp-remote bridge, a small stdio-to-HTTP relay that runs on your machine and adds the header for you. It needs Node.js (for npx).

  1. Open the config file: Settings → Developer → Edit Config (it opens claude_desktop_config.json).
  2. Add the server (merge with any mcpServers you already have):
{
  "mcpServers": {
    "fspn": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://fspn.ragealley.com/mcp",
               "--header", "Authorization: Bearer sa_…"]
    }
  }
}
  1. Save and fully quit and reopen Claude Desktop. The tools appear under the connector list in a new chat.

Your token sits in that file in plain text. Keep the file private (it lives in your user profile, not in any synced folder), and revoke the token if you ever share the machine.

Other MCP clients

Any client that speaks MCP over streamable HTTP works the same way:

By hand, this lists the tools:

curl -X POST https://fspn.ragealley.com/mcp \
  -H "Authorization: Bearer sa_…" -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

The tools

These are the 36 tools tools/list returns — the same set the local stdio server exposes, so anything written against one works against the other. Weeks and seasons are the NFL's; when a tool takes season and week, give the ones you are asking about.

My team and my league

Everything here reads the league the token is scoped to (your Sleeper or ESPN league as last synced).

Players and projections

The shared NFL data the Tuesday job publishes, priced with your league's scoring.

Games, series and ratings

The Elo models for NFL, NBA, MLB and soccer.

Model accuracy and data quality

Play

The daily games, same puzzle for the whole league.

The console (read_write only)

Limits and safety

Troubleshooting

You seeIt meansDo this
401 with error -32001 (and a WWW-Authenticate: Bearer header)No token was sent, or the token is mistyped or revoked: That API token isn't valid — it may have been revoked.Check the header is exactly Authorization: Bearer sa_…; if in doubt, create a new token and revoke the old one.
403 with error -32003: The API needs the Sync + API plan.The token is real but the plan has lapsed (or the account never had it).Account → Plan & billing → Get Sync + API. Tokens survive and resume as soon as the plan is active.
A tool result with isError: true saying This token is read-only — create one with the read_write scope to make changes.You called run_command (a write) with a read token. The call itself was accepted (HTTP 200); the tool refused.Create a read_write token if you really want Claude changing rosters or running jobs.
429 with error -32029More than 120 calls in the last minute from this token.Wait for Retry-After (60 seconds). Split heavy scripting across tokens if you must.
400 with error -32700The body was not JSON.Send Content-Type: application/json and a JSON-RPC 2.0 object.
405 on GET /mcpThe endpoint is POST-only; there is no server-to-client stream.Point the client at the URL as a streamable-HTTP server, not an SSE one.
413The request body was over 256 KiB.Trim the arguments.
Error -32601 Unknown methodThe method is not one of initialize, tools/list, tools/call, ping.Resources, prompts and sampling are not offered.
The tools answer but the numbers are staleThe league is read as last synced.Sync now on the Account page (Sync plan, once every five minutes per league), or wait for the Tuesday / Thursday / Sunday run.
Claude Desktop shows nothing after editing the configThe JSON did not parse, npx is not on the path, or Desktop was not fully quit.Validate the file, install Node.js, then quit Desktop from the menu bar / tray and reopen it.
The connector's sign-in shows Sync + API neededThe account you signed in with has no plan that includes the API.Account → Plan & billing → Get Sync + API (or sign in with the account that has it), then connect again.
That connection can't startUnknown client_id or redirect_uri doesn't matchThe client's registration expired or was made against another server (a stale cache after a reinstall, or a self-hosted copy).Remove the connector in the client and add it again; it re-registers.
The connector worked, then asks you to connect againThe refresh token expired (30 days unused), you revoked the app on the Account page, or a refresh token was replayed and the connection was revoked for safety.Approve again — a fresh connection replaces the old one.
The consent page's Approve goes nowhereThe browser blocked the redirect back to the app (a strict extension) or the app's callback window closed.Retry from the client; the code is good for ten minutes and is single-use.