Skip to main content
Glama
MoayadAbbara

FPL MCP

by MoayadAbbara
README.md
# FPL MCP

**Manage your Fantasy Premier League team with AI.** An [MCP](https://modelcontextprotocol.io/)
server that lets an LLM client like Claude read your FPL team, analyse players and fixtures,
suggest transfers, spy on your mini-league rivals, and actually make transfers, set your
captain, and play chips — all from plain-language chat.

> ⚠️ **Unofficial.** Not affiliated with, endorsed by, or connected to the Premier League.
> Uses the public FPL API. Runs entirely on **your own machine** — your session token never
> leaves your computer, and your password is never seen by this tool or the model.

---

## Demo

One sentence, multiple moves — a transfer, a captaincy change, and a line-up swap,
all executed on the real team:

> *"Transfer out João Pedro, bring in Havertz, make Haaland captain, and bring
> Yates into the starting eleven for Le Fée"*

![FPL MCP demo — managing a team from chat](docs/demo.gif)

---

## What makes it different

Most FPL tools only *read* data and give advice you then apply by hand. This one:

- **Actually manages your team** — transfers, captaincy, line-up, and chips, executed for real.
- **Signs you in without ever touching your password** — a real browser opens, you log in on
  the official FPL page, and only the session token is captured.
- **Spies on your mini-league** — rivals' squads are public, so it computes ownership *within
  your league* and tells you your edge and the threats.
- **Suggests transfers with a position-aware model** — three strategies: best points, safe
  template picks, or differentials to climb the rank.

## Tools

| Category | Tools |
|---|---|
| **Auth** | `login_to_fpl` |
| **Your team** | `get_my_team` |
| **Data** | `get_gameweek_status`, `search_players`, `compare_players`, `get_player`, `get_fixtures`, `blank_double_gameweeks`, `get_league_standings`, `transfer_history`, `team_news` |
| **Analysis** | `suggest_transfers`, `analyze_mini_league` |
| **Manage** | `make_transfer`, `transfer_preview`, `set_captain`, `substitute`, `play_chip` |

## How sign-in works (and why it's safe)

FPL migrated to a token-based login (PingOne OIDC). Instead of asking for your password,
`login_to_fpl`:

1. Opens a **real browser window** on the official FPL site.
2. **You** sign in there yourself.
3. The session token is read from the network traffic and stored locally in `token.txt`.

Your password is typed only into FPL's own page — it never reaches this code or the model.
No bot-detection is bypassed; a human logs in. See [docs/FINDINGS.md](docs/FINDINGS.md) for
the full technical write-up.

## Requirements

- Python 3.12+
- [uv](https://docs.astral.sh/uv/)
- Node.js (only if you use the MCP Inspector for development)

## Setup

```bash
git clone https://github.com/MoayadAbbara/FPL-MCP.git
cd FPL-MCP
uv sync --extra browser      # includes Playwright for browser login
uv run playwright install chromium
```

### Connect it to Claude

Register the server with your MCP client. For Claude Code:

```bash
claude mcp add fpl -- uv run --directory /path/to/FPL-MCP python src/server.py
```

Or add it to your client's MCP config (`.mcp.json` / `claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "fpl": {
      "command": "uv",
      "args": ["run", "python", "src/server.py"],
      "cwd": "/path/to/FPL-MCP"
    }
  }
}
```

Restart the client, then just talk to it.

## Usage

Once connected, use natural language:

```
"Sign in to FPL"
"Show my team"
"Any injury news on Arsenal players?"
"Compare Haaland and Gyökeres"
"Suggest transfers — differential mode"
"Analyse my mini-league 123456"
"Transfer out Haaland, bring in João Pedro, and make Watkins captain"
```

The model calls the right tools and, for anything that changes your team, tells you what it did.

## Architecture

Layered — each layer only knows the one below it:

```
src/
  tools/    MCP tool surface (thin glue: fetch -> domain -> format -> text)
  format/   raw data -> compact, model-friendly text
  domain/   pure FPL logic (scoring, suggestions, roster maths) — no HTTP, no MCP
  api/      FPL HTTP client
  auth/     token capture (browser) and storage
  server.py entry point
```

Raw FPL JSON never reaches the model; everything passes through `domain/` then `format/` so
only decision-relevant fields remain.

## Development

```bash
uv run ruff format . && uv run ruff check --fix .   # format + lint
uv run python src/server.py                          # run the server (stdio)
```

## Notes

- The season-dependent tools (`suggest_transfers`, `analyze_mini_league`) work best once the
  season has started; before the first deadline they return a clear "not yet" message.
- Automating team management may bump against the FPL Terms of Service. Use it for your own
  team, keep it personal, and stop if asked to.

## License

[MIT](LICENSE)

TDQS

A3.5/5.0

Scored across 18 tools

Disambiguation4/5

Most tools target a distinct action and resource: search, compare, get profile, fixtures, transfers, chips, and squad moves are well separated. The main potential confusion is between get_league_standings and analyze_mini_league, which both deal with mini-league data, though their descriptions indicate different scopes.

Naming Consistency3/5

There is a clear majority pattern of imperative get_/set_/make_/play_ verbs, but several names are noun phrases instead, such as team_news, transfer_history, transfer_preview, and blank_double_gameweeks. The convention is consistent enough to be readable, but it is not uniformly verb_noun.

Tool Count4/5

18 tools is on the heavier end, but the FPL domain is broad and each tool serves a distinct part of the workflow: login, squad, players, fixtures, news, transfers, chips, and leagues. A few could arguably be folded together, but the count feels justified rather than bloated.

Completeness5/5

The tool surface covers the core FPL lifecycle: authentication, team viewing, player research, fixture difficulty, injuries, league standings, mini-league analysis, transfer history/suggestions/preview/execution, captain selection, substitutions, and chips. There are no obvious dead ends or missing domain-critical operations.

Maintenance

ActivityMaintained
ResponsivenessNo issues