ChessGraph-MCP
Provides access to a positional graph knowledge base in Neo4j, with nodes for positions (FEN), edges for played moves ([:PLAYED]), and theory links ([:THEORY]), enabling GraphRAG-based chess analysis and semantic coaching.
Provides SQL access to chess game telemetry in PostgreSQL, including game type, ELO, results, ACPL, and blunder percentages, to support data-driven chess analysis.
Click on "Deploy 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., "@ChessGraph-MCPEvaluate 1.e4 e5 2.Nf3 and tell me if Nc6 is playable."
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.
ChessGraph MCP
A local layer for personalized chess coaching
Connect an MCP-capable agent to personal game history, a positional knowledge graph, and reproducible Stockfish analysis—without giving the model unrestricted database access.
Deterministic analysis · Personal evidence · Typed MCP tools · Read-only by design
Why ChessGraph?
A chess engine can calculate excellent moves, but it does not know your history. A database can reveal recurring mistakes, but it cannot calculate the best move in a new position. A language model can explain ideas, but it should not invent the chess evidence behind them.
ChessGraph MCP separates those responsibilities:
Stockfish calculates candidate moves, evaluations, WDL, and principal variations.
PostgreSQL remembers games, move telemetry, openings, endgames, and historical engine evaluations.
Neo4j connects positions, personal moves, theory moves, transpositions, games, and endgame patterns.
The retrieval API serves those same reads to the interface, without asking the model to fetch the page.
Hermes-Agent explains the combined evidence as a personalized lesson.
The design principle is simple: the engine searches, deterministic code validates, the databases provide context, and the model explains only the evidence it receives.
Related MCP server: Chess Engine MCP Server
Architecture
flowchart LR
subgraph sources [Data sources]
pgn["Chess.com PGN archives"]
openings["Lichess opening theory"]
endgames["Endgame Atlas benchmarks"]
end
subgraph ingestion [Deterministic ingestion]
normalizer["ETL and FEN normalization"]
backfill["Historical Stockfish backfill"]
graphSync["PostgreSQL to Neo4j sync"]
end
subgraph knowledge [Local evidence stores]
postgres[("PostgreSQL: games and telemetry")]
neo4j[("Neo4j: position graph")]
end
subgraph runtime [Read paths]
api["FastAPI retrieval"]
pgMcp["PostgreSQL MCP: 9 tools"]
graphMcp["Neo4j MCP: 6 tools"]
sfMcp["Stockfish MCP: 3 tools"]
stockfish["Stockfish UCI"]
end
ui["React coach"]
host["Hermes-Agent and frontier model"]
coach["Evidence-backed coaching response"]
pgn --> normalizer
openings --> normalizer
endgames --> normalizer
normalizer --> postgres
postgres -->|"unevaluated moves"| backfill
backfill -->|"scores and CPL"| postgres
postgres --> graphSync
graphSync --> neo4j
ui -->|"page facts"| api
ui -->|"questions"| host
api -->|"repository reads"| postgres
api -->|"repository reads"| neo4j
api -->|"bounded search"| stockfish
host -->|"typed MCP calls"| pgMcp
host -->|"typed MCP calls"| graphMcp
host -->|"typed MCP calls"| sfMcp
pgMcp -->|"parameterized reads"| postgres
graphMcp -->|"bounded traversals"| neo4j
sfMcp -->|"serialized UCI"| stockfish
host --> coachThe ETL layer writes data. The MCP servers and the retrieval API only read.
They call the same repositories in chess_mcp/. MCP tools stay typed and
bounded for Hermes. The API serves the facts the interface can draw before a
question is asked, such as the rating-band recap and the ranked training plan.
Hermes explains; it does not assemble the page.
What the agent can ask
Evidence source | Best suited for | MCP capabilities |
PostgreSQL | Game selection, longitudinal statistics, move records, openings, endgames, ranked coaching briefs | 9 curated tools, paginated move retrieval, statement timeouts |
Neo4j | Theory versus personal choices, transpositions, recurring positions, graph context | 6 curated tools, anchored queries, maximum traversal depth |
Stockfish | Fresh position analysis, candidate comparison, WDL, legal variations | MultiPV, same-root move comparison, line validation |
Examples:
“Show my largest rapid-game mistakes and explain the top three.”
“Where did I leave opening theory, and what did I usually play instead?”
“Do different move orders in my games transpose into this position?”
“Compare my move with Stockfish's best move using the same search budget.”
“Which opening family scores worst for me, and what should I drill first?”
“Which positions keep tempting me into the same wrong move?”
“Which endgame patterns recur in my losses?”
Evidence flow for a coaching answer
sequenceDiagram
actor User
participant Hermes as Hermes-Agent
participant PG as PostgreSQL MCP
participant Graph as Neo4j MCP
participant SF as Stockfish MCP
User->>Hermes: Why was this move a mistake?
Hermes->>PG: get_game_moves and get_blunders
PG-->>Hermes: FEN, played move, CPL, clock, game context
Hermes->>Graph: get_position_context and get_position_moves
Graph-->>Hermes: Theory, personal choices, recurring patterns
Hermes->>SF: compare_move from the same root
SF-->>Hermes: Best line, played line, score, WDL, provenance
Hermes->>SF: validate_line for any cited continuation
SF-->>Hermes: Legal UCI, SAN, and resulting FENs
Hermes-->>User: Verified explanation and actionable lessonPersonalized training
The training view is not a fixed lesson list. Both API endpoints behind it read the stored games and rank what to work on next.
GET /api/coach/brief returns the material a coach would open with:
the strongest opening families, by score in the stored games;
the target: the weakest opening family, with its wins, draws and losses;
calculation positions — repeated spots where the recorded move differs from
best_move_uci, ranked by frequency and average centipawn loss;the endgames field, which states plainly that endgame type is not stored on games rather than guessing one;
four tasks, each with a reason that quotes the stored record.
GET /api/coach/plan returns up to six ranked PlanItems. Each item carries a
kind (opening, defense, endgame or puzzle), the reason that justifies
it, a goal, a check_after_games review point, the line to drill, the player's
colour, and a ready flag.
A drill is only offered when it can actually be drilled: ready stays false
until the stored theory line for that family is at least MIN_DRILL_PLIES (6)
plies long, and the reason says how many plies it has. Drilled lines are capped
at TASK_PLIES (12). The interface shows the drill length next to the board, so
a short line is reported as short instead of silently passed off as a lesson.
Design guarantees
Read-only agent access
No arbitrary SQL or Cypher tools.
PostgreSQL uses parameterized statements, read-only transactions, local statement timeouts, and result caps.
Neo4j uses read transactions, parameterized values, indexed anchors, and a hard maximum path depth.
Database permissions remain the final security boundary; dedicated read-only accounts are recommended.
Reproducible engine evidence
Scores are normalized to the player at the root position.
Centipawn and mate scores remain distinct.
CPL is computed only when both comparable scores are centipawn scores.
compare_movesearches the best and played moves from the same root with the same requested budget.Principal variations are legally replayed in UCI and SAN.
Responses preserve engine identity, options, search limits, depth, nodes, and elapsed engine time when available.
Shared position identity
PostgreSQL and Neo4j use a four-field normalized FEN:
piece placement · side to move · castling rights · en-passant targetDropping move counters lets different move orders converge on the same position key. Stockfish receives a valid six-field FEN generated from that shared key.
Quick start
Prerequisites
Python 3.12+
Node.js 22+ and npm, for the React interface
PostgreSQL with the project schema and loaded data
Neo4j with the synchronized position graph
A local Stockfish binary
An MCP host such as Hermes-Agent
1. Install the project
uv syncThis installs three executable MCP servers:
.venv/bin/chessgraph-postgres-mcp
.venv/bin/chessgraph-neo4j-mcp
.venv/bin/chessgraph-stockfish-mcp2. Configure local services
cp .env.template .envSet the real values in .env:
POSTGRES_USER=chess_reader
POSTGRES_PASSWORD=change_me
POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=5432
POSTGRES_DB=chess
CHESS_USERNAME=your_chess_username
NEO4J_URI=bolt://127.0.0.1:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=change_me
NEO4J_DATABASE=neo4j
STOCKFISH_PATH=/usr/games/stockfish
HERMES_API_URL=http://127.0.0.1:8642/v1
HERMES_API_KEY=
BACKEND_URL=http://127.0.0.1:8000CHESS_USERNAME is the Chess.com account stored in the games. Keep the real
value in .env. Do not copy it into AGENTS.md or the Hermes seeds. Search
budgets and the other limits are documented in
.env.template.
Both stores must be reachable before the interface or the coaches are useful:
PostgreSQL on 5432 and Neo4j on 7687. If Neo4j is down the coach says the
graph evidence is missing instead of guessing at it.
3. Load data if needed
If PostgreSQL and Neo4j are already populated, skip this step. Otherwise,
create the schemas from etl/sql_files/ and run:
uv run python etl/postgres_db/postgres_load.py
uv run python etl/postgres_db/load_stockfish_eval.py
uv run python etl/neo4j_db/neo4j_load.pyThe loaders mutate or rebuild data; the MCP servers never invoke them.
4. Connect Hermes-Agent
Merge agent/hermes-mcp.example.yaml into
~/.hermes/config.yaml, then adjust its absolute executable paths.
Hermes registers tools with a server prefix. For example:
mcp_chess_postgres_get_blunders
mcp_chess_neo4j_get_position_moves
mcp_chess_stockfish_compare_movePostgreSQL and Neo4j may serve parallel reads. Stockfish parallel calls remain disabled because one persistent UCI process is deliberately serialized.
Copy the identity seeds before the first coaching session. Hermes loads
SOUL.md only from $HERMES_HOME, and memory only from
$HERMES_HOME/memories/. See agent/README.md.
The coach panel calls Hermes through a Vite proxy. Set HERMES_API_URL and
HERMES_API_KEY from .env.template. HERMES_API_KEY must
match API_SERVER_KEY in ~/.hermes/.env. The Vite dev and preview servers
add the bearer header and strip the browser's Origin and Referer headers, so
the key stays on the server side and the gateway's origin guard does not reject
the request. Do not expose the key as a VITE_ variable.
5. Verify
uv run pytestOptional live-service tests:
CHESSGRAPH_RUN_INTEGRATION=1 uv run pytest tests/test_integration.pyInspect a server with the official MCP development tooling:
uv run mcp dev chess_mcp/stockfish/server.py6. Run the retrieval API
uv run uvicorn backend.main:app --host 127.0.0.1 --port 8000Fifteen routes serve the interface and the coaching reads:
Route | Purpose |
| Liveness check |
| Player summary: games, results, average ratings, date range |
| Rating-band recap: win rate, lines, clocks, results |
| Filter games by player, type, outcome, ECO, and date |
| One game's metadata and movetext |
| Paged moves, clocks, and stored evaluations |
| Opening lessons for a colour |
| Endgame lessons for the player's rating tier |
| Strengths, weakest target, calculation, four tasks |
| The ranked training plan |
| Opening theory for an exact normalized position |
| Neo4j position context and outgoing moves |
| Bounded MultiPV analysis |
| One played move against the best move, same root |
| Replay a UCI line into legal SAN and FENs |
The UI proxies /api to BACKEND_URL. See backend/README.md.
The Stockfish routes start their own engine on first use. Hermes continues to use
the separate engine inside the Stockfish MCP server.
7. Run the UI
cd ui
npm install
npm run devOpen http://127.0.0.1:5173. The app has three modes:
Home — the default view. A rating-band recap counted from PostgreSQL through
GET /api/recap. Pick a band and the charts recompute; each card opens into the chart and table behind it. The favourite line in a band is the stored opening name with the most games, so a line that was played can still rank behind a larger one.Training — the ranked plan from
GET /api/coach/plan, drilled on the board with a hint drawn from your own stored move, and the live coach beside it.My games — stored games grouped by time control, with the review jumping to a game's recorded key moment.
Every panel is a live read: the recap, games, lessons, coaching brief, plan, and position analysis all come from the retrieval API, and the coach answers through the Hermes gateway. There is no sample data in the interface.
Other UI commands:
cd ui
npm test # clock rules, statistics, plan ranking, and coach transport
npm run lint # oxlint
npm run build # type-check and production bundle
npm run preview # serve the production bundleSee ui/README.md for the interface structure and libraries.
MCP surface
Tool | Purpose |
| Filter games by player, type, outcome, ECO, and date |
| Retrieve one game's metadata and PGN movetext |
| Page through ordered moves, FENs, clocks, and evaluations |
| Aggregate results and ratings |
| Find the data owner's or a named player's evaluated mistakes |
| Rank opening families by result and surface repeated mistakes |
| Find games containing an exact normalized FEN |
| Retrieve opening theory for a position |
| Retrieve filtered endgame benchmarks |
Resource: chessgraph://postgres/schema
Tool | Purpose |
| Retrieve a position with opening and endgame links |
| Compare outgoing personal and theory moves |
| Find bounded paths to convergent graph positions |
| Retrieve graph-linked mistakes for one game |
| Rank repeated mistake positions |
| Retrieve endgame patterns and benchmark positions |
Resource: chessgraph-neo4j://schema
Tool | Purpose |
| Run bounded depth, node, or time-based MultiPV analysis |
| Compare a legal played move with the best move from one root |
| Replay UCI moves and return legal SAN/FEN evidence |
Resource: chessgraph-stockfish://capabilities
See docs/mcp.md and the package-specific READMEs under
chess_mcp/ for contracts, semantics, and extension guidance.
Project structure
ChessGraph-MCP/
├── chess_mcp/ modular MCP package
│ ├── postgres/ relational repositories, recap, training plan, server
│ ├── neo4j/ graph repositories, models, server
│ └── stockfish/ UCI lifecycle, scoring, models, server
├── etl/
│ ├── postgres_db/ game, theory, and engine-evaluation loaders
│ ├── neo4j_db/ graph synchronization
│ └── sql_files/ PostgreSQL schema
├── backend/ FastAPI reads for the UI
├── ui/ React coach, all panels reading the API
│ └── src/
│ ├── views/ Home, Training, and My games
│ ├── data/ API-backed reads plus name and type helpers
│ ├── lib/ chess rules, clocks, evaluations, graph, stats
│ ├── components/ board, coach panel, eval bar, cards
│ └── services/ coach transport and engine calls
├── agent/ Hermes persona, memory seeds, MCP config example
├── docs/ operations and MCP reference
├── tests/ unit and opt-in integration tests
├── CHESS.md chess-domain reference
└── STOCKFISH.md engine and NNUE referenceData sources
Personal PGN archives exported from Chess.com
Dataset licenses and terms remain those of their respective publishers. Personal game records may contain usernames and should be treated as private data.
Current scope
ChessGraph MCP is a local evidence layer, not a complete coaching application. It currently provides:
local stdio MCP transport for Hermes;
a FastAPI retrieval process for the interface, using the same repositories;
read-only runtime tools, with no arbitrary query surface;
existing-data analysis over the loaded games;
ranked coaching briefs and a training plan derived from those games;
deterministic validation and typed evidence;
a local React interface for Home, Training, and game review, reading the API rather than carrying sample data.
Committed Hermes seeds live in agent/ (SOUL.md, MEMORY.md,
USER.md). Project instructions live in AGENTS.md. The coach
panel calls Hermes through the Vite proxy and answers from the MCP evidence.
Not yet built: persisting lessons or drilling history back into the stores, running the retrieval API as a remote HTTP or OAuth service, and automatically verifying every natural-language strategic claim the model produces. The training plan ranks what to work on next; it does not yet record whether a drill was completed.
Documentation
License
Released under the MIT License.
Available Tools
6 toolsfind_transpositionsCRead-onlyIdempotent
Find bounded move paths from a position to convergent graph nodes.
| Name | Required | Description | Default |
|---|---|---|---|
| fen | Yes | ||
| limit | No | ||
| max_depth | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| paths | No | |
| fen_norm | Yes | |
| max_depth | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a read-only, idempotent, non-destructive, closed-world operation. The description adds only that the search is "bounded" and targets convergent nodes, without explaining how depth limits, result limits, or convergence affect behavior; with annotations covering safety, this is adequate but thin.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no wasted clauses. Its brevity is efficient, though the jargon makes it slightly less clear than it could be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a complex graph-search tool with an output schema and robust annotations, but the description does not explain the search behavior, how the parameters shape it, or what a "convergent graph node" means. For a tool with three entirely undocumented parameters, the description is too incomplete to guide reliable invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for all three parameters. It vaguely implies a starting position and a bounded search, but does not explain fen, limit, or max_depth, leaving their semantics entirely undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a verb and resource ("Find bounded move paths") and hints at transpositions via "convergent graph nodes," but the phrasing is jargon-heavy and does not explicitly say this is a chess transposition search. It does not distinguish the purpose from siblings like get_position_moves or get_position_context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no when-to-use guidance, no exclusions, and no mention of when an agent should choose this tool over the sibling tools. The agent is left to infer the appropriate context from the tool name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_endgame_contextCRead-onlyIdempotent
Get endgame classifications and bounded benchmark positions for a FEN.
| Name | Required | Description | Default |
|---|---|---|---|
| fen | Yes | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| patterns | No | |
| position | Yes | |
| benchmarks | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/closed-world, so the safety profile is covered. The description adds a little context ('bounded benchmark positions') but never explains what 'bounded' means, how many positions are returned, or how the limit interacts with it. Not contradictory, just thin beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler, which is the right shape for a tool definition. It is terse to the point of underspecification, but nothing in it wastes the reader's time.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema and rich annotations exist, so return shape and safety need not be restated. Still, the description omits the 'limit' semantics and any differentiation from get_position_context, which are the two things the structured fields cannot supply.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across two parameters, so the description carries the full burden. It mentions the FEN implicitly ('for a FEN') but says nothing about 'limit' — neither its unit nor what is being limited — leaving an agent to guess the default/ceiling semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Get') and two concrete resources ('endgame classifications' and 'bounded benchmark positions') scoped by a FEN, which is meaningfully more specific than a generic 'get context'. However it never contrasts itself with the sibling get_position_context, so an agent must guess which one to call for a given position.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No indication of when to use this versus get_position_context or get_position_moves, and no prerequisites or exclusions are given. The only implicit cue is the word 'endgame', which the agent must infer as the selecting condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_game_blundersBRead-onlyIdempotent
List recorded user blunders for one game in ply order.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| game_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| game_id | Yes | |
| blunders | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, closed-world, so the safety profile is covered. The description adds the useful ordering guarantee ('ply order') and the 'recorded user blunders' scope, but says nothing about how the limit truncates results or whether missing blunders produce an empty list.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. It is efficient, though arguably undersized for two undocumented parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return values needn't be explained, and this is a simple read operation whose safety is covered by annotations. Still, the limit semantics and any relationship to the recurring-blunder sibling are left unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate and does not. It implies game_id via 'for one game' but never explains the limit parameter, its default of 100, or whether it is a cap on returned blunders.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (recorded user blunders for one game), plus an ordering (ply order). It implicitly distinguishes itself from get_recurring_blunder_positions by scoping to one game, but never names the sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use, when-not-to-use, or alternative tool guidance. The agent must infer from siblings that this is the per-game variant versus the recurring-position variant, with nothing in the description to confirm that routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_position_contextBRead-onlyIdempotent
Get a normalized position with its opening and endgame classifications.
| Name | Required | Description | Default |
|---|---|---|---|
| fen | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| openings | No | |
| position | Yes | |
| endgame_patterns | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent and non-destructive, so the safety profile is covered. The description adds the notion of 'normalized' output and classification results, but never explains what normalization entails or what the classifications represent, leaving behavioral gaps modest.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single efficient sentence with the core action front-loaded and no filler. It is terse to the point of omitting useful detail, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 are largely covered. However, with an undocumented required parameter and no differentiation from the overlapping endgame sibling, the definition is only minimally sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is one parameter ('fen') with 0% schema description coverage, and the description never mentions it or clarifies that it expects a FEN string. The single-parameter shape keeps this from being worse, but the description fails to compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('Get a normalized position') and adds that it returns opening and endgame classifications, which distinguishes it from pure-move tools like get_position_moves. It does not, however, differentiate itself from the overlapping get_endgame_context sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No indication of when to choose this over get_endgame_context or find_transpositions, and no prerequisites or exclusions are stated. The agent must infer routing from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_position_movesCRead-onlyIdempotent
List bounded played and theory moves leaving a normalized position.
| Name | Required | Description | Default |
|---|---|---|---|
| fen | Yes | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| moves | No | |
| fen_norm | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive, closed-world), so the bar is lower. The description does add real behavioral content by disclosing that results mix 'played' (database) and 'theory' (book) moves and that output is bounded, but it says nothing about ordering, deduplication, or what happens when no moves exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; nothing is redundant. The terseness comes at the cost of clarity, but there is no wasted text to trim.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple (one required param) and has an output schema plus rich annotations, which covers return values and safety. Still, the description leaves essential ambiguity about FEN input format and the played-vs-theory distinction, which materially affect interpretation of results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the load, but it never explains what 'fen' expects or what 'limit' bounds in practice. 'Bounded' is the only nod to the limit parameter, and 'normalized position' only hints at FEN normalization — both too vague to compensate for the undocumented schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (list) and a resource (moves) tied to a position, which distinguishes it from siblings like get_position_context or find_transpositions. However, the key qualifiers 'bounded', 'played and theory', and 'normalized position' are unexplained jargon, so an agent cannot confidently say what a returned move actually is.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to call this versus find_transpositions (which presumably also works from a position) or get_position_context. No prerequisites or exclusions are given; the agent must infer usage from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recurring_blunder_positionsCRead-onlyIdempotent
Rank positions linked to blunders in multiple recorded events.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| min_occurrences | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| positions | No | |
| min_occurrences | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and closed-world, so safety is covered. The description adds that results are ranked by recurrence across multiple events, but it does not say what the ranking key is (count, win rate, evaluation swing) or how ties are broken. That is meaningful added context, but thinner than it could be for a ranking tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the resource and scope come before anything else. Its brevity is efficient, though it shades into under-specification rather than crispness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 not be explained, but the description still omits the two undocumented parameters and any guidance on interpreting the ranking. For a ranking/aggregation tool with 0% schema coverage, the definition is too thin to call confidently.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for both parameters: neither 'limit' nor 'min_occurrences' is documented in the schema, and the description does not compensate. "Multiple recorded events" loosely gestures at min_occurrences (default 2), but nothing explains that limit caps returned rows or what units either value uses.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ("rank") and resource ("positions linked to blunders") with a scoping qualifier ("in multiple recorded events"). This implicitly separates it from get_game_blunders, which presumably works within a single game, but no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to reach for this tool versus get_game_blunders, get_position_context, or get_position_moves, and no prerequisites or exclusions. The phrase "multiple recorded events" hints at cross-event aggregation but leaves the agent to infer the selection rule.
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.
6 tool updates
v0.1.0- First observed
find_transpositions - First observed
get_endgame_context - First observed
get_game_blunders - First observed
get_position_context - First observed
get_position_moves - First observed
get_recurring_blunder_positions
TDQS
Scored across 6 tools
Most tools have clearly distinct purposes: position context, moves, transpositions, per-game blunders, recurring blunder positions, and endgame context. There is some overlap between get_position_context and get_endgame_context because both involve endgame classifications, and get_position_moves vs find_transpositions both concern moves from a position, but the distinctions are manageable.
All tool names use snake_case with a clear verb_noun pattern, mostly get_ and one find_. The naming is predictable and readable throughout.
Six tools is well-scoped for a focused chess graph analysis server. Each tool covers a distinct analytical operation without obvious redundancy.
The surface covers core read-only analytics: position context, moves, transpositions, blunders, recurring blunders, and endgame context. Minor gaps may exist around discovering game IDs or broader search/listing operations, but core workflows appear covered.
Maintenance
Related MCP Connectors
Pedagogical chess intelligence for AI agents: explain positions and games for a target Elo.
Stockfish chess eval: best move, score, principal variation, multipv. $0.005/call via x402.
Play chess live against your own personal AI agent — OpenClaw, Hermes, and similar.
Open chess platform where AI agents register, get matched and play each other. Referee only.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables comprehensive chess analysis through Stockfish engine integration, positional evaluation, puzzle training, game review, and access to extensive chess databases. Provides visual board rendering, interactive game viewers, and tactical puzzle training with 3+ million problems from Lichess.34AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceEnables 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 npm2MIT
- AlicenseAqualityDmaintenanceA 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.64MIT
- AlicenseAqualityBmaintenanceMCP chess runtime that lets LLMs play, analyze, and adapt strength by exposing Stockfish, human move likelihood (Maia3), and Lichess statistics, with the LLM handling strategy and the server handling computation.1331 npmAGPL 3.0