Developers

Your personal chess data, for agents

Chessfolio exposes your own chess data (games, stats, ratings, reports, puzzles and a personal study collection) through a REST API and an MCP server, both authenticated with personal access tokens. Your personal data stays private: a token can access only its owner’s data. There are five narrow writes, each scoped to an exact owned game or study row: attaching a PGN, requesting an engine review, uploading a PGN to study, requesting a study-game review, and deleting a game from the study collection. Alongside it sits a small public surface: six token-less tools — three reading published Chess-Results tournament data, one an ECF rating calculator, and two reading a curated classic-games library.

Quick start

  1. Create a token in Settings → API access

    Sign in and open Settings → API access, give the token a name and copy it when it’s shown. It is shown exactly once; you can revoke it any time.

  2. Call the REST API

    Send the token as a bearer header. Every endpoint returns JSON about the token owner only.

    curl -H "Authorization: Bearer cfp_…" https://chessfolio.io/api/v1/me
  3. Or connect over MCP

    The MCP server speaks streamable HTTP at https://chessfolio.io/api/mcp. In claude.ai, add it as a custom connector with that URL and the same Authorization header. In Claude Code:

    claude mcp add --transport http chessfolio https://chessfolio.io/api/mcp --header "Authorization: Bearer $TOKEN"

Connecting a client

Any MCP client (Claude Code, claude.ai connectors, Codex, Hermes and the rest) needs three things: the server URL, your token as a bearer header, and the tool list. Point it at https://chessfolio.io/api/mcp over streamable HTTP, send Authorization: Bearer cfp_…, and it reads every tool schema from the discovery documents. The public tools need no header.

Your personal endpoints

Token required

Sixteen REST endpoints and sixteen matching MCP tools over one shared service layer, so a REST response and its MCP counterpart return the same data. Every one takes your token and reads or writes only your own data.

