Skip to main content
Glama

lichess-mcp

An MCP server for Lichess, the free, open-source chess site. MCP (Model Context Protocol) is the open standard that lets AI apps like Claude and Cursor call outside tools. This server gives them a player's profile and recent games, the mistakes Lichess's engine flagged in those games, cloud engine evaluations, exact endgame results from the tablebase, puzzles, and opening statistics.

It is built around one rule: the model never does the chess. Every evaluation, every "this was a mistake", every best move comes from Lichess: its server analysis of a game, its cloud evaluation cache, or its endgame tablebase. When Lichess has no answer, the tool says "not available" and tells the model not to estimate one.

No API key needed. Runs locally over stdio or as a remote server with a web playground.

The code is MIT. The piece images in public/pieces/ are the cburnett set by Colin M.L. Burnett, copied from Lichess's lila repo and licensed GPLv2+ (see public/pieces/LICENSE).

Game review in the playground

Why the model never does the chess

Language models are fluent about chess and often wrong about it. They suggest illegal moves, hang pieces, miss short tactics, and state evaluations no engine would agree with, all in the same confident tone as when they are right. For a coaching tool that is the worst kind of error, because the player has no easy way to tell.

So the work is split:

  • Lichess does the chess. Per-move evals and inaccuracy / mistake / blunder labels come from Lichess's server analysis (Stockfish). Position evals come from the Lichess cloud cache. Positions with 7 pieces or fewer come from the Syzygy tablebase, which is perfect play.

  • The code does bookkeeping. chess.js validates FENs (the standard text format for a chess position), replays games to recover each position, and converts engine notation (e7e5) to normal notation (e5). It never judges a position.

  • The model explains. It reads the structured results and talks to the player.

  • Missing data stays missing. An unanalysed game, a position the cloud cache doesn't have, or a hidden puzzle solution comes back as an explicit "not available" with the next step (request analysis on Lichess, use the tablebase, open the analysis board). The server instructions and tool messages tell the model not to fill the gap itself.

Related MCP server: Lichess MCP

What you can ask

Review my last blitz game as thibault. What were my worst moves?

What does the engine say about this position? r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3

Is this king and pawn endgame a win? 4k3/8/4K3/4P3/8/8/8/8 w - - 0 1

Give me today's puzzle but don't tell me the answer yet.

What do 1600-1800 blitz players play against the Sicilian after 2. Nf3? (needs a token, see below)

Install

Requires Node.js 20 or newer. The package name is lichess-coach-mcp (the name lichess-mcp on npm belongs to an unrelated project).

The package is not on npm yet. The commands below install it straight from GitHub with npx -y github:frogr/lichess-mcp: npm clones the repo, installs dependencies and builds it (a prepare script runs npm run build). The first start takes about 20 seconds while that happens, so run it once in a terminal before adding it to a client. If you'd rather not run a build through npx, use From source.

After the package is published to npm, npx -y lichess-coach-mcp will do the same thing. Until then, don't run that name: nothing has been published under it by this project.

Claude Desktop

Add this to claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop:

{
  "mcpServers": {
    "lichess": {
      "command": "npx",
      "args": ["-y", "github:frogr/lichess-mcp"]
    }
  }
}

To enable opening_stats, add "env": { "LICHESS_TOKEN": "lip_..." } with your own token.

Claude Code

claude mcp add --transport stdio lichess -- npx -y github:frogr/lichess-mcp

# with a token, available in every project:
claude mcp add --env LICHESS_TOKEN=lip_... --transport stdio --scope user lichess -- npx -y github:frogr/lichess-mcp

# or a hosted copy of the remote server:
claude mcp add --transport http lichess https://your-host.example/mcp

Cursor

Add to ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (this project):

{
  "mcpServers": {
    "lichess": {
      "command": "npx",
      "args": ["-y", "github:frogr/lichess-mcp"]
    }
  }
}

For a hosted copy, use { "url": "https://your-host.example/mcp" } instead.

From source

