{
  "name": "Chessfolio",
  "description": "Two capability sets over one MCP door. Personal, PAT-authenticated tools for the token owner's own chess data — stats, rating progress, games (list and single-game detail), problem opening lines, the latest weekly report and puzzles. Plus three PUBLIC, token-less tournament tools — tournament state, a Round-1 pairing estimate and a next-round Swiss pairing estimate — reading public Chess-Results data. Read-only throughout. Each tool's `auth` field says which it is.",
  "version": "1.1.0",
  "homepage": "https://chessfolio.io",
  "documentation": "https://chessfolio.io/developers",
  "auth": {
    "type": "bearer",
    "description": "Personal tools need Authorization: Bearer <token> — create a personal access token at chessfolio.io → Settings → API access. The public tournament tools (auth: \"none\") need no token."
  },
  "remotes": [
    {
      "transport": "streamable-http",
      "endpoint": "https://chessfolio.io/api/mcp"
    }
  ],
  "tools": [
    {
      "name": "get_profile",
      "description": "The authenticated user's Chessfolio profile: display name, linked platform usernames, connected sources with sync freshness (last_synced_at), and total game count. Read-only, like every tool on this server.",
      "auth": "bearer",
      "input_schema": {
        "type": "object",
        "properties": {}
      }
    },
    {
      "name": "get_chess_stats",
      "description": "Aggregate statistics over the user's games for a chosen window: win/draw/loss by colour, online vs over-the-board comparison, performance rating, records and streaks, recent form, weekday performance, opponent-strength breakdown, game-length breakdown, top openings, monthly form and average accuracy. Same compute as the chessfolio.io dashboard.",
      "auth": "bearer",
      "input_schema": {
        "type": "object",
        "properties": {
          "range": {
            "type": "string",
            "enum": [
              "30d",
              "90d",
              "1y",
              "all"
            ],
            "description": "Time window: 30d, 90d, 1y (default) or all."
          },
          "providers": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "chesscom",
                "lichess",
                "ecf"
              ]
            },
            "description": "Restrict to sources: chesscom, lichess and/or ecf (OTB). Omit for all."
          },
          "timeClasses": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "bullet",
                "blitz",
                "rapid",
                "standard"
              ]
            },
            "description": "Restrict to time-control buckets: bullet, blitz, rapid, standard. Omit for all."
          },
          "opening": {
            "type": "string",
            "description": "Opening-family prefix filter, e.g. 'Sicilian'."
          }
        }
      }
    },
    {
      "name": "get_rating_progress",
      "description": "Rating series per provider and time control (including ECF over-the-board), each with start/end/delta over the window. Series longer than 60 points are evenly downsampled (first and last always kept) — pointsDownsampled says when. The window's opening value is seeded from the latest pre-window rating so deltas match the dashboard.",
      "auth": "bearer",
      "input_schema": {
        "type": "object",
        "properties": {
          "range": {
            "type": "string",
            "enum": [
              "30d",
              "90d",
              "1y",
              "all"
            ],
            "description": "Time window: 30d, 90d, 1y (default) or all."
          },
          "providers": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "chesscom",
                "lichess",
                "ecf"
              ]
            },
            "description": "Restrict to sources: chesscom, lichess and/or ecf (OTB). Omit for all."
          },
          "timeClasses": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "bullet",
                "blitz",
                "rapid",
                "standard"
              ]
            },
            "description": "Restrict to time-control buckets: bullet, blitz, rapid, standard. Omit for all."
          }
        }
      }
    },
    {
      "name": "list_games",
      "description": "Paged list of the user's games (50 per page) across chess.com, Lichess, ECF (OTB), manual and PGN imports, with filters matching the chessfolio.io games library: provider, result, colour, time class, date range, move-count range, opening, opponent, opening-line prefix (lineMoves, as returned by get_problem_lines) and free-text search. accuracy is the effective accuracy (platform value preferred, chessfolio review value as fallback — accuracySource says which).",
      "auth": "bearer",
      "input_schema": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "description": "1-based page number (50 games per page)."
          },
          "sort": {
            "type": "string",
            "enum": [
              "date-desc",
              "date-asc",
              "accuracy-desc",
              "accuracy-asc"
            ],
            "description": "Sort order. Default date-desc."
          },
          "providers": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "chesscom",
                "lichess",
                "ecf",
                "manual",
                "pgn"
              ]
            },
            "description": "Sources to include. Omit for all."
          },
          "results": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "win",
                "draw",
                "loss"
              ]
            },
            "description": "Filter by result."
          },
          "colours": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "white",
                "black"
              ]
            },
            "description": "Filter by the user's colour."
          },
          "timeClasses": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "ultraBullet",
                "bullet",
                "blitz",
                "rapid",
                "classical",
                "daily",
                "correspondence",
                "standard"
              ]
            },
            "description": "Raw time classes to include."
          },
          "from": {
            "type": "string",
            "description": "Inclusive lower date bound, YYYY-MM-DD."
          },
          "to": {
            "type": "string",
            "description": "Inclusive upper date bound, YYYY-MM-DD."
          },
          "movesMin": {
            "type": "integer",
            "description": "Minimum full-move count."
          },
          "movesMax": {
            "type": "integer",
            "description": "Maximum full-move count."
          },
          "opening": {
            "type": "string",
            "description": "Opening-name prefix filter."
          },
          "opponent": {
            "type": "string",
            "description": "Opponent-name contains filter."
          },
          "lineMoves": {
            "type": "string",
            "description": "SAN opening-line prefix (use a lineMoves value from get_problem_lines)."
          },
          "q": {
            "type": "string",
            "description": "Free-text search over opponent, opening, event and ECO."
          }
        }
      }
    },
    {
      "name": "get_game",
      "description": "One of the user's games in full: the same summary fields as list_games plus its moves and, where a Chessfolio review exists, a review summary. `movesSource` says what the moves are — `pgn` when the full game is stored (reviewed or PGN-attached games), `opening-only` when only the recorded opening line is known, or null for an OTB/online game with no attached PGN, which carries no moves at all (the endpoint never fabricates moves). `review` is present only when a Chessfolio analysis exists: accuracy for both colours and for the user, the key critical moments and a move-classification histogram (no per-ply detail). Read-only. `id` is a game id exactly as returned by list_games.",
      "auth": "bearer",
      "input_schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The game id, as returned by list_games."
          }
        },
        "required": [
          "id"
        ]
      }
    },
    {
      "name": "get_problem_lines",
      "description": "The 'lines that keep hurting': per-colour opening lines (6–24 plies) where the user's score drops at least 8 points below their colour baseline over at least 5 games, ranked by a struggle index of (drop × log2 of games). Each line carries its SAN prefix (lineMoves) for drill-through into list_games, plus a ready-made games URL. OTB (ECF) games carry no move lists and are excluded — hasLineData says whether any analysable games exist in the window.",
      "auth": "bearer",
      "input_schema": {
        "type": "object",
        "properties": {
          "range": {
            "type": "string",
            "enum": [
              "30d",
              "90d",
              "1y",
              "all"
            ],
            "description": "Time window: 30d, 90d, 1y (default) or all."
          },
          "providers": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "chesscom",
                "lichess",
                "ecf"
              ]
            },
            "description": "Restrict to sources: chesscom, lichess and/or ecf (OTB). Omit for all."
          },
          "timeClasses": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "bullet",
                "blitz",
                "rapid",
                "standard"
              ]
            },
            "description": "Restrict to time-control buckets: bullet, blitz, rapid, standard. Omit for all."
          }
        }
      }
    },
    {
      "name": "get_weekly_report",
      "description": "The user's most recent Friday weekly report as its frozen payload: per-source sections (chess.com / Lichess / OTB) with games, rating lines, best win and toughest defeat, plus puzzles — exactly what the email and the public share page render, with the share URL included. Returns a clear message when no report exists yet (reports generate on Fridays for weeks with activity).",
      "auth": "bearer",
      "input_schema": {
        "type": "object",
        "properties": {}
      }
    },
    {
      "name": "get_puzzle_stats",
      "description": "Cross-source puzzle activity and ratings: 12-week solve summary with win rate, volume bucketed to suit the window (day/week/month), and rating series for Lichess puzzles and chess.com tactics (chess.com is a peak-only rating — their API exposes no current value). Rating series longer than 120 rows are evenly downsampled, first and last kept (dataDownsampled says when).",
      "auth": "bearer",
      "input_schema": {
        "type": "object",
        "properties": {
          "range": {
            "type": "string",
            "enum": [
              "30d",
              "90d",
              "1y",
              "all"
            ],
            "description": "Time window: 30d, 90d, 1y (default) or all."
          }
        }
      }
    },
    {
      "name": "get_tournament_state",
      "description": "Public, read-only snapshot of any Chess-Results tournament — no token needed (source: chess-results.com). Returns the seeded player list, published round pairings with results, current standings, and any not-paired / requested-bye / withdrawal notes, plus a snapshotAt timestamp. Treat it as a point-in-time scrape that MAY BE STALE, not a live feed — always read snapshotAt. tnr is the Chess-Results tournament number (e.g. 651260) or a full chess-results.com tournament URL.",
      "auth": "none",
      "input_schema": {
        "type": "object",
        "properties": {
          "tnr": {
            "type": "string",
            "description": "Chess-Results tournament number (e.g. 651260) or a full chess-results.com tournament URL."
          }
        },
        "required": [
          "tnr"
        ]
      }
    },
    {
      "name": "estimate_round1",
      "description": "Public, read-only ESTIMATE of Round-1 pairings for a Chess-Results tournament — no token needed (source: chess-results.com). This is an ESTIMATE derived from the seed list, NOT the official pairing: the arbiter's real draw can differ. The opponent estimate is more reliable than colour — Round-1 colours hinge on the initial-colour draw, so treat the estimated colour as a coin-flip. The underlying snapshot may be stale (see staleWarning in the payload). Optional target returns just one player's board by case-insensitive name. tnr is the Chess-Results tournament number (e.g. 651260) or a full URL.",
      "auth": "none",
      "input_schema": {
        "type": "object",
        "properties": {
          "tnr": {
            "type": "string",
            "description": "Chess-Results tournament number (e.g. 651260) or a full chess-results.com tournament URL."
          },
          "target": {
            "type": "string",
            "description": "Optional player name (case-insensitive) to return just their estimated board."
          }
        },
        "required": [
          "tnr"
        ]
      }
    },
    {
      "name": "estimate_pairings",
      "description": "Public, read-only ESTIMATE of the next round's pairings for a Chess-Results Swiss tournament — no token needed (source: chess-results.com). It runs the real FIDE Dutch pairing engine (bbpPairings) over the live standings, but it is an ESTIMATE, NOT the official pairing: the arbiter's Swiss-Manager draw can legitimately differ (accelerated pairings, custom settings, manual corrections). The older manual seeded-Swiss method is a teaching aid, not the target. Colours follow each player's prior-round colour history. Optional round picks which round to estimate (defaults to the next unplayed round). Optional target spotlights one player by case-insensitive name and returns their board plus a what-if scenario table. tnr is the Chess-Results tournament number (e.g. 651260) or a full chess-results.com tournament URL.",
      "auth": "none",
      "input_schema": {
        "type": "object",
        "properties": {
          "tnr": {
            "type": "string",
            "description": "Chess-Results tournament number (e.g. 651260) or a full chess-results.com tournament URL."
          },
          "round": {
            "type": "integer",
            "description": "round to estimate; defaults to the next unplayed round"
          },
          "target": {
            "type": "string",
            "description": "a player name to spotlight; returns their board + a what-if scenario table"
          }
        },
        "required": [
          "tnr"
        ]
      }
    }
  ]
}