croissant-mcp
Fetches recent games from the Lichess API and integrates with local En Croissant database files to provide opening preparation and review capabilities.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@croissant-mcpWhat am I due to review today, and what do opponents actually play there?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
croissant-mcp
An MCP server that gives Claude programmatic access to a local En Croissant installation, so opening prep can be driven from a conversation instead of by hand in the GUI.
Quickstart
Requires Python 3.13+, uv, and a local En Croissant install (developed against 0.15.0).
git clone https://github.com/cheungbrenden/croissant-mcp
cd croissant-mcp
uv syncRegister the server once, user-level, so it's available in any session:
claude mcp add --scope user croissant-mcp -- uv run --directory /path/to/croissant-mcp croissant-mcpThen ask for prep in a conversation:
What am I due to review today, and what do opponents actually play there?
Nothing else to configure — the Lichess handle is derived from the
<handle>_lichess.db3 filename and paths from the standard macOS locations.
USAGE.md has the full tool list, with honest status marks for what
is built and what isn't.
Related MCP server: Chess MCP
Why this exists
En Croissant is a Tauri desktop app. Its 64 backend commands are registered via
tauri_specta::collect_commands!() and reachable only over Tauri's IPC bridge —
there is no CLI, HTTP API, or headless mode. (tauri_plugin_cli is registered,
but its config declares a single positional file arg: that's file-association
handling, not a scripting interface.)
It doesn't need one. Everything the app persists is in open formats:
~/Library/Application Support/org.encroissant.app/
db/<name>.db3 SQLite — Games, Players, Events, Sites, Info
db/<name>.pgn the PGN the database was imported from
db/<name>.ecsi proprietary position index (magic bytes "ECSI", v4)
engines/stockfish/ the UCI engine binary
~/Documents/EnCroissant/*.pgn repertoire files
~/Library/WebKit/org.encroissant.app/.../LocalStorage/localstorage.sqlite3
FSRS training state, keyed deck-<repertoire path>-<n>,
values UTF-16. Not in the PGN.So this project reads En Croissant's files, never its code. It is not a fork and has no upstream relationship.
Start with USAGE.md — what you can ask for and what's built yet. Design records (build order, test seams, domain vocabulary) live in docs/.
Developed against En Croissant 0.15.0. The app registers
tauri_plugin_updater and updates itself, and every format above is internal and
undocumented. Startup asserts the shapes we depend on so a format change fails
loudly instead of being misread.
The sidecar is not a live export. It's the file the database was imported
from, so the two can drift: the Lichess pair matches exactly (190/190), the
chess.com pair does not (3525 PGN events against a GameCount of 3521). Treat
equivalence as an invariant to check, never a property to rely on. Because of
this — and because a game played ten minutes ago isn't in it at all — recent
games come from the Lichess API and the sidecar is the bulk/offline fallback.
How repertoires and decks work
Read from En Croissant's own source rather than inferred by experiment.
Start header — [Start "[0,0,0]"] is a JSON array of child indices from the
tree root, written as JSON.stringify(game.start) and read as
JSON.parse(Start ?? "[]"). It marks where training begins, not where the file
begins: buildFromTree skips any node whose path is a prefix of start. The
Vienna file starts at [0,0,0], which is why its deck drills from move 3
(f4, e5, Nf3) and never asks for 1.e4 or 2.Nc3.
Deck key suffix — deck-${file}-${game}, where game is the index of the
game within the PGN file. -0 is the first game; a multi-game repertoire gets
one deck per game.
Cards are built eagerly, and adding lines is safe. On open, if the deck is
empty En Croissant builds cards for the whole tree. If the deck is non-empty it
calls syncDeck, which reconciles against the tree, reports added/removed
counts, and preserves existing cards and the review log. So writing new lines
into a repertoire and reopening it schedules the new positions without
disturbing existing scheduling. Logs are only wiped by the explicit Reset button.
A position's drilled answer is always its first child. buildFromTree uses
item.node.children[0].san and ignores the rest. Whatever move we write first at
a node is the move you'll be drilled on — variation order is semantic, not
cosmetic.
Cards are only created for positions where it's your turn (halfmove parity
against Orientation), leaf nodes are skipped, and positions are deduplicated by
full FEN with the first occurrence winning — so transpositions collapse to one
card.
Scope
Lichess only; chess.com is historical and opt-in. Blitz only by default, since that's the bulk of most players' game history.
Your own win rate is not a ranking signal anywhere. A typical two-year window holds only a few dozen blitz games per colour, which makes any per-position percentage noise. Ranking is on coverage instead: deterministic, and it needs no sample size.
What it deliberately does not do
Two things on disk are closed formats:
The move BLOB.
length(Moves)equalsPlyCountexactly — one byte per ply, an index into the generated legal moves for each position. Decoding it means reproducing En Croissant's move generator ordering byte-for-byte. Avoided entirely by reading the.pgnsidecar instead.The
.ecsiindex. Powers fast position search over large databases. No substitute here; brute-force PGN scanning covers the personal databases (130 KB and 7.6 MB) and the Lichess explorer API covers reference statistics.
Indexed search over a multi-gigabyte master database is the one capability this
project cannot reach. If that ever becomes a real need, it's a separate project
(extract the Rust search core from En Croissant as a [[bin]] target) — not a
requirement here.
What it does to your data
Read-only against
.db3. ThePawnHomecolumn and the.ecsiindex are derived; hand-written rows would desync them. To add games, write PGN and import through the GUI.Repertoire files under
~/Documents/EnCroissant/are the one place this project writes at all.
Development
uv sync
uv run pytestResources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseCqualityDmaintenanceAn MCP server that enables natural language interaction with the Lichess chess platform, allowing users to play games, analyze positions, manage their account, and participate in tournaments through Claude.902717MIT
- Alicense-qualityDmaintenanceA powerful chess engine and game server built with the Model Context Protocol (MCP). Play chess against AI, analyze positions, and integrate chess functionality into your AI applications.281ISC
- AlicenseAqualityBmaintenanceA hybrid AI chess coach MCP server that uses Stockfish for grounded evaluation and LLM for natural-language coaching, enabling game analysis, weakness diagnosis, and personalized drills from your own games.61MIT
- Alicense-qualityDmaintenanceBidirectional MCP server that connects Claude with an Obsidian vault, enabling note management, full-text search, graph traversal, and daily notes operations.3,697MIT
Related MCP Connectors
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
MCP server giving Claude AI access to 22+ NYC public-record databases for real estate due diligence
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/cheungbrenden/croissant-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server