git clone https://github.com/frogr/lichess-mcp && cd lichess-mcp
npm ci   # also builds dist/ through the prepare script
# then use "command": "node", "args": ["/absolute/path/to/lichess-mcp/dist/index.js"]

Configuration

Env var

Default

Purpose

LICHESS_TOKEN

none

Personal API token from lichess.org/account/oauth/token, no scopes needed. Only opening_stats requires it. Leave it unset otherwise: Lichess rejects every request that carries a bad token.

LICHESS_TIMEOUT_MS

15000 (stdio), 12000 (HTTP)

Per-request timeout.

The HTTP server has more settings (rate limits, CORS, body size); they are listed in .env.example.

Tools

Tool

What it does

Key inputs

Source of the chess

get_player

Profile: title, rating per speed with game counts and provisional flags, W/L/D totals, puzzle high scores

username

n/a

recent_games

Up to 20 recent finished games, read from Lichess's NDJSON export: opponent, result, opening, accuracy, and whether the game has analysis

username, max, perf_type, rated

Lichess server analysis (accuracy)

get_game

One game: players, result, opening, every move in SAN with clock time, per-move eval and judgment when analysed, clean PGN

game_id (id or URL), include_pgn

Lichess server analysis

find_mistakes

One player's flagged moves: move played, Lichess's best move and line, eval and winning chances before and after, the FEN before the move

game_id, for_player (name or white/black), min_severity

Lichess server analysis

evaluate_position

Cloud eval for a FEN: score, best move and line in SAN, up to 3 lines

fen, multi_pv

Lichess cloud eval

tablebase

Exact win/draw/loss for 7 pieces or fewer, distance to mate or zeroing, every move ranked

fen

Lichess tablebase (Syzygy)

puzzle_of_the_day

Today's puzzle: position, side to move, rating, themes, source game. Solution hidden unless reveal_solution

reveal_solution

Lichess puzzles

get_puzzle

Same, by puzzle id

id, reveal_solution

Lichess puzzles

opening_stats

Opening explorer: opening name, each next move's popularity and results, from the Lichess or Masters database

moves or fen, database, speeds, ratings

Lichess opening explorer (needs token)

Every tool is marked readOnlyHint: true and declares an outputSchema. Results come back as JSON text, which works in any client, and as structuredContent for clients that use it.

Design notes

Not available is a normal answer. Three things are often missing, and each has its own reply:

  • A game nobody asked Lichess to analyse. find_mistakes returns analysis_available: false, no mistakes, and the steps to request a free analysis on Lichess. In the live check on 2026-10-07 (see PROOF.md), 8 of thibault's 20 most recent games had no analysis.

  • A position not in the cloud cache. evaluate_position returns available: false. If the position has 7 pieces or fewer it points to tablebase; otherwise it gives the Lichess analysis-board URL. This is common for real middlegame positions: in the same live check, 13 of 15 mistake positions were not in the cache.

  • The opening explorer without a token. Lichess now requires sign-in for it, so opening_stats says that up front instead of failing with a bare 401.

Puzzles are for solving. The solution stays out of the response (not just out of the text) until reveal_solution: true. While hidden, there is a one-line hint naming the piece that moves first, taken from Lichess's solution, so the model can nudge without working anything out. The puzzle position is rebuilt by replaying the source game, which keeps real move numbers; the solution is then numbered from there (14... e4 15. Nxf6+ Qxf6).

Bookkeeping that can't invent notation. UCI-to-SAN conversion plays each move on a real board and stops at the first illegal move, so a malformed engine line comes back shorter, never made up. Lichess engines write castling as king-takes-rook (e1h1); that is translated before replay. Win chances use Lichess's own formula on Lichess's eval.

Being polite to Lichess. The client follows the Lichess API tips: one request at a time per host, a descriptive User-Agent, and after any 429 it stops calling that host for a full minute and says so instead of retrying. It also has timeouts, retries on 5xx with backoff, and a 60-second cache so an agent asking the same thing twice costs one request. The game export is NDJSON (one JSON object per line); it is read as a stream and the download is cancelled once enough games have arrived.

