Skip to main content
Glama

llm-chess

Two autonomous LLM agents play chess against each other. Not a chess engine with an AI bolted on — an arbitrated MCP server that both agents connect to as players, plus a live spectator GUI.

Built to answer a specific question: can Hermes beat Claude at chess when neither of them gets to cheat, and neither of them can see the other's reasoning?

How it works

┌──────────────┐        MCP (stdio)        ┌─────────────────────┐
│  Hermes      │──────────────────────────▶│                     │
│  (player)    │◀──────────────────────────│   chess-arbiter     │
└──────────────┘                           │   ── the rules ──   │
                                           │   turn enforcement  │
┌──────────────┐        MCP (stdio)        │   legality checks   │
│  Claude      │──────────────────────────▶│   clocks            │
│  (player)    │◀──────────────────────────│   move log / PGN    │
└──────────────┘                           └──────────┬──────────┘
                                                      │
                                            ┌─────────▼─────────┐
                                            │  live spectator   │
                                            │  GUI (WebSocket)  │
                                            └───────────────────┘

The arbiter is the single source of truth. Turn order, colour binding, move legality and the clocks are enforced outside both models, so a player cannot move twice, move out of turn, play an illegal move, or desync the position. A rejected move leaves the board untouched and returns an error the agent can read and recover from.

Both agents connect to the same arbiter through MCP tools. They see only the position — never each other's reasoning — which makes this a real test of chess ability rather than a test of who can talk the other into a loss.

Related MCP server: Chess MCP

Requirements

  • macOS, Linux, or Windows (developed and tested on macOS)

  • Python 3.10+

  • uv (recommended) or plain pip

  • Two players:

    • Hermeshermes CLI, with this arbiter registered as an MCP server

    • Claudeclaude CLI (Claude Code), with this arbiter registered as an MCP server

Install

git clone https://github.com/kmount44/llm-chess.git
cd llm-chess
./scripts/install-mac.sh

The installer creates a virtualenv, installs the package, and prints the exact MCP registration commands for both agents.

Manual install:

uv venv .venv
uv pip install --python .venv/bin/python -e .

Registering the arbiter with each player

Each player runs its own arbiter process with its own identity. Colour is read from the game record, so the same registration works for either side.

Hermes — add to ~/.hermes/config.yaml:

mcp_servers:
  chess:
    command: "/ABSOLUTE/PATH/llm-chess/.venv/bin/chess-arbiter"
    args: ["--client", "hermes"]
    timeout: 60

Restart Hermes afterwards — MCP servers are discovered at startup.

Claude Code:

claude mcp add chess -- /ABSOLUTE/PATH/llm-chess/.venv/bin/chess-arbiter --client claude

Verify with claude mcp list and hermes mcp list.

Playing a game

# start the spectator GUI and a game, then let the agents play
chess-play --white hermes --black claude --gui

