Skip to main content
Glama
prepaser

llm-chess-mcp

by prepaser

llm-chess-mcp

An MCP chess runtime that lets LLMs play, analyze, and adapt their strength without outsourcing every decision to an engine.

Rather than returning a single best move, it exposes objective strength (Stockfish and Lc0), human move likelihood (Maia3), and real-game statistics (Lichess) so the LLM can choose how it wants to play. The LLM does the strategy and judgment; the MCP server handles all the computation.

Engines

Engine

Role

Runtime

Stockfish 18 (WASM)

Objective evaluation, best moves, multipv

In-process (npm stockfish)

Lc0 (native)

Independent neural-network search and candidate ranking

Bundled child process, CPU by default

Maia3 5M (ONNX)

Human-like move probabilities conditioned on Elo

Dedicated Node child processes (onnxruntime-node)

Lichess explorer

Real human game statistics

HTTP (needs token)

No separately installed engine executable or Python runtime is required for the bundled CPU engines on supported platforms. Stockfish runs in the server process; Lc0 and Maia inference run in dedicated child processes. Lc0 CPU bundles target Linux x64 (glibc >= 2.35) and Windows x64. The published package bundles the Maia3 5M model; other export variants are not runtime options unless their ONNX files are provided separately.

Analysis modes

Analysis defaults to both. Set ENGINE_MODE=stockfish or ENGINE_MODE=lc0 for a server-wide default, or pass engine_mode to analysis, move evaluation, and candidate tools. A request overrides the environment, which overrides the packaged default. Single-engine requests never initialize or check the other engine and never silently switch engines on failure.

Results identify each engine as ok, error, or not_requested. When one engine fails in both mode, the successful result is returned with partial: true. Both failing is an error. Cancellation stops the whole request. Scores, WDL, principal variations, and move classifications remain engine-local; centipawn values from different engines are never averaged. Move classification uses the existing CP-loss heuristic within each engine, not a calibrated cross-engine measure of move quality.

Candidate consensus uses equal-weight reciprocal rank fusion: sum(1 / (60 + rank)) / successfulEngineCount. An unranked move contributes zero without being labeled bad. Within each engine, tied intent scores retain the engine's original ranking. Consensus ties prefer more supporting engines, then UCI order. This is a ranking score, not a probability. natural remains Maia-only; ease_off and give_chance require every successful engine to approve the candidate using available WDL data.

Stockfish retains depth-based limits. Lc0 uses movetime_ms, with default fast/normal/deep budgets of 1000/3000/10000 ms. Reported depths and node counts are not comparable between engines. Full game history is passed when available; FEN-only games have no inferred real history.

Related MCP server: Chess MCP

Build from source

The published runtime supports Node.js 20.3 and newer. Repository maintenance uses Node.js 22.13 or newer because pnpm 11 and the coverage gate require it.

pnpm install
pnpm build
pnpm test

pnpm test:unit runs the unit suite. pnpm test:e2e builds first, then runs the MCP transport tests. pnpm check runs the full local gate; use pnpm release:check before publishing.

Transports

stdio remains the default transport and requires no flags. To expose a local Streamable HTTP endpoint instead:

pnpm build
node dist/index.js --transport http

The server listens on http://127.0.0.1:3000/mcp and supports Streamable HTTP sessions, JSON responses, and SSE. The equivalent development command is pnpm dev:http.

HTTP options:

--host <host>            Bind host (default: 127.0.0.1)
--port <port>            Listen port (default: 3000)
--path <path>            Endpoint path (default: /mcp)
--allowed-host <host>    Allowed Host/Origin hostname; repeat as needed

The package also exposes a typed ESM API:

import { serveHttp } from "llm-chess-mcp";

const server = await serveHttp({ port: 3000, bodyTimeoutMs: 15_000 });
await server.close();