Inputs. Usernames, game ids, puzzle ids and enum values are checked by zod schemas before any request. A game id can also be a lichess.org URL. FENs are validated with chess.js (including Lichess's underscore URL form and missing move counters) before anything is sent. Move lists for the explorer accept SAN or UCI and name the first illegal move.

Errors. Upstream failures become tool errors (isError: true) with a hint the model can act on:

No Lichess game with id 'zzzzzzzz'. (HTTP 404)
Hint: Game ids are the 8 characters after lichess.org/ in the game URL. Use recent_games to list a player's games.

Remote server and playground

npm start serves:

Route

POST /mcp

MCP over Streamable HTTP (official SDK), stateless, JSON responses

GET /

Web playground: enter a username to review recent games and their flagged mistakes on a board, try the puzzle of the day, and copy client configs

GET /health

Status, version, limits and whether a token is set. Never calls Lichess.

/mcp is protected for public hosting: per-IP rate limit (default 30/min, token bucket), a global daily cap (default 5,000), a 64 KB body limit checked before parsing, a 30-second wall-clock limit per request, CORS with an optional allow list, and generic messages instead of stack traces. The playground page is served with a strict Content-Security-Policy and builds every element with DOM methods, so text from Lichess is never parsed as HTML.

Deploy

Render (free): push the repo to GitHub, then in Render choose New > Blueprint and pick the repo. render.yaml sets up a free web service with npm ci && npm run build, npm start, health check on /health, and TRUST_PROXY=1. Optionally add LICHESS_TOKEN in the dashboard to enable opening_stats. Free instances sleep when idle, so the first request after a while takes a few extra seconds.

Docker:

docker build -t lichess-coach-mcp . && docker run -p 3000:3000 lichess-coach-mcp

Any Node host: npm ci && npm run build && npm start. Set TRUST_PROXY to the number of proxies in front of the app so rate limiting sees the real client IP.

Env vars: LICHESS_TOKEN (optional), LICHESS_TIMEOUT_MS, PORT, HOST, RATE_LIMIT_PER_MINUTE, DAILY_REQUEST_LIMIT, MAX_BODY_BYTES, REQUEST_TIMEOUT_MS, CORS_ORIGINS, TRUST_PROXY. Defaults are in .env.example.

Development

npm install
npm test                 # vitest, recorded fixtures only, no network
npm run typecheck
npm run build
npm run smoke            # stdio: initialize + tools/list
npm run smoke:http       # HTTP: /health, CORS, initialize, tools/list, playground
node scripts/smoke.mjs --live         # also real tool calls to Lichess
node scripts/live-check.mjs thibault  # consistency check against live Lichess (see PROOF.md)
npm run screenshots      # Playwright + Chromium, live data

Tests run against responses recorded from the real Lichess API in test/fixtures/ (one opening-explorer response is synthetic and labeled as such, since the explorer needs a token). A mocked fetch fails on any URL it doesn't know. test/server.test.ts drives the full MCP protocol in memory, including output-schema validation; test/http.test.ts runs the SDK client against a real socket.

src/
  index.ts         stdio entrypoint (the package bin)
  http.ts          Node HTTP adapter for the remote server
  app.ts           routes, CORS, rate limits, size and time limits
  server.ts        tool registration and server instructions
  lichess.ts       HTTP client: per-host queue, 429 cooldown, retries, cache
  ndjson.ts        streaming NDJSON parser
  chess.ts         chess.js helpers: FEN checks, UCI to SAN, replay
  tools/           one file per tool group: zod schemas + handler
public/            playground page and piece SVGs
test/              vitest suites + fixtures/
scripts/           smoke tests, live check, screenshots

Credits

Data from the Lichess API. Not affiliated with Lichess. Piece images are the cburnett set by Colin M.L. Burnett, the set Lichess uses by default, licensed GPLv2+ (as listed in Lichess's COPYING.md). They are not under this repo's MIT license: public/pieces/LICENSE has the attribution and the full GPLv2 text, and it applies if you copy those files.

License

MIT © Austin French, for the code. The piece SVGs in public/pieces/ are GPLv2+, not MIT; see public/pieces/LICENSE.


Need an MCP server for your own API? austn.net

Available Tools

9 tools
evaluate_positionCloud engine evaluation of a positionA
Read-onlyIdempotent

Get the engine evaluation of a chess position (FEN) from Lichess's cloud cache: score, best move and principal line in SAN, for up to 3 candidate moves. If the position isn't cached, it returns available=false rather than a guess.

ParametersJSON Schema
NameRequiredDescriptionDefault
fenYesPosition in FEN, e.g. "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1". Move counters may be omitted.
multi_pvNoHow many candidate lines (1-3).

Output Schema

ParametersJSON Schema
NameRequiredDescription
fenYes
depthNo
linesYes
knodesNoThousands of nodes searched.
sourceNo
messageYes
availableYesFalse when Lichess has no cached cloud evaluation for this position.
side_to_moveYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnly, idempotent and non-destructive behavior, but the description adds genuine context the annotations don't: results come from a cache and an uncached position yields available=false rather than a guessed evaluation. That fallback contract is exactly the kind of trait an agent needs before relying on the result.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence that delivers the verb, resource, source, output contents and the cache-miss behavior with zero filler. Nothing is padded or redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the return values need not be spelled out, and annotations plus schema cover safety and parameters; the description closes the remaining gap by explaining the cache-miss case. It is only slightly short of complete because it omits any routing hint toward the tablebase sibling for endgame positions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the FEN and multi_pv parameters are both documented with formats and bounds in the schema. The description's 'up to 3 candidate moves' merely restates the multi_pv maximum, adding no syntax or semantic detail beyond the structured fields, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get the engine evaluation of a chess position (FEN)') and scopes the source as 'Lichess's cloud cache', which meaningfully separates it from a local engine or the tablebase sibling. It does not name a sibling tool to contrast against, so it falls short of the top mark.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies usage (feed it a FEN, get an eval) and notes the up-to-3 candidate-move capability, but gives no explicit when-to-use guidance or exclusions. Notably it never tells the agent to prefer the 'tablebase' sibling for endgame positions, which is the most likely selection ambiguity here.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_mistakesEngine-flagged mistakes in a gameA
Read-onlyIdempotent

List one player's inaccuracies, mistakes and blunders in a Lichess game, straight from Lichess's server analysis: the move played, the engine's best move and line, evals before/after and winning chances lost. If the game was never analysed, it says so instead of guessing.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idYesLichess game id (8 characters, e.g. "bKi4MXMJ") or a lichess.org game URL.
for_playerYesWhose mistakes to list: a username in the game, or "white" / "black".
min_severityNoSmallest judgment to include (default inaccuracy = everything Lichess flagged).inaccuracy

Output Schema

ParametersJSON Schema
NameRequiredDescription
urlYes
playerYes
game_idYes
messageYes
summaryNo
mistakesYes
analysis_availableYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the read-only/idempotent/safe profile, and the description adds genuinely new behaviour: results come from Lichess's server analysis rather than a locally computed evaluation, and an unanalysed game yields an explicit statement rather than guesses. Rate limits, auth, or pagination are not mentioned.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler: the first front-loads what is returned and from where, the second covers the degraded case. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is not required; the description nonetheless sketches the payload and the unanalysed-game case. With annotations covering safety and the schema covering all three parameters, nothing an agent needs to invoke this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including the game_id format and the white/black-or-username option for for_player, so the schema carries the burden. The description lists the three severity labels, loosely mapping to min_severity's enum, but adds no format or edge-case detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (list) and resource (one player's inaccuracies/mistakes/blunders in a Lichess game) and pins the source as Lichess server analysis, which cleanly separates it from siblings like evaluate_position or get_game.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies the prerequisite context (a Lichess game that has been analysed, one player at a time) and the fallback when that precondition fails. It doesn't explicitly route the agent away from evaluate_position when the agent just wants a single-position judgement, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_gameOne game with moves and evalsA
Read-onlyIdempotent

Fetch one Lichess game: players, ratings, result, opening, time control, every move in SAN with clock times, and per-move engine evals and judgments when Lichess has analysed the game. Includes clean PGN.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idYesLichess game id (8 characters, e.g. "bKi4MXMJ") or a lichess.org game URL.
include_pgnNoInclude the PGN text (headers + moves, no comments).

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
pgnNo
urlYes
dateNo
noteYes
movesYes
ratedYes
speedYes
phasesNo
resultYes"1-0", "0-1", "1/2-1/2", or "*" if unfinished.
statusYes
winnerNo
openingNo
playersYes
variantYes
has_analysisYes
time_controlNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), so the bar is lower. The description still adds real behavioral context: evals and judgments are only present 'when Lichess has analysed the game', and the PGN is 'clean' (headers + moves, no comments). That conditional availability is exactly the kind of nuance annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero preamble, with the resource and payload front-loaded before the conditional eval caveat. The enumeration is long but each item is substantive rather than filler; slightly list-heavy for a description that could group related fields.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no further explanation, and the description nonetheless sketches the payload shape. Combined with full schema coverage and clear annotations, an agent has everything needed to invoke it; only the routing versus sibling list tools is left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters (game_id format/URL, include_pgn default) are already fully documented in the schema. The description mentions 'Includes clean PGN' and 'every move in SAN', which aligns with but does not extend the schema semantics. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Fetch') plus a precise resource ('one Lichess game') and enumerates the returned payload: players, ratings, result, opening, time control, SAN moves with clock times, engine evals/judgments, and PGN. The singular 'one game' clearly separates it from sibling recent_games (a list) and get_player (a player entity).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the payload description, and the clause 'when Lichess has analysed the game' signals a conditional expectation the caller should have. However, no sibling is named and no when-to-use/when-not guidance is given, so the agent must infer that recent_games is the path for discovery and this tool for a known game_id.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_playerLichess player profile and ratingsA
Read-onlyIdempotent

Look up a Lichess player: title, ratings for each speed they play (bullet, blitz, rapid, classical, puzzles, variants) with game counts and provisional flags, win/loss/draw totals, and basic profile info.

ParametersJSON Schema
NameRequiredDescriptionDefault
usernameYesLichess username, e.g. "thibault". Case does not matter.

Output Schema

ParametersJSON Schema
NameRequiredDescription
urlYes
gamesNo
titleNoGM, IM, FM, CM, NM, WGM, ..., LM, BOT
patronYes
profileNo
ratingsYesRated speeds and variants the player has actually played, most games first.
usernameYes
created_atNo
last_seen_atNo
puzzle_modesYesPuzzle Storm / Racer / Streak high scores.
account_statusYes
play_time_hoursNo

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and non-destructive, so the safety profile is fully covered by structured data. The description's addition is mostly return-content scope (which speed ratings, provisional flags, W/L/D totals), and since an output schema exists that content is largely redundant. It does not mention auth or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One front-loaded sentence with zero filler: verb and resource come first, and the parenthetical field list earns its place by defining scope rather than padding. Nothing to cut without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read-only lookup with a full output schema and complete annotations, the definition is essentially complete. The only minor gap is that most of its text describes return values that the output schema already documents, and no auth/rate-limit context is offered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter has 100% schema description coverage, including a pattern and a concrete example ('thibault') and the case-insensitivity note, so the schema carries the full burden. The description adds nothing about the username argument beyond implying profile lookup, which is the baseline-3 case for fully documented params.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb ('look up') plus specific resource ('Lichess player'), and it enumerates the exact data scope (per-speed ratings, game counts, provisional flags, W/L/D totals, profile info). That scope makes it clearly distinguishable from siblings like get_game, recent_games, and opening_stats, which operate on games/openings rather than a player profile.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the verb and resource — an agent can infer this is the profile-lookup tool — but there is no explicit when-to-use statement and no reference to alternatives such as recent_games when the agent actually wants game history. No exclusions or prerequisites are stated anywhere.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_puzzleLichess puzzle by idA
Read-onlyIdempotent

Fetch a Lichess puzzle by id: position (FEN), side to move, rating, themes and source game. The solution stays hidden unless reveal_solution=true.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesLichess puzzle id (5 characters, e.g. "uFTip"), as in lichess.org/training/uFTip.
reveal_solutionNoInclude the solution moves. Leave false to coach: let the player try first, then call again with true.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
fenYesThe position the solver faces (after the opponent's last move).
urlYes
hintNoA small nudge (which piece moves first) for when the player is stuck. Present only while the solution is hidden.
playsYes
ratingYes
themesYesLichess theme tags, e.g. "fork", "mateIn2", "endgame".
messageYes
solutionNoFull forced line, solver and opponent moves alternating. Only present when reveal_solution is true.
last_moveNoThe opponent's move that set up the puzzle.
source_gameYes
solver_colorYes
solver_movesYesHow many moves the solver must find.
solution_revealedYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly=true, idempotent=true, non-destructive and open-world, so safety is covered. The description adds genuinely useful non-obvious context: the solution payload is withheld unless reveal_solution=true, which tells the agent why a call may return no solution.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One compact sentence plus a conditional clause; the verb and identifier are front-loaded and the return contents are delivered as a tight list. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter lookup with a full schema and an output schema, the description covers the essentials. It omits where an agent obtains a puzzle id and any error behavior for invalid ids, but nothing critical to correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description goes slightly beyond the schema by explaining the conditional effect of reveal_solution on the returned payload (solution remains hidden), which is the kind of effect detail that helps decide whether to set it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetch a Lichess puzzle by id') and enumerates what comes back (FEN, side to move, rating, themes, source game). It does not, however, name or contrast itself with the close sibling puzzle_of_the_day, which also returns a puzzle, so an agent must infer the distinction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'By id' weakly implies you must already hold a puzzle id, which is an implied prerequisite rather than stated guidance. There is no explicit when-to-use statement and no routing to alternatives such as puzzle_of_the_day for a random/daily puzzle.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opening_statsOpening explorer statisticsA
Read-onlyIdempotent

Opening explorer statistics for a position from the Lichess or Masters database: opening name, how often each next move was played, and White/draw/Black results. Takes a move list or FEN. Needs LICHESS_TOKEN on the server (Lichess now requires sign-in for the explorer).

ParametersJSON Schema
NameRequiredDescriptionDefault
fenNoStart position in FEN. Omit for the normal starting position.
movesNoMoves from the start (or from fen): SAN like "1. e4 c5 2. Nf3" or UCI like "e2e4 c7c5". Gives the opening name too.
speedsNolichess database only: limit to these speeds.
ratingsNolichess database only: rating buckets, e.g. [1600, 1800] for 1600-1999.
databaseNolichess = all rated Lichess games; masters = over-the-board games between 2200+ FIDE players.lichess

Output Schema

ParametersJSON Schema
NameRequiredDescription
fenYes
messageYes
openingNo
databaseYes
draws_pctYesPercent of games.
moves_sanYes
next_movesYes
total_gamesYes
black_wins_pctYesPercent of games.
white_wins_pctYesPercent of games.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), but the description adds a genuinely useful non-schema trait: the server requires LICHESS_TOKEN because Lichess now mandates sign-in for the explorer. That is a real operational constraint an agent must know before calling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, no filler: the purpose and return contents are front-loaded, and the authentication requirement follows. Every sentence carries information the agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not explain return values, and it correctly focuses on what the tool does, what it accepts, and the token prerequisite. Nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents fen, moves, speeds, ratings and database. The description only restates what inputs are accepted ('move list or FEN') without adding format or constraint detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Opening explorer statistics for a position') and enumerates the payload (opening name, move frequency, W/D/B results). It is clearly separable from siblings like get_game or evaluate_position, which do not return opening-tree statistics.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context for use: query a position via move list or FEN, and choose between the Lichess or Masters database. It does not explicitly say when NOT to use it versus a sibling such as evaluate_position, so it falls short of full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

puzzle_of_the_dayLichess daily puzzleA
Read-onlyIdempotent

Today's Lichess daily puzzle: position (FEN), side to move, rating, themes and the source game. The solution stays hidden unless reveal_solution=true, so a coach can let the player try first.

ParametersJSON Schema
NameRequiredDescriptionDefault
reveal_solutionNoInclude the solution moves. Leave false to coach: let the player try first, then call again with true.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
fenYesThe position the solver faces (after the opponent's last move).
urlYes
hintNoA small nudge (which piece moves first) for when the player is stuck. Present only while the solution is hidden.
playsYes
ratingYes
themesYesLichess theme tags, e.g. "fork", "mateIn2", "endgame".
messageYes
solutionNoFull forced line, solver and opponent moves alternating. Only present when reveal_solution is true.
last_moveNoThe opponent's move that set up the puzzle.
source_gameYes
solver_colorYes
solver_movesYesHow many moves the solver must find.
solution_revealedYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds a genuine behavioral trait not in the annotations: the solution is withheld unless reveal_solution=true, and the intended two-call coaching loop. It stops short of noting anything about freshness (that the puzzle changes daily) or failure behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with what the tool returns, and the second sentence immediately explains the one parameter's behavioral consequence. No filler or restated boilerplate.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no further explanation, and the annotations cover the read-only idempotent nature. The description closes the remaining gap an agent needs — that the solution field is conditional — making the definition complete for a zero-required-parameter read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With a single parameter at 100% schema description coverage, the schema already documents reveal_solution, its default, and the coach-then-reveal pattern. The description's mention of reveal_solution restates that same guidance rather than adding format or side-effect detail, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Today's Lichess daily puzzle') and enumerates what the response contains (FEN, side to move, rating, themes, source game). It implicitly differentiates from the sibling get_puzzle by scoping to 'today's daily', but never names that sibling explicitly, leaving a small gap for an agent choosing between the two.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It supplies a concrete usage context and workflow: leave reveal_solution=false so a coach can let the player try, then call again with true. That is actionable guidance for the primary use case, but it gives no exclusions or direct comparison against siblings like get_puzzle or find_mistakes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

recent_gamesA player's recent gamesA
Read-onlyIdempotent

List a Lichess player's most recent finished games (up to 20): id, date, speed, opponent and rating, result, opening name, and accuracy when Lichess has analysed the game. Use has_analysis to pick games that find_mistakes can review.

ParametersJSON Schema
NameRequiredDescriptionDefault
maxNoHow many games (1-20, default 10). Most recent first.
ratedNotrue for rated only, false for casual only. Omit for both.
usernameYesLichess username, e.g. "thibault". Case does not matter.
perf_typeNoOnly this speed or variant, e.g. blitz.

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNo
gamesYes
returnedYes
usernameYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish read-only, idempotent, non-destructive behaviour, so the description only needs to add context. It does: games are 'finished' (not in-progress), capped at 20, and accuracy is present only 'when Lichess has analysed the game' — a genuinely useful conditional that no annotation conveys.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with purpose then the chaining hint, with no filler. The enumerated return-field list is somewhat long, but it supports the purpose statement rather than padding it.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the return shape needn't be re-explained, and safety is covered by annotations; the description still supplies the 20-game cap, the 'finished' qualifier, the accuracy condition and the find_mistakes handoff. Only the relationship to get_game for single-game detail is left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so max, rated, perf_type and username are already fully documented with defaults, ranges and enums; the description's 'up to 20' merely restates the schema maximum. Baseline 3 applies since the description adds no syntax or semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List a Lichess player's most recent finished games') plus the scope cap and the exact fields returned, which cleanly separates it from get_game (single game) and get_player (profile). An agent can pick it over siblings on name alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent forward: 'Use has_analysis to pick games that find_mistakes can review,' naming the downstream sibling and the condition that selects it. However it gives no contrast against get_game, get_player or opening_stats, and 'has_analysis' is an output field rather than an input, which could momentarily confuse an agent scanning parameters.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tablebaseExact endgame result (7 pieces or fewer)A
Read-onlyIdempotent

Exact result for an endgame with 7 or fewer pieces from the Lichess tablebase: win/draw/loss for the side to move, distance to mate or zeroing, and every move ranked. This is perfect play, not an estimate.

ParametersJSON Schema
NameRequiredDescriptionDefault
fenYesPosition in FEN, e.g. "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1". Move counters may be omitted.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dtmYesDistance to mate in plies, when known (positive = side to move mates).
dtzYesDistance to zeroing move (capture or pawn move), in plies.
fenYes
movesYesLegal moves, best first (as Lichess sorts them), up to 8.
piecesYes
resultYesFor the side to move: win, loss, draw, cursed-win, blessed-loss, maybe-win, maybe-loss, unknown.
sourceYes
verdictYesOne sentence, built from the tablebase result.
checkmateYes
stalemateYes
side_to_moveYes
insufficient_materialYes

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered without description help. The description adds the meaningful guarantee that results are exact perfect play rather than heuristics, but it does not state what happens when the 7-piece limit is exceeded or whether lookups can fail/be rate-limited.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense sentence leads with the resource and scope, then enumerates the outputs, then closes with the exactness caveat. No filler, no repetition of the title, and every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present the description needn't explain return values, and annotations cover safety; the one-parameter schema is fully documented. The remaining gap is the out-of-range failure mode and the absence of explicit sibling routing, which keeps it short of complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single parameter (fen) with 100% schema description coverage, including a format example and the note that move counters may be omitted, so the schema does the heavy lifting. The description does not mention FEN at all and adds nothing beyond it, which is the expected baseline when coverage is complete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: exact endgame result from the Lichess tablebase, with the piece ceiling (7 or fewer) and the returned fields (win/draw/loss, distance to mate or zeroing, ranked moves) spelled out. The clause 'perfect play, not an estimate' distinguishes it from the sibling evaluate_position, which is engine-driven and approximate.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The '7 or fewer pieces' constraint is an effective precondition that tells the agent when this tool is applicable. However, it never explicitly names an alternative for positions outside that bound (e.g., evaluate_position), leaving the routing decision to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 9 tool updatesv0.1.0
    • First observedevaluate_position
    • First observedfind_mistakes
    • First observedget_game
    • First observedget_player
    • First observedget_puzzle
    • First observedopening_stats
    • First observedpuzzle_of_the_day
    • First observedrecent_games
    • First observedtablebase

TDQS

A4/5.0

Scored across 9 tools

Disambiguation4/5

Each tool targets a distinct resource: games, players, analysis, positions, endgames, puzzles, and openings. The only real overlaps are get_game vs recent_games (single fetch vs list) and get_puzzle vs puzzle_of_the_day (same content, different source), but descriptions clearly separate them.

Naming Consistency4/5

Consistent snake_case throughout with a dominant verb_noun pattern (get_game, get_player, get_puzzle, find_mistakes, evaluate_position). A few noun-only names (recent_games, tablebase, puzzle_of_the_day, opening_stats) break the pattern slightly but remain readable and predictable.

Tool Count5/5

Nine tools is well-scoped for a chess coaching domain, covering games, players, analysis, positions, endgames, puzzles, and openings without redundancy.

Completeness4/5

Strong lifecycle coverage: player lookup, game retrieval, mistake analysis, position evaluation, tablebase, puzzles, and opening stats. Minor gaps like game search or puzzle-by-theme browsing exist but core coaching workflows are fully supported.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables natural language interaction with Lichess chess platform to play games, analyze positions, manage challenges and tournaments, and interact with other players through Claude Desktop.
    16 npm
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Connects Claude to Lichess for playing chess games, analyzing positions with Stockfish cloud evaluation, and solving puzzles. Supports real-time gameplay including moves, challenges, draw offers, and accessing user profiles and game history.
    28
    16 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to explore player profiles, ratings, game archives, leaderboards, clubs, and puzzles via the Chess.com API.
    2
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to perform professional-grade chess analysis using Stockfish and optionally Leela Chess Zero, including position analysis, full game review, opening lookup, and puzzle generation.
    11 npm
    2
    MIT