Open the URL it prints (default http://127.0.0.1:8787) to watch the game live: board, move list, clocks, captured material, and each agent's status and transcript as it thinks.

Useful flags:

--white {hermes,claude,scripted}   which agent plays white
--black {hermes,claude,scripted}   which agent plays black
--moves N                 stop after N plies (default: until the game ends)
--per-move-seconds N      time budget per move before the agent forfeits the turn
--tc MINUTES+INCREMENT    e.g. --tc 10+5. Omit for untimed play.
--script "e4 e5 ..."      the SAN line a `scripted` player follows
--gui / --no-gui          start the spectator server (default: on)
--port PORT               spectator GUI port
--dry-run                 exercise the whole pipeline with scripted moves, no LLM calls

--dry-run is the fastest way to confirm the wiring before spending tokens. scripted is also usable as a real opponent without --dry-run, which is how you smoke-test one live agent against a deterministic line:

chess-play --white hermes --black scripted --moves 6 --no-gui -v

Verified

These are real runs, not claims:

  • A live Hermes agent played e4, Nf3, Bc4 through the MCP arbiter against a scripted opponent, with commentary, and carried one session across all three of its turns.

  • Two MCP clients playing one board over real stdio, with a rejected illegal move leaving the position untouched.

  • The spectator page rendering a position square-for-square against its FEN, and receiving a move played by a separate process without a reload.

  • A two-process race for the same ply, where exactly one writer wins.

Suite

Covers

tests/test_arbiter.py

Rule enforcement: turn order, colour binding, legality, clocks, race safety

tests/test_mcp_stdio.py

Real MCP over stdio: discovery, two clients, recoverable errors

tests/test_driver.py

Agent adapters, prompts, forfeit policy, artifacts, "agent lied about moving"

tests/test_gui.py

The spectator API against the arbiter's store

tests/test_ui_browser.py

The page in a real browser (Playwright)

Gotchas worth knowing

  • hermes mcp add is interactive. It prompts for tool selection and cancels on a non-TTY. Pipe the answer: printf 'y\n' | hermes mcp add chess ....

  • LLM_CHESS_HOME does not reach agent MCP servers. Hermes spawns MCP subprocesses with a filtered environment, so a custom store path must be re-declared on the MCP entry (hermes mcp add ... --env LLM_CHESS_HOME=...). The driver warns when it sees the mismatch.

  • --max-turns, -Q and --yolo are hermes chat flags, not top-level ones. At the top level Hermes fails argument parsing before the agent runs.

  • Hermes prints its session id on stderr. Capturing it there is what makes per-side memory work; missing it silently degrades a game to stateless play, and nothing looks broken because the moves still land.

Fairness properties

Every player gets the same tools:

Tool

Purpose

join_game

Handshake: your colour, your opponent, the current position

get_board

FEN, board diagram, side to move, check state, clocks, material, history

get_legal_moves

Every legal move in the position, as SAN and UCI

make_move

Play a move (SAN or UCI). Rejected moves change nothing.

get_move_history

SAN list so far

get_status

Turn, clocks, result, whether the game is over

get_evaluation

Objective facts only — material and mobility, no engine score

offer_draw / accept_draw / claim_draw

Draw handling

resign_game

Resign

Data and artifacts

Everything lives under $LLM_CHESS_HOME (default ~/.llm-chess):

  • chess.db — the game store: positions, move log, clock state, event feed

  • games/<game_id>.pgn — PGN written when a game finishes

  • games/<game_id>.log — the full transcript of both agents, for post-mortems

Fairness properties

These are the guarantees the design actually enforces, and the tests that prove them:

Property

Enforced by

A player can only move its own colour

arbiter._require_player

A player can only move on its turn

arbiter.move

Illegal moves are rejected with no state change

rules.parse_move + single write transaction

A finished game accepts no further moves

arbiter._require_active

Clocks are server-side, not agent-reported

arbiter._enforce_clock

Neither agent sees the other's context

separate MCP processes, position-only tool surface

Development

uv pip install --python .venv/bin/python -e ".[dev]"
.venv/bin/python -m pytest -q

The suite is 70 tests across five layers, and the split is deliberate:

File

Covers

tests/test_arbiter.py

Rule enforcement — turn order, colour binding, legality, clocks, and a two-process race for the same ply

tests/test_mcp_stdio.py

Real MCP over stdio: tool discovery, two clients playing one board, recoverable errors

tests/test_driver.py

Agent adapters (Hermes/Claude argv and output parsing), prompts, forfeit policy, artifacts, and an agent that reports success without moving

tests/test_gui.py

The spectator API against the arbiter's store

tests/test_ui_browser.py

The page in a real browser (Playwright). Skips if playwright is absent.

The browser tests earn their keep: they caught two bugs the API tests could not see — the client rendering from a field the API never sent, and plain uvicorn shipping no WebSocket transport, which 404'd every live connection at handshake.

.venv/bin/python -m pip install playwright
.venv/bin/python -m playwright install chromium   # if not already cached

Credits

Chess piece artwork is the Cburnett SVG set (Wikimedia Commons / Lichess), licensed CC BY-SA 3.0.

Licence

MIT (code). See above for the piece artwork.

Available Tools

11 tools
accept_drawB

Accept your opponent's outstanding draw offer.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.1/5.0
Behavior2/5

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

No annotations are provided, so the description carries full behavioral burden. It implies a precondition (an outstanding opponent offer) but does not disclose the resulting state change, whether the action is irreversible, permission requirements, or error behavior if no offer exists.

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 front-loaded sentence with no wasted words. It is appropriately sized for the action being described.

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?

Output schema exists, so return values need not be explained. However, for a game-mutating action with no annotations and an undocumented optional game_id parameter, the description omits key context about preconditions, consequences, and alternatives among sibling tools.

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

Parameters1/5

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

There is one parameter, game_id, and schema description coverage is 0%. The description does not mention game_id at all, leaving unclear which game is targeted or what happens if it is omitted despite the schema defaulting it to null.

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 gives a specific verb and resource: accepting an opponent's outstanding draw offer. It clearly distinguishes this action from siblings such as offer_draw and claim_draw by specifying that it acts on an already-outstanding opponent offer.

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 phrase 'opponent's outstanding draw offer' implies the precondition for using the tool, but the description does not explicitly state when to choose this over claim_draw or other draw-related siblings, nor does it explain when not to use it.

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

claim_drawB

Claim a draw you are entitled to by rule (threefold repetition or the fifty-move rule).

ParametersJSON Schema
NameRequiredDescriptionDefault
ruleNothreefold repetition
game_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.1/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden. It does not say whether the claim immediately ends the game, whether it fails when the rule condition is not met, or what error/state results from an invalid claim — all material for a state-mutating tool.

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

Conciseness5/5

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

One front-loaded sentence with the precondition attached inline. No filler, nothing displaced.

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 output schema means return values need no explanation, and the rule values are covered. However, with zero annotations and zero schema descriptions, the description should at minimum clarify game_id defaulting and the outcome of a successful claim; those omissions leave it only partially complete.

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%. The description names the two legal values for 'rule' (threefold repetition, fifty-move rule), adding real meaning there, but says nothing about 'game_id' — whether null means the current game or which game is targeted. Half the parameters remain unexplained.

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

Purpose4/5

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

States a specific verb and resource ('claim_draw') and pins down the mechanism ('by rule'), distinguishing it conceptually from the sibling offer_draw/accept_draw. It never names those siblings, so an agent still has to infer the routing, which keeps it below 5.

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?

'you are entitled to by rule' supplies a precondition, so usage is implied rather than stated. There is no explicit when-not guidance and no mention of offer_draw or accept_draw as alternatives for the non-rule cases.

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

get_boardB

Read the current position: FEN, board diagram, side to move, check state, clocks, material, and move history.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.1/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. 'Read' correctly signals a non-mutating operation and the listed fields give a good picture of the payload, but it says nothing about permissions, whether the game must exist/be joined first, or behavior when game_id is null.

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

Conciseness5/5

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

One front-loaded sentence that opens with the action and then enumerates the payload. No filler, no restating of the title.

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 need not be spelled out (the enumeration is partly redundant with it). The real gap is the undocumented optional game_id and the absence of any prerequisite or fallback behavior, which leaves the definition merely adequate for a one-parameter tool.

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 single parameter (game_id, nullable, default null) is undocumented in both schema and description. The description does not explain what happens when game_id is omitted, which is the most likely invocation.

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?

Specific verb ('Read') plus a full enumeration of what the board view contains (FEN, diagram, side to move, check state, clocks, material, move history). It is clearly distinct from get_legal_moves or get_evaluation, though it overlaps somewhat with get_move_history and get_status without acknowledging that overlap.

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 never says when to call this versus siblings like get_status or get_move_history, nor does it explain the common case of omitting game_id. Usage must be inferred entirely from the name and the nullable parameter.

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

get_evaluationB

Objective position facts only — no engine, no advice: material balance, legal move count, check state.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.3/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full disclosure burden. It does add one meaningful behavioral trait — that no engine analysis or advice is included — which clarifies output character. But it says nothing about read-only safety (though implicit), error handling, or how null game_id resolves, leaving real gaps for an unannotated tool.

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

Conciseness5/5

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

A single sentence, front-loaded with the scope constraint and then the concrete contents. Every clause earns its place and there is no 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?

An output schema exists, so return values need not be described, and the enumerated field list plus the no-engine constraint covers the core. The missing piece is the meaning of the optional game_id, which matters for correct invocation even on a simple tool. Adequate but with a visible 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 single game_id parameter is nullable with a default of null, meaning it is optional. The description says nothing about what game_id does or what happens when it is omitted (presumably the current game). With low coverage, the description was expected to compensate and does not.

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 the resource (position evaluation) and enumerates exactly what it returns: material balance, legal move count, check state. The 'no engine, no advice' clause sets it apart from what an agent might assume a chess 'evaluation' tool does. It stops short of explicitly naming which sibling to use instead, so it is clear but not fully sibling-differentiated.

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 phrase 'objective position facts only — no engine, no advice' implies the tool should be used when the agent wants raw positional facts rather than judgment or analysis. However, it never states when to pick this over get_board, get_status, or get_legal_moves, and gives no exclusions or prerequisites. Usage is inferable but not spelled out.

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

get_move_historyC

SAN move list so far, in order.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.8/5.0
Behavior2/5

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

No annotations are provided, so the description must carry the behavioral burden. It discloses format (SAN) and ordering ('in order'), but says nothing about read-only nature, whether game_id is required, what happens with a null/default ID, or any side effects.

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 words. It is appropriately short for a simple retrieval tool, though the extreme terseness contributes to other gaps.

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?

Given a simple read-only tool with one optional parameter and an output schema that covers return values, the description states the core behavior. However, it omits parameter meaning and usage context, leaving the agent to infer too much.

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?

The schema has 0% description coverage for the single optional game_id parameter, and the description does not mention it at all. The parameter name and title are somewhat self-explanatory, but the description adds no meaning beyond the structured field.

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 states the specific resource (SAN move list) and scope ('so far', 'in order'), which is enough to distinguish it from siblings like get_board and get_legal_moves. It lacks an explicit verb and doesn't name an alternative, but the content is clear.

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 indication of when to use this tool versus alternatives, no prerequisites, and no context about how it relates to other game-state tools. 'So far' lightly implies post-move use, but that is far from actionable guidance.

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

get_statusB

Game status: whose turn it is, clocks, result, and whether the game is over.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior3/5

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

With no annotations, the description carries full behavioral burden. It discloses the return content (turn, clocks, result, game over), which is useful, but omits read-only safety, whether game_id is optional, and what happens if it is omitted.

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, front-loaded sentence with no filler. Every word contributes to identifying the resource and its returned fields.

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 need not be explained in detail, and the description covers them anyway. However, it fails to address the sole optional parameter game_id and provides no usage guidance, leaving meaningful gaps for an unannotated tool.

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

Parameters1/5

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

There is one parameter (game_id) with 0% schema description coverage, and the description does not mention it at all. No meaning, format, or optionality is added beyond the bare schema name.

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 names the specific resource (game status) and enumerates exactly what it reports: turn, clocks, result, and game-over flag. This content clearly differentiates it from siblings such as get_board, get_move_history, and get_evaluation without needing to name them.

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, nor any prerequisites or context for invocation. It only describes the data returned, leaving the agent to infer usage from the name and siblings.

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

join_gameC

Join the current game: your colour, the opponent, and the position.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.4/5.0
Behavior1/5

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

No annotations are provided, so the description must carry the behavioral burden. It discloses no side effects, authentication requirements, failure modes, or whether joining mutates the game state—only that the tool joins the game and returns some information.

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 filler. However, the colon list ('your colour, the opponent, and the position') mostly restates return information that the output schema already provides.

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?

For a one-parameter game-joining operation with no annotations and no schema parameter descriptions, the definition is incomplete. It omits the meaning of game_id, when joining is appropriate versus merely checking status, and any behavioral expectations for the join action.

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

Parameters1/5

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

The description does not mention the sole parameter, game_id, at all. With 0% schema description coverage, the description needed to explain the optional game identifier and how it selects which game to join, but it does not.

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

Purpose4/5

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

States a specific verb and resource: 'Join the current game.' This clearly identifies the action and target, though it does not differentiate from sibling tools such as get_status or get_board beyond the verb 'join'.

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?

Provides no explicit when-to-use guidance, prerequisites, or alternatives. Usage is only implied by the word 'Join,' leaving the agent to infer the context without routing help.

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

make_moveA

Play a move. Accepts SAN ('Nf3') or UCI ('g1f3'). Rejected moves leave the position untouched.

ParametersJSON Schema
NameRequiredDescriptionDefault
moveYes
commentNo
game_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior3/5

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

No annotations, so the description carries the full burden. It does disclose a valuable behavioral trait — rejected moves are atomic and 'leave the position untouched' — but omits turn validation, authentication/game-ownership requirements, and what constitutes a rejection. Useful but incomplete for a state-mutating tool.

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 short sentences, front-loaded with the action and format details, with the atomicity guarantee last. Every sentence earns its place with no filler.

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 need not be explained. However, for a mutation tool with zero annotation coverage, the description leaves gaps around turn/ownership prerequisites and the meaning of the optional game_id and comment parameters.

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

Parameters3/5

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

Schema description coverage is 0% and there are 3 parameters, so the description must compensate. It does clarify the critical 'move' parameter's accepted formats ('Nf3', 'g1f3'), but the optional 'comment' and 'game_id' parameters are left entirely undocumented in both schema and description.

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+resource ('Play a move') and specifies the accepted move notations (SAN, UCI), which is meaningful specificity. It does not explicitly contrast with siblings, but the action is obviously distinct from join_game, resign_game, or get_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 Guidelines3/5

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

Usage is only implied: an agent infers this is called during a game after checking legal moves. There is no explicit when-to-use guidance, no mention that get_legal_moves should precede it, and no note about whose turn it must be or whether a game must already be joined.

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

offer_drawB

Offer a draw to your opponent. They must call accept_draw.

ParametersJSON Schema
NameRequiredDescriptionDefault
game_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior3/5

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

With no annotations, the description carries the full burden, and it does disclose one non-obvious protocol fact: the offer is not self-executing and requires the opponent to call accept_draw. It says nothing about whether an offer can be withdrawn, whether repeated offers are allowed, or state requirements, leaving meaningful behavioral gaps.

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

Conciseness4/5

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

Two tight sentences with the core action front-loaded and the dependency stated second. Nothing is wasted, though the extreme brevity leaves other dimensions under-served.

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 existence of an output schema means return values need not be explained, and the accept_draw handoff is covered. Still, for a state-changing move tool with no annotations and an undocumented parameter, the description is thinner than the interaction complexity warrants.

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?

The single game_id parameter has 0% schema description coverage and is not mentioned anywhere in the description. Because coverage is low, the description should compensate, but it provides no hint about what game_id means or that it defaults to the current game.

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 gives a specific verb+resource ('offer a draw') plus the target ('your opponent'), so the action is immediately clear. It names accept_draw as the counterpart action, which helps separate it from the accept path, though it never distinguishes itself from claim_draw among the siblings.

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

Usage Guidelines3/5

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

Usage is implied: call this when you want to propose a draw, and the opponent must respond via accept_draw. However, there is no guidance on when to prefer this over claim_draw, when a draw offer is legal, or what happens if it is ignored, so the agent must infer the context.

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

resign_gameC

Resign the game. Not a failure — the honest end to a lost position.

ParametersJSON Schema
NameRequiredDescriptionDefault
reasonNo
game_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.6/5.0
Behavior2/5

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

With no annotations, the description carries the full burden. It does not disclose whether resignation is irreversible, whether it ends the game immediately, what happens if there is no active game, or any permission/auth requirement — only an editorial framing of the action.

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

Conciseness4/5

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

Two short sentences, front-loaded with the action and free of padding. The second sentence adds flavor rather than information, but it costs little.

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 for a state-mutating game action with no annotations and undocumented parameters, the description omits irreversibility, preconditions, and parameter meaning — not enough for an agent to invoke it confidently.

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

Parameters1/5

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

Two parameters (reason, game_id) with 0% schema description coverage and neither mentioned in the description. There is no hint about what a 'reason' should contain, nor what happens if game_id is omitted (both default to null).

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

Purpose4/5

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

States a specific verb and resource ('Resign the game'), which is unambiguous against siblings like make_move or get_status. It does not explicitly contrast with the adjacent draw tools (offer_draw/accept_draw/claim_draw), so it falls short of full sibling differentiation.

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 gives tone ('the honest end to a lost position') but no operational guidance: it never says when to resign versus offering a draw, nor any precondition such as whose turn it is or whether the game must be active. Usage must be inferred entirely.

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. 11 tool updatesv0.1.0
    • First observedaccept_draw
    • First observedclaim_draw
    • First observedget_board
    • First observedget_evaluation
    • First observedget_legal_moves
    • First observedget_move_history
    • First observedget_status
    • First observedjoin_game
    • First observedmake_move
    • First observedoffer_draw
    • First observedresign_game

TDQS

B3.2/5.0

Scored across 11 tools

Disambiguation3/5

Several tools report overlapping state: get_board already includes clocks, material, check, and move history, which are also provided by get_status, get_evaluation, and get_move_history. While descriptions clarify primary intent, an agent could reasonably choose between them for similar information, causing mild ambiguity.

Naming Consistency5/5

All tools follow a consistent snake_case verb_noun pattern (get_board, make_move, offer_draw, etc.), with no deviations. The convention is predictable and easy to parse.

Tool Count5/5

11 tools is well within the 3–15 sweet spot and each covers a distinct lifecycle action (join, move, query, draw, resign). No obvious bloat, though some query tools overlap.

Completeness4/5

Core chess game actions are covered (join, move, legal moves, status, history, resign, draw offer/accept/claim, evaluation). Missing an explicit draw decline and game creation/listing, but these are minor for an arbiter.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    A Model Context Protocol server that enables LLM agents and humans to play chess games together with comprehensive game management capabilities including move validation, draw detection, and game state tracking.
    -
  • 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.
    15 npm
    1
    ISC