The root API also exports buildServer, GameStore, ChessError, ExplorerError, the service/domain types needed to provide custom AppServices, and safe chess helpers including parseImportedPgn, pgnOf, and snapshotChess. The package root is the supported public API. Deep imports under dist/ are intentionally not exported and will fail with ERR_PACKAGE_PATH_NOT_EXPORTED; use named root exports instead. This removes the previous dist/* compatibility exports and is a breaking change for integrations that imported internal modules.

bodyTimeoutMs limits HTTP body upload time; it is not a whole-tool deadline. The deprecated requestTimeoutMs alias remains supported when bodyTimeoutMs is omitted.

Binding to 0.0.0.0 or :: requires at least one --allowed-host. HTTP mode does not provide authentication or TLS; use a trusted network or an authenticated reverse proxy when exposing it beyond localhost. Origin values are validated when present, but the server does not emit browser CORS headers.

Lichess token (optional)

The opening explorer now requires authentication. Generate a personal access token at https://lichess.org/account/oauth/token/create and set it in .env:

cp .env.example .env
# set LICHESS_TOKEN=...

Without a token, opening_explorer returns a disabled notice; all other tools work.

Explorer filters are strict. Speeds are ultraBullet, bullet, blitz, rapid, classical, and correspondence; rating buckets are 0, 1000, 1200, 1400, 1600, 1800, 2000, 2200, and 2500. masters accepts neither filter. Invalid filters fail locally. Transient failures (network, timeout, 429, and 5xx) are retried once within a 12-second total budget; invalid requests and other 4xx responses are not retried. Responses must be valid UTF-8 JSON and are limited to 1 MiB, 256 moves, and 256 characters per move or opening string.

Configure in your MCP client

opencode

Add to opencode.json (project) or ~/.config/opencode/opencode.json (global):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "llm-chess-mcp": {
      "type": "local",
      "command": ["npx", "-y", "llm-chess-mcp"],
      "enabled": true,
      "environment": {
        "LICHESS_TOKEN": "your-token"
      }
    }
  }
}

Claude Code

Add to .mcp.json (project) or ~/.claude.json (global), or run:

claude mcp add llm-chess-mcp -- npx -y llm-chess-mcp
{
  "mcpServers": {
    "llm-chess-mcp": {
      "command": "npx",
      "args": ["-y", "llm-chess-mcp"],
      "env": {
        "LICHESS_TOKEN": "your-token"
      }
    }
  }
}

Codex CLI

Add to ~/.codex/config.toml:

[mcp_servers.llm-chess-mcp]
command = "npx"
args = ["-y", "llm-chess-mcp"]

[mcp_servers.llm-chess-mcp.env]
LICHESS_TOKEN = "your-token"

Or via the CLI:

codex mcp add llm-chess-mcp --command npx --args -y llm-chess-mcp --env LICHESS_TOKEN=your-token

Tools

Tool

Description

create_game

Create a game (optionally from a FEN), returns game_id

delete_game

Delete a process-shared game and free game capacity

game_state

Authoritative state: FEN, turn, revision, check/mate/draw flags, history, last move, castling (optional ASCII)

game_play_move

Play a move (SAN or UCI) — the only mutating tool, with stale-position guard

game_legal_moves

All legal moves with metadata

game_pgn

Export the game as PGN

game_import_pgn

Import a PGN into a new game

position_analyze

Per-engine MultiPV lines (cp/mate/WDL + UCI/SAN PV), consensus ranking, and analysis_level preset

human_move_distribution

Maia3 human-move probabilities at a target Elo

move_evaluate

Score one or more moves + cpLoss + classification

move_candidates

Primary tool: unified candidates (objective + human + opening)

move_candidates_by_intent

Convenience layer: candidates ranked for a strategic intent

opening_explorer

Lichess human game statistics

Result format

structuredContent is the canonical successful result. Handler-level failures set isError and provide structuredContent.error. Input-schema failures are generated by the MCP SDK before the handler and use its standard isError text result without structuredContent. Otherwise, content is only a short human-readable summary and must not be parsed as data.

Score conventions

  • Engine analysis scores are side-to-move perspective: positive cp = side to move is better; mate N = side to move mates in N. wdl is [win, draw, loss] in permille for the side to move.

  • move_candidates gives per-engine objective.byEngine values with moverCp (the mover's perspective — higher is better for the player choosing the move) and whiteCp (fixed white perspective) so the sign never flips on you.

  • move_evaluate reports the score from the mover's perspective, plus cpLoss (centipawns lost vs the best move) and a classification: best / excellent / good / inaccuracy / mistake / blunder.

  • maia3Prob is a human-likelihood, not move quality. A high-probability move can still be objectively bad.

  • Successful analysis continuations return corresponding pv and pvSan arrays of equal length in UCI and SAN. An invalid engine continuation is rejected at the internal tool boundary instead of returning a truncated pvSan.

Candidate structure

move_candidates returns each candidate with three independent facets:

{
  "uci": "g1f3",
  "san": "Nf3",
  "objective": {
    "byEngine": {
      "stockfish": { "rank": 1, "moverCp": 55, "whiteCp": 55, "cpLoss": 0, "moverMate": null, "whiteMate": null, "wdl": [153, 844, 3] },
      "lc0": { "rank": 1, "moverCp": 45, "whiteCp": 45, "cpLoss": 0, "moverMate": null, "whiteMate": null, "wdl": [200, 750, 50] }
    }
  },
  "consensusRank": 1,
  "consensusScore": 0.01639344262295082,
  "support": 2,
  "human": { "maia3Prob": 0.62, "selfElo": 1500, "opponentElo": 1500 },
  "opening": { "status": "available", "games": 18421, "frequency": 0.31, "white": 9000, "draws": 3000, "black": 6421, "averageRating": 1800 }
}
  • objective.byEngine — independent Stockfish and Lc0 evaluations; an engine's entry is null when it did not evaluate that candidate. moverCp is from the mover's perspective (higher = better for the chooser).

  • human — Maia3 conditional probability at a target Elo.

  • opening — Lichess empirical frequency (a different signal from Maia3).

opening.status is available, no_data (API ok but no games in this position), unavailable (timeout/429/401), or disabled (no token). Explorer failure does not discard successful engine or Maia3 results. The selected engine mode controls which engines run. In both mode, one engine failure yields partial: true; both failing produces a tool error. Top-level engines records each outcome and enginesUsed lists successful engines.

move_candidates also returns moveSensitivity, describing how sharply the evaluation changes across the top engine lines:

{
  "moveSensitivity": {
    "stockfish": { "level": "high", "topMoveSpreadCp": 245 },
    "lc0": { "level": "medium", "topMoveSpreadCp": 120 }
  }
}

level is low (<80cp spread), medium (80–200cp), or high (≥200cp). High sensitivity means choosing among plausible alternatives can materially change the evaluation — useful for deciding whether to ease off or play precisely. An unavailable or unrequested engine has null sensitivity. The two engines' centipawn scales are independent and should not be compared directly.

Analysis levels

Position and candidate tools accept an analysis_level preset:

Level

Stockfish depth

MultiPV

Lc0 time (ms)

fast

8

5

1000

normal

15

8

3000

deep

22

10

10000

Position analysis accepts depth/multipv overrides; candidate tools use sf_depth/sf_multipv. movetime_ms overrides the Lc0 budget in either tool. move_evaluate defaults to depth 15 and 3000 ms and accepts explicit overrides.

Stale-position guard

Every state read returns a revision. game_play_move requires expected_revision; if the game has advanced since your last read, the move is rejected:

{ "error": { "code": "STALE_POSITION", "message": "position changed: expected revision 2, current 3" } }

Runtime limits

  • Up to 1,000 games are retained per process; idle games expire after one hour.

  • move_evaluate accepts at most 10 moves per call.

  • Imported and exported PGNs are limited to 1 MiB, 256 headers, and 4,096 plies; stored snapshots enforce the same byte, header, token, and ply resource bounds. Imports also cap the mainline and variations together at 32,768 structural elements and 16 KiB per lexical token. Every variation is legality-checked; game state retains the mainline. UTF-8 BOMs and standard escaped header values are supported.

  • Custom FENs reject inconsistent castling/en-passant metadata and impossible pawn or promotion material.

  • Stockfish and Lc0 each accept up to 32 active or queued analyses. Maia runs at most two inferences concurrently and queues up to 32 more.

  • Lichess Explorer requests run one at a time and share 429 cooldowns.

  • HTTP retains at most 64 MCP sessions; sessions with no active request expire after 30 minutes. An open GET/SSE stream keeps its session active.

  • HTTP accepts bodies up to 2 MiB under normal body-parser capacity. Once those parsers are full, an overflow request receives only a small, up-to-8 KiB probe; only a complete MCP cancellation notification can proceed, and no accepted parser is preempted. The listener's connection limit bounds overflow probes. After body parsing, it permits 16 concurrent POST dispatches and downstream compute/network jobs process-wide, with two of each per session. A separate bounded control lane prioritizes MCP cancellation when normal dispatch capacity is full. If an existing-session POST response closes before it finishes, its session is closed and its work is aborted; an uncooperative downstream operation still holds capacity until it settles. HTTP also caps connections at 128 and applies a 15-second body upload deadline plus bounded header, socket, and keep-alive timeouts.

Programmatic users can override the HTTP limits through HttpServerOptions. These safeguards do not replace public-edge quotas: a public deployment must still enforce request, connection, and authentication limits at the reverse proxy.

MCP cancellation notifications, session deletion, and server shutdown propagate to body uploads and Stockfish, Lc0, Maia, and Lichess work. Stockfish stops safely at its UCI queue boundary, drains queued work during shutdown, and rejects new analysis until teardown completes. Lc0 rejects active and queued work on shutdown and waits for its process to exit, escalating termination when necessary. Lichess fetch and retry waits abort immediately. Maia runs native inference in dedicated child processes; cancelling active work terminates its child, while queued cancellation is immediate. A raw response disconnect for an existing-session POST closes that session and aborts its work. Reconnect with a new session, then re-read the process-shared game state before retrying a move.

Intents

move_candidates_by_intent ranks candidates for a chosen intent. It is a convenience layer over move_candidates; the fixed thresholds below are heuristic defaults, not the source of truth:

Intent

Meaning

best

Strongest engine move

strong

Engine-strong but human-plausible

natural

Most human-typical at the target Elo

balanced

Blend of strength and human-likeness

ease_off

Human-plausible moves that modestly reduce advantage without changing the expected result

give_chance

Human-plausible inaccuracies that meaningfully improve the opponent's chances

This tool ranks candidates but does not choose a move. Use the returned signals and conversation context to make the final decision — do not map user skill mechanically to an intent.

Example flow

The normal play loop is three calls:

  1. create_gamegame_id

  2. move_candidates → pick a move

  3. game_play_move (with expected_revision) → commit it

Go deeper only when you need to:

  • position_analyze — objective best lines

  • human_move_distribution — what a human of a given Elo would play

  • opening_explorer — real-game statistics

  • move_evaluate — score a specific move (or compare several)

Export Maia3 to ONNX

The publisher chooses the model in model.config.json. The export step needs Python + PyTorch once; it downloads the pinned checkpoint, verifies the reimplementation against the original, and writes the verified ONNX bundle to models/.

uv venv .venv-maia3 --python 3.13
uv pip install --python .venv-maia3/bin/python -r scripts/requirements.txt
uv pip install --python .venv-maia3/bin/python "maia3 @ git+https://github.com/CSSLab/maia3.git@1e13597c42d4858b7cfd7cfdae01e297263364b2"
.venv-maia3/bin/python scripts/export_maia3.py --device cpu

The default --config is the repository's model.config.json; pass another config path to export a different supported Maia3 variant. The generated models/manifest.json records the source, checkpoint digest, model filename, and artifact digests. Run pnpm model:check before packaging to verify that the manifest still matches the config and files.

The default config selects the current pinned 5M checkpoint:

{
  "schemaVersion": 3,
  "analysis": { "mode": "both" },
  "maia3": {
    "model": "5m",
    "source": {
      "type": "huggingface",
      "repoId": "UofTCSSLab/Maia3-5M",
      "filename": "maia3-5m.pt",
      "revision": "b6559de2398d7140b985f28fd2c19fb5e47ddabe"
    }
  },
  "stockfish": {
    "version": "18.0.8",
    "flavor": "lite-single"
  },
  "lc0": {
    "version": "0.32.1",
    "weights": {
      "url": "https://storage.lczero.org/files/networks-contrib/t1-256x10-distilled-swa-2432500.pb.gz",
      "sha256": "bc27a6cae8ad36f2b9a80a6ad9dabb0d6fda25b1e7f481a79bc359e14f563406"
    },
    "backend": "cpu",
    "platforms": ["linux-x64", "win32-x64"]
  }
}

Supported architectures are 3m, 5m, 23m, and 79m; the source checkpoint must match the selected architecture. Hugging Face revisions must be full lowercase commit SHAs. For local weights, replace maia3.source with {"type": "local", "path": "weights/checkpoint.pt"}. Relative checkpoint paths resolve against the config file, not the working directory. Absolute local checkpoint paths are also accepted; prefer relative paths for portable configs. --cache-dir optionally controls the Hugging Face download cache.

Model/source selection now uses the config file instead of the old --model and --checkpoint flags. Export always verifies before replacing the bundle; there is no --skip-verify or custom --out. pnpm export:maia3 is equivalent when the required Python environment is active.

The workflow is: edit the root config, export, run pnpm check, then run pnpm test:package. Exporting with another config does not change the root config; make them agree before packaging. Any unlisted files left over after switching models must be removed or moved out of models/ explicitly; checks report them and never delete them automatically.

Normal pnpm build only compiles TypeScript. npm includes the generated models/ alongside dist/, not the Python scripts, source checkpoint, or build config. Consumers do not download weights from Hugging Face at install or runtime. With MAIA3_MODEL unset, the bundled manifest chooses the default; an explicit supported key retains package-then-working-directory model lookup.

Exporter regression tests run separately from the Python-free Node checks:

.venv-maia3/bin/python -m unittest discover -s scripts -p 'test_model_*.py'

Maia3 ONNX verification

The exported ONNX model is regression-tested against the upstream Maia3 implementation across fixed positions and Elo pairs:

.venv-maia3/bin/python scripts/verify_maia3.py --config model.config.json

Use --onnx path/to/model.onnx to verify a specific ONNX artifact. Without it, verification reads the model filename from the generated manifest.

It checks top-1/top-k move agreement and max probability error to detect export/runtime regressions. The bundled maia3-5m.onnx passes with 100% top-1 and top-5 agreement and max probability error < 1e-4.

Configure Stockfish

The same model.config.json selects the exact npm stockfish version and default engine flavor. 18.0.8 is the npm package version; it contains the Stockfish 18 engine. Version ranges, tags, and prereleases are not accepted. Supported flavors are full, single, lite, lite-single, single-lite (an alias), and asm.

After editing the stockfish section:

pnpm stockfish:prepare
pnpm check
pnpm test:package

Preparation uses pnpm to pin and install the exact dependency and update the lockfile, compiles TypeScript, then checks initialization, UCI readiness, analysis, and shutdown using the configured flavor. Only after successful verification is the default flavor recorded in package.json. An incompatible version fails preparation; older loader APIs are not automatically adapted. If preparation fails, dependency files may already have changed. Correct the configuration or compatibility error and rerun it; Git changes are never automatically reverted.

Runtime selection is an explicit engine option, then STOCKFISH_FLAVOR, then the packaged default. The real loader rejects an installed package version that differs from the pinned dependency. Consumers receive Stockfish as an exact npm dependency; the running server never installs or switches versions.

pnpm model:check checks both engines without downloading or installing anything. Stockfish-only changes do not require Maia export: its manifest continues to record only normalized Maia settings. Schema version 1 build configs must be updated to the unified format above. Ordinary builds do not install engines. External NNUE replacement and flavor-specific package size optimization are not provided.

Package verification

Lc0 engines and weights are prepared by the publisher with pnpm lc0:prepare. Preparation runs on Linux with Docker and Wine available. The Linux CPU build uses Ubuntu 22.04 and DNNL; the runtime backend is named blas even when DNNL provides its matrix operations. If Docker requires sudo, explicitly set LC0_DOCKER_SUDO=1. The Linux engine source archive and third-party notices are retained with the prepared artifacts. A prebuilt Linux artifact directory may instead be supplied through LC0_LINUX_BUNDLE. The staged bundle is checked before it replaces a previous working bundle. Preparation includes every platform selected in the config; partial-platform replacement is rejected. If the root config changes during preparation, the existing bundle is preserved and preparation must be rerun. bundle/lc0/manifest.json records platform executables, required libraries, backend, network identity, and SHA-256 digests. The package contains artifacts for both supported platforms and a shared pinned weight file; it does not download models or install GPU software when the server starts.

On Windows 10/11 x64, install the official Microsoft Visual C++ v14 x64 Redistributable before using Lc0. The Lc0/DNNL binaries require MSVCP140.dll, VCOMP140.dll, VCRUNTIME140.dll, and VCRUNTIME140_1.dll; Microsoft runtime DLLs are not redistributed in this package. Stockfish-only mode does not require Lc0 or its native runtime prerequisites.

CPU is the default. CUDA is a build-time option requiring a compatible NVIDIA environment and a successful preparation probe. A missing GPU/backend is an explicit engine failure, not an implicit switch to CPU. Windows validation via Wine is supplementary and must not be reported as a native Windows test. CUDA preparation takes a matching Linux artifact directory in LC0_LINUX_BUNDLE and a Windows archive in LC0_WINDOWS_ARCHIVE, with its SHA-256 in LC0_WINDOWS_ARCHIVE_SHA256. It does not install GPU drivers.

Package artifacts are verified locally; this project intentionally has no hosted CI workflow.

Run pnpm check for the deterministic offline gate. Use pnpm test:package to pack the project, install the tarball in a clean temporary directory, and run the installed llm-chess-mcp binary against the real Stockfish, Lc0, and Maia runtimes. pnpm release:check runs both checks plus the production dependency audit and package manifest dry run.

Package verification uses the OS temporary directory by default. If it exceeds its disk quota or free space, select a larger writable location:

PACKAGE_SMOKE_TMPDIR=/path/on/larger/disk pnpm test:package

The same environment variable applies to pnpm release:check and publishing. Temporary installs are removed after success or failure. On failure, a bounded diagnostic report (including available npm log excerpts) is saved separately in .package-smoke-failures/; PACKAGE_SMOKE_LOGDIR overrides that location. Keep diagnostic logs private and review them before sharing. They are not included in the npm package.

License & attribution

This project is licensed under the AGPL-3.0 (see LICENSE).

It bundles and depends on third-party components:

Component

License

Source

Maia3 (Chessformer)

AGPL-3.0

UofT CSSLab — Monroe et al., Chessformer: A Unified Architecture for Chess Modeling (ICLR 2026)

Stockfish (via npm stockfish)

GPL-3.0

The Stockfish developers

Lc0

GPL-3.0

The Leela Chess Zero developers; bundled library notices accompany each platform artifact

onnxruntime-node

MIT

Microsoft

chess.js

BSD-2-Clause

Jeff Hlywa

The bundled Maia3 model (models/maia3-5m.onnx) is derived from UofTCSSLab/Maia3-5M at b6559de2398d7140b985f28fd2c19fb5e47ddabe. The ONNX export is a build-time step (scripts/export_maia3.py); the runtime does not execute any Maia3 Python code.

Available Tools

13 tools
create_gameCreate Chess GameA

Create a new chess game and return its game_id. The server is the authoritative source of board state — never track the board yourself. Optionally pass a FEN to start from a custom position.

ParametersJSON Schema
NameRequiredDescriptionDefault
fenNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
game_idYes
revisionYes

TDQS

A4.5/5.0
Behavior4/5

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

Annotations (readOnlyHint=false) already indicate a write operation, but the description adds the critical behavioral directive to treat the server as the source of truth and avoid local board tracking. It also discloses the return of game_id. This goes beyond what annotations provide.

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?

The description is two sentences and front-loaded with the primary action. Each sentence adds value: the core function, the state-tracking warning, and the optional parameter explanation. No wasted words.

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 simple create tool with one optional parameter and an existing output schema, the description covers the essential aspects: what it does, return value, usage caution, and parameter semantics. It does not mention error behavior or prerequisites, but these are not critical for this tool's complexity.

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

Parameters5/5

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

The schema has 0% coverage for the 'fen' parameter, but the description clearly explains that it is optional and used to start from a custom FEN position. This fully compensates for the missing schema description.

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?

The description starts with a specific verb+resource pair ('Create a new chess game') and explicitly states the return value (game_id), making the tool's purpose unambiguous. It also clearly distinguishes from siblings like delete_game and game_import_pgn.

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 description gives clear usage context: the server is authoritative and one should never track the board locally, which implies how to use this with other game-state tools. It also notes the optional FEN for custom positions but does not explicitly exclude alternatives like game_import_pgn.

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

delete_gameDelete Chess GameC
DestructiveIdempotent

Delete a game and free its session.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
deletedYes
game_idYes

TDQS

C2.7/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, destructiveHint=true, and idempotentHint=true, so the safety profile is covered structurally. The description adds "free its session" as a mild behavioral note but doesn't disclose permanence of deletion, whether related data (moves, analyses) is destroyed, or access requirements. No contradiction with annotations exists; the description adds modest value over what annotations provide.

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

Conciseness3/5

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

The description is exactly one sentence (7 words), front-loaded with the action verb. It's efficient but arguably over-terse — the "free its session" concept and the game_id requirement both deserve elaboration. This borders on under-specification rather than genuine conciseness, though it avoids padding.

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?

For a simple 1-parameter destructive tool with good annotations and an output schema, the description is minimally adequate. The main gap is the unexplained "free its session" semantic — whether deletion is permanent, whether sessions are tied to games, and what the caller should expect afterward. Low complexity lowers the bar, but the session concept creates real ambiguity the description should resolve.

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%, and the description fails to compensate. While game_id is a self-descriptive parameter name, the description doesn't explain how to obtain a valid game_id (e.g., from create_game or game_state), any format expectations, or validation constraints. With zero coverage, the description carries the burden and drops the ball.

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?

"Delete a game" clearly identifies the verb and resource, and it implicitly distinguishes from create_game among siblings. However, "free its session" is vague and unexplained — it's unclear what a session is, what freeing it means, or whether it implies releasing resources beyond the game itself.

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 guidance on when to use this tool versus alternatives, no mention of prerequisites (ownership, active games, permissions), and no reference to sibling tools like create_game as the inverse operation. It neither states exclusions nor implies usage context beyond the literal action.

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

game_import_pgnImport Chess PGNA

Import a PGN into a new game. Returns a new game_id with the position after all PGN moves. Rejects malformed or illegal PGN.

ParametersJSON Schema
NameRequiredDescriptionDefault
pgnYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
fenYes
turnYes
isDrawYes
game_idYes
historyYes
isCheckYes
castlingYes
lastMoveYes
revisionYes
isGameOverYes
moveNumberYes
isCheckmateYes
isStalemateYes
isDrawByFiftyMovesYes
isThreefoldRepetitionYes
isInsufficientMaterialYes

TDQS

A4/5.0
Behavior4/5

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

With all annotations false, the description carries the transparency burden. It discloses that a new game is created (side effect), returns a game_id, and rejects invalid PGN. However, it does not mention idempotency, potential side effects on other resources, or permission requirements, but the core side effect is well-stated.

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?

The description is three concise sentences: action, result, and error handling. No unnecessary details or redundant phrasing. It is well-structured and easy to parse.

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?

There is no output schema, but the description clearly states the output: 'Returns a new game_id.' It also mentions error rejection. It does not describe the error format or potential additional outputs (e.g., full game state), but for a simple import tool, these details are not critical. The description provides sufficient context for a basic understanding.

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 only parameter 'pgn' has no description in the schema. The description implies it is a PGN string by the tool name and purpose, and mentions rejection of malformed PGN, but does not elaborate on acceptable format (e.g., whether headers are required) or provide examples. This is minimal but adequate for a standard chess PGN.

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?

The description clearly states the action: 'Import a PGN into a new game' and its outcome: 'Returns a new game_id with the position after all PGN moves.' This distinguishes it from sibling tools like create_game, game_pgn, and game_play_move by specifying the input format (PGN) and the new game creation.

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?

The description mentions error behavior ('Rejects malformed or illegal PGN') but does not explicitly indicate when to use this tool versus alternatives, such as when a PGN is available versus starting a blank game with create_game. There is no mention of alternatives or prerequisites.

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

game_pgnExport Chess PGNB
Read-onlyIdempotent

Export the current game as PGN.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
pgnYes
game_idYes
revisionYes

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and idempotentHint=true, so the description adds no new behavioral context. The word 'Export' is consistent with read-only, but there is no elaboration on side effects, permissions, or response details beyond the output schema.

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?

The description is a single sentence with zero filler. It efficiently states the tool's function without unnecessary detail, making it easy to parse quickly.

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 with one parameter and an output schema, so the description covers the core action. However, it lacks any guidance on alternatives or parameter specifics, and the lack of usage context means the description is only minimally adequate for the tool's overall adoption.

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 clarify the parameter, but it only refers to 'the current game' without explaining that game_id identifies which game. The lone parameter's meaning is left implicit, forcing the agent to infer from the parameter name alone.

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?

The description states a specific action ('Export') on a specific resource ('the current game') with a clear output format (PGN). It distinguishes from siblings like game_import_pgn (import) and game_state (state retrieval), making its purpose unambiguous.

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 guidance is provided on when to use this tool versus alternatives such as game_state or game_import_pgn. The description is a single declarative sentence with no context about scenarios, prerequisites, or exclusions.

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

game_play_movePlay Chess MoveA
Destructive

Play a move (SAN like 'e4' or UCI like 'e2e4') and return the resulting state. This is the ONLY tool that mutates the game. expected_revision is required: pass the revision from your most recent game_state/move_candidates read. If the game has advanced since then, the move is rejected with STALE_POSITION.

ParametersJSON Schema
NameRequiredDescriptionDefault
moveYes
game_idYes
expected_revisionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
fenYes
moveYes
turnYes
isDrawYes
game_idYes
historyYes
isCheckYes
castlingYes
lastMoveYes
revisionYes
isGameOverYes
moveNumberYes
isCheckmateYes
isStalemateYes
isDrawByFiftyMovesYes
isThreefoldRepetitionYes
isInsufficientMaterialYes

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already mark destructiveHint=true, but the description adds critical concurrency behavior: the STALE_POSITION rejection if the revision is outdated. It also states it returns the resulting state, which is useful even with an output schema.

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 concise sentences deliver the core action, uniqueness, and concurrency requirement with zero fluff. Each sentence 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?

For a mutating tool with an output schema and annotations, the description covers the essential operational details: mutation, concurrency control, error condition, and move format. It is complete enough for an agent to use it correctly.

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?

With zero schema description coverage, the description compensates by explaining the 'move' parameter (SAN vs UCI) and the 'expected_revision' parameter (required, from a recent read, and its role in staleness). The 'game_id' is self-explanatory, so overall it adds substantial meaning.

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?

Description explicitly states 'Play a move' and even clarifies SAN/UCI formats. The unique claim 'This is the ONLY tool that mutates the game' clearly differentiates it from all siblings, which are read-only or other operations.

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 clearly states when to use this tool (to make a move) and specifies the required expected_revision from a prior read. It does not explicitly mention alternatives, but by highlighting it's the only mutating tool, it implicitly advises that all other tools are non-mutating.

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

game_stateGet Chess Game StateA
Read-onlyIdempotent

Return the authoritative state of a game: FEN, turn, revision, check/mate/draw flags, move history, last move, castling rights. Use this instead of remembering the board. Set include_ascii=true to also get a board diagram.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idYes
include_asciiNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
fenYes
turnYes
boardNo
isDrawYes
game_idYes
historyYes
isCheckYes
castlingYes
lastMoveYes
revisionYes
isGameOverYes
moveNumberYes
isCheckmateYes
isStalemateYes
isDrawByFiftyMovesYes
isThreefoldRepetitionYes
isInsufficientMaterialYes

TDQS

A4.1/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and idempotentHint=true, covering safety and repeatability. The description adds value by specifying the content of the response (fields) and the optional include_ascii behavior, but does not disclose additional behavioral nuances like response format or error conditions beyond what annotations already imply. With strong annotations, this is adequate.

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?

The description is two sentences, front-loaded with the core purpose and fields, followed by an optional usage hint. Every sentence carries value; there is no fluff or redundancy. It is concise and well-structured.

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?

Given the presence of an output schema (which explains return structure) and the simple parameter set, the description fully covers what the tool does and when to use it. It even lists the key fields for quick understanding and provides a usage example for the optional parameter. It is complete for this tool's complexity.

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 coverage is 0%, so the description must compensate. It explains include_ascii (setting it true provides a board diagram) but leaves game_id implicit, though the name suggests it identifies the game. It adds some meaning for include_ascii, but could have explicitly stated game_id's purpose. Since game_id is evident from context, this partially compensates.

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?

The description clearly states the tool returns the authoritative game state and enumerates specific fields (FEN, turn, revision, flags, move history, etc.). It differentiates itself from siblings like game_pgn (which likely returns a different format) by focusing on the internal state, and explicitly suggests using it instead of remembering the board.

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 description provides explicit guidance to use this tool instead of relying on memory, giving a clear when-to-use context. It does not explicitly mention when not to use it or mention alternatives, but the ton of 'authoritative state' and scope differentiate it from related tools. No exclusions are stated, but the implied usage is clear.

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

human_move_distributionEstimate Human Chess MovesA
Read-onlyIdempotent

Return the Maia3 human-like move probability distribution for the current position, conditioned on a target Elo. Higher probability = more human-typical at that rating. This is NOT move quality — a high-probability move can still be objectively bad.

ParametersJSON Schema
NameRequiredDescriptionDefault
eloNo
top_nNo
game_idYes
oppo_eloNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
eloYes
movesYes
game_idYes
oppo_eloYes
revisionYes

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and idempotentHint=true, covering safety and determinism. The description adds crucial behavioral nuances: it clarifies that higher probability means more human-typical, and explicitly notes that this is not move quality, preventing misinterpretation. It does not contradict annotations, and adds context beyond what annotations provide, such as the meaning of the output values.

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?

The description is extremely concise—two sentences, no fluff. Every word earns its place: the first sentence defines the function and key input (Elo), and the second provides a critical caveat. It is front-loaded with the core purpose and avoids unnecessary details.

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?

The tool is relatively simple (read-only, 1 required param) and has an output schema, so the description needn't detail the return structure. It covers the core usage and behavior (human-likeness, Elo conditioning, not-quality warning). The main gap is parameter semantics (covered separately), but overall the description provides sufficient context for an agent to understand what the tool does and when to use it.

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 coverage is 0%, so the description must explain parameters. It only mentions 'target Elo' (which maps to elo) but does not clarify top_n (how many moves returned), oppo_elo (opponent rating effect), or game_id (required, identifies position). The word 'distribution' might imply all moves, but top_n suggests a subset, creating ambiguity. This is inadequate for a 4-param tool with no schema descriptions.

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?

The description clearly states the tool returns the Maia3 human-like move probability distribution for the current position, conditioned on target Elo. It explicitly distinguishes itself from move quality ('This is NOT move quality'), which differentiates it from siblings like move_evaluate or position_analyze. The verb 'Return' and specific resource 'Maia3...distribution' make the purpose precise.

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 description implies when to use: when you need human-like probabilities for a given rating, and warns against confusing with move quality. It does not explicitly mention alternatives or when NOT to use it, but the 'NOT move quality' caveat curbs misuse. The 'conditioned on a target Elo' hints at the parameter, but no direct guidance on top_n or oppo_elo is given. So it provides clear context with a partial exclusion but lacks explicit alternative naming.

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

move_candidatesGenerate Chess Move CandidatesA
Read-onlyIdempotent

The primary move-selection tool. Combine Stockfish objective evaluation (moverCp, whiteCp, cpLoss, mate, WDL), Maia3 human probability, and Lichess real-game statistics into a unified candidate list. moverCp is from the mover's perspective: higher = better for the player choosing the move. Use this before choosing a move; the final choice is yours.

ParametersJSON Schema
NameRequiredDescriptionDefault
eloNo
game_idYes
sf_depthNo
lichess_dbNolichess
maia_top_nNo
sf_multipvNo
analysis_levelNonormal
lichess_speedsNo
lichess_ratingsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
eloYes
fenYes
turnYes
game_idYes
revisionYes
candidatesYes
analysis_levelYes
moveSensitivityYes

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 openWorldHint. The description adds valuable behavioral context by explaining that moverCp is from the mover's perspective and that the tool merges three distinct evaluation sources, which goes beyond what annotations or schema convey.

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?

The description is three sentences, front-loaded with the tool's primary role, and every sentence adds meaningful context: what the tool does, the moverCp perspective, and when to use it. There is no redundancy or 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?

Given the tool's complexity and the presence of an output schema and helpful annotations, the description covers the core selection context well. It could be more complete by explicitly contrasting with sibling tools like move_candidates_by_intent, but the 'primary' framing mitigates this gap.

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%, and the description does not explain any of the nine input parameters such as elo, sf_depth, lichess_ratings, or analysis_level. It adds meaning to the output metrics but fails to compensate for the lack of parameter documentation.

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?

The description clearly states this is the primary move-selection tool and that it combines Stockfish evaluation, Maia3 human probability, and Lichess statistics into a unified candidate list. This specific verb+resource combination distinguishes it from sibling tools like move_evaluate or move_candidates_by_intent.

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 explicitly instructs the agent to use this tool before choosing a move, which is strong usage guidance. However, it does not name alternatives or provide when-not-to-use conditions, so it falls short of full differentiation.

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

move_candidates_by_intentRank Chess Moves by IntentA
Read-onlyIdempotent

Convenience layer over move_candidates: rank candidates for a strategic intent. This tool RANKS candidates but does NOT choose a move — use the returned signals and conversation context to make the final decision. Do not map user skill mechanically to an intent. intents: best (strongest engine move), strong (engine-strong but human-plausible), natural (most human-typical), balanced (blend of strength and human-likeness), ease_off (human-plausible moves that modestly reduce advantage without changing the expected result), give_chance (human-plausible inaccuracies that meaningfully improve the opponent's chances).

ParametersJSON Schema
NameRequiredDescriptionDefault
eloNo
intentYes
game_idYes
sf_depthNo
lichess_dbNolichess
maia_top_nNo
sf_multipvNo
analysis_levelNonormal
lichess_speedsNo
lichess_ratingsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
eloYes
fenYes
turnYes
intentYes
game_idYes
revisionYes
candidatesYes
analysis_levelYes
moveSensitivityYes

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is covered. The description adds behavioral context by stating it RANKS but does NOT choose a move, and clarifies the meaning of each intent, which is valuable beyond the 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?

The description is a single paragraph but packs essential information: purpose, relationship to sibling, behavioral caveat, and intent definitions. It is front-loaded with the core purpose and then details intents. Slightly long but each sentence adds value.

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?

The tool has 10 parameters, 2 required, and an output schema. The description explains the core intent parameter and the tool's role, but does not cover other parameters like elo, sf_depth, or lichess_db. However, the output schema exists, so return values are covered. The description is adequate for a complex tool but could mention how other parameters affect ranking.

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 description coverage is 0%, so the description must compensate. It explains the 'intent' parameter in detail with definitions for each enum value, which is critical. However, other parameters like elo, sf_depth, lichess_db, etc., are not explained in the description, relying on the schema's names and defaults. Given the complexity, the description covers the most important parameter but leaves others to inference.

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?

The description clearly states it is a convenience layer over move_candidates that ranks candidates for a strategic intent. It explicitly distinguishes itself from move_candidates and clarifies it does not choose a move, which differentiates it from siblings like game_play_move.

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

Usage Guidelines5/5

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

The description provides explicit guidance on when to use this tool: as a ranking layer over move_candidates, and explicitly warns not to map user skill mechanically to an intent. It also lists all intents with definitions, giving clear context for selection.

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

move_evaluateEvaluate Chess MovesA
Read-onlyIdempotent

Evaluate one or more moves with Stockfish without mutating the game. Pass a single move string or an array of moves to compare. Returns, for each move, the score after the move (from the mover's perspective), cpLoss vs the best move, and a classification (best/excellent/good/inaccuracy/mistake/blunder).

ParametersJSON Schema
NameRequiredDescriptionDefault
moveYes
depthNo
game_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
game_idYes
resultsYes
revisionYes

TDQS

A4.2/5.0
Behavior4/5

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

Annotations include readOnlyHint=true and idempotentHint=true, and the description explicitly states 'without mutating the game,' reinforcing that. It also adds value by describing the output (score, cpLoss, classification) and the engine (Stockfish), which are not required but provide useful behavioral context.

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?

The description is concise—three sentences—and front-loaded with the core purpose and non-mutation guarantee. Every sentence adds meaning without redundancy.

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 is present, so detailed return field explanations are unnecessary. The description covers the primary purpose, input flexibility, and key output categories, making it adequate for most usage scenarios. Minor omissions (e.g., depth semantics) are acceptable given the schema's constraints.

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 coverage is 0% and the description partially compensates by explaining the 'move' parameter format (string or array). However, it does not clarify the 'depth' or 'game_id' parameters beyond what the schema already provides, leaving incomplete semantic coverage.

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?

The description clearly states the tool evaluates moves using Stockfish, specifying the action (evaluate), resource (moves), and context (without mutating the game). It distinguishes itself from sibling tools like game_play_move (which mutates) and game_legal_moves (which lists legal moves).

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 description implies its use for analysis rather than gameplay via 'without mutating the game' and mentions comparing moves, which gives context. However, it does not explicitly name alternative tools or provide exclusion criteria, so it falls short of a perfect score.

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

opening_explorerQuery Lichess Opening ExplorerB
Read-onlyIdempotent

Query the Lichess opening explorer for real human game statistics in the current position (requires LICHESS_TOKEN).

ParametersJSON Schema
NameRequiredDescriptionDefault
dbNolichess
speedsNo
game_idYes
ratingsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
dbYes
blackYes
drawsYes
movesYes
whiteYes
game_idYes
openingYes
revisionYes

TDQS

B3.1/5.0
Behavior4/5

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

Annotations (readOnlyHint, openWorldHint, idempotentHint) already indicate a safe read-only operation. Description adds environment requirement: the question requires a token. Does not mention permissions, read-only side effects, or returns.

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?

Short description of one sentence with no unnecessary details. However, the output or result not mentioned.

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?

Despite output schema(true), annotations (readOnly/openWorld/idempotent), the description doesn't mention what the tool returns (opening list/names/counts), so the agent may not know if it can fulfill the request. the description is too sparse for interactive decision-making.

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?

Description gives no parameter semantics. The input schema covers params and types but does not explain the source or valid values. There are 4 parameters and he documentation does not cover the specific role of `db`, `speeds`, `ratings`, or `game_id`. Coverage is 0% and the description doesn't compensate.

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?

Description uses a specific verb ('Query') with the Lichess opening explorer and the current position context. However, it doesn't distinguish itself from sibling tools other than by name and implicit use case.

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 explicit guidance on when to use this tool vs alternatives like position_move or game_analysis. The only guidance meaning implied: 'current position' and 'requires a token'. Not enough.

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

position_analyzeAnalyze Chess PositionA
Read-onlyIdempotent

Run Stockfish on the current position and return the top engine lines (multipv). Scores are from the side-to-move perspective: positive cp = side to move is better; mate N = side to move mates in N. wdl is [win, draw, loss] in permille for the side to move. Use analysis_level (fast/normal/deep) or explicit depth/multipv. Does NOT mutate the game.

ParametersJSON Schema
NameRequiredDescriptionDefault
depthNo
game_idYes
multipvNo
analysis_levelNonormal

Output Schema

ParametersJSON Schema
NameRequiredDescription
fenYes
turnYes
linesYes
game_idYes
revisionYes
analysis_levelYes

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint and idempotentHint, so the description's statement 'Does NOT mutate the game' adds no new information, but it does clarify the evaluation perspective and wdl format, and explains analysis levels without contradiction.

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?

All sentences are purposeful and detailed without redundancy, front-loading the core action and then explaining parameters and output semantics efficiently.

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?

For a 4-parameter tool with output schema and strong annotations, the description covers the tool's functionality, parameter choices, and output interpretation (cp, mate, wdl) completely, making it highly usable.

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

Parameters5/5

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

Schema description coverage is 0%, but the description explains the meaning and effect of analysis_level, depth, and multipv, and clarifies that game_id is required to identify the position. This compensates fully for the lack of schema documentation.

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?

The description clearly states the tool runs Stockfish on the current position and returns top engine lines, distinguishing it from sibling tools like move_evaluate and move_candidates.

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 explains how to specify analysis level or depth/multipv, and mentions it does not mutate the game, but lacks explicit when-not-to-use or alternative tool comparisons.

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. 13 tool updatesv0.3.1
    • First observedcreate_game
    • First observeddelete_game
    • First observedgame_import_pgn
    • First observedgame_legal_moves
    • First observedgame_pgn
    • First observedgame_play_move
    • First observedgame_state
    • First observedhuman_move_distribution
    • First observedmove_candidates
    • First observedmove_candidates_by_intent
    • First observedmove_evaluate
    • First observedopening_explorer
    • First observedposition_analyze

TDQS

A3.7/5.0

Scored across 13 tools

Disambiguation4/5

Game lifecycle tools are clearly distinct: create, delete, state, move, legal moves, PGN export/import. The move-analysis tools overlap somewhat—position_analyze, move_evaluate, move_candidates, and move_candidates_by_intent all return evaluation-like signals—but their descriptions clarify different purposes: raw engine lines, per-move comparison, unified candidate selection, and intent-based ranking. An agent could hesitate between these, but they are not truly interchangeable.

Naming Consistency3/5

Some names follow verb_noun (create_game, delete_game), while others are noun phrases or prefixed differently (game_state, game_pgn, game_import_pgn, position_analyze, opening_explorer). The move_* group is predictable, but the overall naming is a mix of conventions. Names are still readable and snake_case consistent, so the inconsistency is moderate rather than chaotic.

Tool Count5/5

Thirteen tools is well within the ideal range and appropriate for a chess server that handles game lifecycle, PGN import/export, legal move queries, engine analysis, human-move modeling, and opening statistics. Each tool has a defined role, and the count does not feel bloated or thin.

Completeness5/5

The surface covers the full lifecycle: create, read state, mutate via play move, legal moves, delete, and PGN import/export. Analysis coverage is also strong: Stockfish lines, move evaluation, human move distributions, unified candidates, intent-based ranking, and opening explorer. There are no obvious dead ends for playing or analyzing a chess game.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A Model Context Protocol server that lets your AI talk to Stockfish. Because apparently we needed to make chess engines even more accessible to our silicon overlords.
    15
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A 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.
    21
    1
    ISC
  • F
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that exposes Stockfish chess analysis to LLM chat clients, enabling move analysis, game review, and explanation of engine choices.
    -