The sixteen personal MCP tools and their matching REST operations, every one requiring a token
REST endpointMCP toolReturns
/api/v1/meget_profileThe authenticated user's Chessfolio profile: display name, linked platform usernames, connected sources with sync freshness (last_synced_at), and total game count.
/api/v1/me/statsget_chess_statsAggregate 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.
/api/v1/me/ratingsget_rating_progressRating series per provider and time control (including ECF over-the-board), each with start/end/delta over the window.
/api/v1/me/gameslist_gamesPaged 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).
/api/v1/me/games/{id}get_gameOne 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).
/api/v1/me/games/{id}/analysisget_game_analysisMove-by-move engine analysis of one of the user's reviewed games (the deterministic detail behind get_game's review summary).
/api/v1/me/games/{id}/critical-momentsget_critical_momentsThe teachable positions from one of the user's reviewed games, so you do not have to read every ply to find what matters.
POST /api/v1/me/games/{id}attach_pgnAttach one complete PGN to an existing game in the authenticated user's Chessfolio library.
POST /api/v1/me/games/{id}/reviewrequest_game_reviewAsk Chessfolio to run its engine review over one of the authenticated user's games.
/api/v1/me/problem-linesget_problem_linesThe '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).
/api/v1/me/report/latestget_weekly_reportThe 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.
/api/v1/me/puzzlesget_puzzle_statsCross-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).
/api/v1/me/studylist_study_gamesThe authenticated user's personal study collection — every game saved via upload_study_game, newest first, up to 200 rows.
POST /api/v1/me/studyupload_study_gamePaste one complete PGN into the authenticated user's personal study collection — for studying somebody else's game (a classic, a friend's game, one found online), not for the user's own played games (use attach_pgn against an existing list_games row for those).
POST /api/v1/me/study/{id}/reviewrequest_study_analysisAsk Chessfolio to run its engine review over one of the authenticated user's study games (as saved by upload_study_game).
DELETE /api/v1/me/study/{id}delete_study_gameDelete ONE game from the authenticated user's personal study collection, including its per-ply study notes (they cascade with the row).

The public surface

Public · no token

Six tools need no token and touch none of your account. Three read published tournament data straight from chess-results.com: point them at a tournament number and they answer for anyone. One has no upstream at all — a rating calculator that works only on the numbers you hand it. The last two read a curated classic-games library: browse it, then fetch one game’s editorial essay and PGN by slug. All are GET, like the personal endpoints.

The six public REST endpoints and their matching MCP tools, none of them requiring a token
REST endpointMCP toolReturns
/api/v1/librarylist_library_gamesPublic, token-less listing of Chessfolio's curated classic-games library — around 50 published historical and instructive games, each with editorial commentary, a source citation and full engine analysis behind it.
/api/v1/library/{slug}get_library_gamePublic, token-less full entry for one published library game: the editorial essay, its source citation, the canonical PGN, and both players' overall engine accuracy — but deliberately NO per-ply data (no move evaluations, no critical moments, no depth): the library surface is prose and provenance, not an analysis feed, by hard design exclusion.
/api/v1/tournaments/{tnr}/stateget_tournament_statePublic, read-only snapshot of any Chess-Results tournament — no token needed (source: chess-results.com).
/api/v1/tournaments/{tnr}/round1estimate_round1Public, read-only ESTIMATE of Round-1 pairings for a Chess-Results tournament — no token needed (source: chess-results.com).
/api/v1/tournaments/{tnr}/pairingsestimate_pairingsPublic, read-only ESTIMATE of the next round's pairings for a Chess-Results Swiss tournament — no token needed (source: chess-results.com).
/api/v1/ecf/rating-changecalculate_ecf_rating_changePublic, token-less ECF rating calculator: work out what a set of results does to an English Chess Federation rating, using the ECF's published K Rating algorithm (V4, August 2020).

Chess-Results tournament tools

get_tournament_state, estimate_round1, estimate_pairings

Parameters

tnr
Required. The Chess-Results tournament number, for example 651260. In a REST path it is digits only; the MCP tools also accept a full chess-results.com tournament URL.
target
Optional, on round1 and pairings. A player name (case-insensitive) to return just their estimated board (with a what-if scenario table on pairings).

No token, no header. Point curl at a tournament number:

curl https://chessfolio.io/api/v1/tournaments/651260/state
curl "https://chessfolio.io/api/v1/tournaments/651260/round1?target=Wesson"
  • An estimate, not a pairing. estimate_round1 derives boards from the seed list, so isEstimate is always true. The arbiter's official draw can differ.

  • Colour is a coin-flip. Round-1 colours turn on the initial-colour draw, so trust the estimated opponent far more than the estimated colour.

  • Snapshots can be stale. State carries a snapshotAt timestamp and is a short-lived scrape, not a live feed. Read the timestamp before you rely on it.

  • Read from chess-results.com. The tournament tools scrape published Chess-Results data. If that page layout changes they fail loudly rather than return half-parsed rows.

ECF rating calculator

calculate_ecf_rating_change

Parameters

currentRating
Required. The rating before these games, for example 1650. Four-digit scale (2020 onwards), not an old-style three-digit grade.
games
Required. Opponent rating then result, comma-separated: 1750 win, 1700 draw, 1600 loss. Short forms work too: w, d and l, or 1, = and 0. Up to 100 games a call, and send a whole month together, because the ECF’s monthly cap is a per-month rule.
age
Optional. Only the under-18 boundary matters: a junior who is gaining rating moves at K = 40 rather than 20, which roughly doubles the change. Omit to be treated as an adult.
gamesThisMonth
Optional. Every rated game played in the rating month, when that is more than the games listed here. The ECF’s 700-point monthly cap divides by this number, so it defaults to however many games you sent.

No token here either, and no upstream. The whole answer comes out of the query string:

curl "https://chessfolio.io/api/v1/ecf/rating-change?currentRating=1650&games=1750%20win,1700%20draw,1600%20loss"
  • Arithmetic, not an official figure. The ECF rates a whole monthly cycle against one Old Rating carried in from the previous cycle, which is not always the rating published as effective for the month the games were played. Opponents count at the ratings they held for that cycle too.

  • K Rating only. New and partially-rated players (fewer than 10 rated games) are rated by the ECF's P (performance) algorithm instead. This does not implement P, so the answer does not apply to them.

  • Adjustment is treated as zero. Adjustment is an ECF-wide drift correction applied in some years and not others, and it is zero in almost all of them.

Classic-games library

list_library_games, get_library_game

Parameters

slug
Required on get_library_game. A game’s slug, for example opera-game-morphy-1858, as returned by list_library_games.

No token, no header. Browse around 50 curated classic and instructive games, then fetch one by slug:

curl https://chessfolio.io/api/v1/library
curl https://chessfolio.io/api/v1/library/opera-game-morphy-1858
  • Prose and provenance, not an analysis feed. get_library_game returns the editorial essay, its source citation, the canonical PGN and both players' overall accuracy — but deliberately no per-ply data at all: no move evaluations, no critical moments, no depth. That is a hard design exclusion, not a gap.

  • Study it move by move for free. Paste a library game's PGN into your own study collection with upload_study_game. Because the content is byte-identical to the copy already analysed here, request_study_analysis returns that analysis at zero engine cost via content-addressed dedupe.

  • One 404, no oracle. An unknown slug, a malformed one, and a well-formed but unpublished one all answer with the same fixed message, so the response never confirms whether a draft exists.

The fine print, up front

  • Five narrow writes. Personal tools are read-only except attach_pgn, which can attach moves to one exact game id owned by the token holder; request_game_review, which can queue (or wait for) an engine review of one exact owned game; upload_study_game, which can save one validated PGN into the token holder's own study collection; request_study_analysis, the study collection's equivalent of request_game_review; and delete_study_game, which removes one game (and its per-ply notes, irreversibly) from the token holder's own study collection while leaving the underlying analysed game record untouched. None can edit results, ratings, another user's data, or create anything outside the token holder's own account.

  • Owner-scoped tokens. A personal token can access only its creator's data, with no cross-user access. The public tools sit outside this entirely: they touch no account, reading either published Chess-Results data, the curated library, or nothing but the numbers you send them.

  • Rate-limited. 120 requests per minute per user on the personal surface, shared across REST and MCP. Four endpoints are tighter, each in its own bucket and each shared across both surfaces: PGN attachment at 20 per hour; newly queued reviews at 20 per hour — one allowance shared between request_game_review and request_study_analysis, since both queue the same engine — with re-fetching an already-reviewed game or study game costing nothing against either; study-collection uploads at their own, separate 20 per hour, enforced atomically and failing closed if the limiter itself is unavailable; and the two per-ply analysis reads at 30 a minute, because those replay every move through a chess engine instead of answering from a query. The public tools are 60 a minute, and each of the three families — tournament, ECF calculator, library — is limited separately, so a busy tournament weekend cannot lock out the rating calculator or the library. Over REST that 60 is per caller. Over MCP it is a single shared bucket per family, because the protocol carries no client address to charge it to.

  • Downsampled rating series. Series longer than 60 points are evenly downsampled (first and last points always kept); responses say when this happened.

  • OTB games have no move lists. Over-the-board (ECF) games carry results and ratings but no moves, so they are excluded from problem-lines analysis.

  • Study uploads dedupe on the moves, not the file. Re-uploading a game whose headers, comments or clock tags differ from one already in your collection lands on that same row instead of creating a duplicate — its analysis is kept, and any new comments fill plies that don't already have a note. Separately, and regardless of collection membership, Chessfolio's backing store reuses analysis whenever the full canonical text — headers and clocks included — byte-matches a game analysed anywhere in Chessfolio's store, including a library game, so request_study_analysis can return that analysis for free, spending nothing against the shared review allowance.

  • Tokens are shown once. Only a fingerprint is stored. Tokens are revocable any time in Settings and revocation takes effect on the next request.

Machine-readable discovery

Everything above is also published where agents look for it.

Point an agent at your chess

Create a token in Settings and you’re one curl away. No Chessfolio account yet? It’s free.