Skip to main content
Glama

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.

Python MCP Stockfish License

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 --> coach

The 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 lesson

Personalized 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_move searches 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 target

Dropping 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+

  • uv

  • 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 sync

This installs three executable MCP servers:

.venv/bin/chessgraph-postgres-mcp
.venv/bin/chessgraph-neo4j-mcp
.venv/bin/chessgraph-stockfish-mcp

2. Configure local services

cp .env.template .env

Set 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:8000

CHESS_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.py

The 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_move

PostgreSQL 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 pytest

Optional live-service tests:

CHESSGRAPH_RUN_INTEGRATION=1 uv run pytest tests/test_integration.py

Inspect a server with the official MCP development tooling:

uv run mcp dev chess_mcp/stockfish/server.py

6. Run the retrieval API

uv run uvicorn backend.main:app --host 127.0.0.1 --port 8000

Fifteen routes serve the interface and the coaching reads:

Route

Purpose

GET /health

Liveness check

GET /api/player

Player summary: games, results, average ratings, date range

GET /api/recap

Rating-band recap: win rate, lines, clocks, results

GET /api/games

Filter games by player, type, outcome, ECO, and date

GET /api/games/{game_id}

One game's metadata and movetext

GET /api/games/{game_id}/moves

Paged moves, clocks, and stored evaluations

GET /api/lessons/openings

Opening lessons for a colour

GET /api/lessons/endgames

Endgame lessons for the player's rating tier

GET /api/coach/brief

Strengths, weakest target, calculation, four tasks

GET /api/coach/plan

The ranked training plan

GET /api/openings

Opening theory for an exact normalized position

GET /api/positions

Neo4j position context and outgoing moves

POST /api/engine/analyze

Bounded MultiPV analysis

POST /api/engine/compare

One played move against the best move, same root

POST /api/engine/validate

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 dev

Open 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 bundle

See ui/README.md for the interface structure and libraries.

MCP surface

Tool

Purpose

list_games

Filter games by player, type, outcome, ECO, and date

get_game

Retrieve one game's metadata and PGN movetext

get_game_moves

Page through ordered moves, FENs, clocks, and evaluations

get_player_summary

Aggregate results and ratings

get_blunders

Find the data owner's or a named player's evaluated mistakes

get_coaching_brief

Rank opening families by result and surface repeated mistakes

find_position_occurrences

Find games containing an exact normalized FEN

lookup_opening

Retrieve opening theory for a position

lookup_endgame_positions

Retrieve filtered endgame benchmarks

Resource: chessgraph://postgres/schema

Tool

Purpose

get_position_context

Retrieve a position with opening and endgame links

get_position_moves

Compare outgoing personal and theory moves

find_transpositions

Find bounded paths to convergent graph positions

get_game_blunders

Retrieve graph-linked mistakes for one game

get_recurring_blunder_positions

Rank repeated mistake positions

get_endgame_context

Retrieve endgame patterns and benchmark positions

Resource: chessgraph-neo4j://schema

Tool

Purpose

analyze_position

Run bounded depth, node, or time-based MultiPV analysis

compare_move

Compare a legal played move with the best move from one root

validate_line

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 reference

Data sources

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 tools
find_transpositionsC
Read-onlyIdempotent

Find bounded move paths from a position to convergent graph nodes.

NameRequiredDescriptionDefault
fenYes
limitNo
max_depthNo

Output Schema

NameRequiredDescription
pathsNo
fen_normYes
max_depthYes

TDQS

C2.7/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness2/5

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.

Parameters2/5

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.

Purpose3/5

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.

Usage Guidelines2/5

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_contextC
Read-onlyIdempotent

Get endgame classifications and bounded benchmark positions for a FEN.

NameRequiredDescriptionDefault
fenYes
limitNo

Output Schema

NameRequiredDescription
patternsNo
positionYes
benchmarksNo

TDQS

C2.9/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness2/5

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.

Parameters2/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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_blundersB
Read-onlyIdempotent

List recorded user blunders for one game in ply order.

NameRequiredDescriptionDefault
limitNo
game_idYes

Output Schema

NameRequiredDescription
game_idYes
blundersNo

TDQS

B3/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters2/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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_contextB
Read-onlyIdempotent

Get a normalized position with its opening and endgame classifications.

NameRequiredDescriptionDefault
fenYes

Output Schema

NameRequiredDescription
openingsNo
positionYes
endgame_patternsNo

TDQS

B3/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness3/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 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.

Parameters2/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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_movesC
Read-onlyIdempotent

List bounded played and theory moves leaving a normalized position.

NameRequiredDescriptionDefault
fenYes
limitNo

Output Schema

NameRequiredDescription
movesNo
fen_normYes

TDQS

C2.8/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters2/5

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.

Purpose3/5

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.

Usage Guidelines2/5

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_positionsC
Read-onlyIdempotent

Rank positions linked to blunders in multiple recorded events.

NameRequiredDescriptionDefault
limitNo
min_occurrencesNo

Output Schema

NameRequiredDescription
positionsNo
min_occurrencesYes

TDQS

C2.9/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness2/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 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.

Parameters2/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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.

  1. 6 tool updatesv0.1.0
    • First observedfind_transpositions
    • First observedget_endgame_context
    • First observedget_game_blunders
    • First observedget_position_context
    • First observedget_position_moves
    • First observedget_recurring_blunder_positions

TDQS

B3.3/5.0

Scored across 6 tools

Disambiguation4/5

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.

Naming Consistency5/5

All tool names use snake_case with a clear verb_noun pattern, mostly get_ and one find_. The naming is predictable and readable throughout.

Tool Count5/5

Six tools is well-scoped for a focused chess graph analysis server. Each tool covers a distinct analytical operation without obvious redundancy.

Completeness4/5

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

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables 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.
    34
    AGPL 3.0
  • 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
  • A
    license
    A
    quality
    B
    maintenance
    MCP 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.
    13
    31 npm
    AGPL 3.0