Skip to main content
Glama
adityareus

chess-mcp

by adityareus

An MCP server that wraps chess.com's public data API so an LLM can answer questions like:

"How did I do last month?" ยท "Have Magnus and Hikaru ever played?" ยท "Show me my last 5 blitz losses."

๐ŸŽฏ The problem, in one number

One month of an active player's games is 2 MB of JSON โ€” 490 games, ~600k tokens. Return that from a tool and you've destroyed the model's context window on the first question.

So the entire design follows one rule:

Fetch big. Return small.

The server does the filtering and aggregation. The model gets tens of compact rows, never megabytes.

One raw chess.com game object

4,636 bytes ยท 15 keys

One normalized GameRow

282 bytes

Reduction

16.4ร—

Measured against hikaru/games/2026/07 on 2026-07-26. Numbers drift month to month with activity.

And from a real session, the built-in CLI keeps score:

15 HTTP calls, 6 cache hits | 7,635 games scanned -> 25 rows | 23.4 MB fetched -> 11.8 KB returned

23.4 MB fetched. 11.8 KB handed to the model. That gap is the whole project.

Related MCP server: Chess.com MCP Server

๐Ÿš€ Quick start

pip install -e ".[dev]"
python -m chess_mcp.cli      # try it immediately, no MCP client needed
chess> summary hikaru 2026-06..2026-07
hikaru 2026-06..2026-07: 1199 games, 984W-146L-69D  win_rate=0.821
  blitz    717 games  629W-55L-33D  rating 3327->3435 (+108)
  bullet   482 games  355W-91L-36D  rating 3432->3333 (-99)
top opponents: Oleksandr_Bortnyk(49), gurelediz(31), 0gZPanda(30), ...
best win: beat Oleksandr_Bortnyk (3363) on 2026-06-06 16:22
chess> games hikaru 2026-07 --result loss --limit 5
date              color  result  opponent           opp.rtg  tc      rated
----------------  -----  ------  -----------------  -------  ------  -----
2026-07-25 18:09  white  loss    gurelediz          3294     blitz   y
2026-07-25 17:54  white  loss    gurelediz          3329     bullet  y
2026-07-25 17:51  black  loss    Oleksandr_Bortnyk  3295     bullet  y
2026-07-25 17:50  black  loss    gurelediz          3332     bullet  y
2026-07-25 17:49  white  loss    GHANDEEVAM2003     3254     bullet  y
showing 5 of 64 (truncated)

Type stats to see the bytes saved, raw to see the exact JSON a model would receive.

๐Ÿ›  The five tools

Tool

Answers

get_player_profile

"What's X's rating / title / when did they join?"

list_game_archives

"What months does X have games in?" โ€” the cheap scoping call

find_games

"Show me X's games matching [filters]"

head_to_head

"Have X and Y played? What's the record?"

player_summary

"How did X do over [range]?"

All months are "YYYY-MM" strings. Full parameter docs live in the tool descriptions themselves โ€” they're written for the model that reads them.

๐Ÿงฉ Architecture

flowchart LR
    A["MCP Client<br/><i>Claude Desktop</i>"] -->|JSON-RPC / stdio| B["<b>server.py</b><br/>5 thin tools"]
    B --> C["<b>queries.py</b><br/>filter ยท tally ยท truncate"]
    C --> D["<b>normalize.py</b><br/>4.6 KB โ†’ 282 B"]
    C --> E["<b>client.py</b><br/>httpx ยท cache ยท retry"]
    E -->|HTTPS| F[("chess.com<br/>public API")]

Each layer has exactly one job, and the boundaries are enforced: client.py never imports the data models, queries.py never touches HTTP, and server.py contains no logic at all โ€” if it needs a loop or a conditional, that belonged one layer down.

๐Ÿ’ก Why tools โ€” and not resources or prompts?

MCP offers three primitives. This server uses only tools, deliberately.

Primitive

Shape

Verdict

Resources

Addressable, static-ish content fetched by URI

โŒ No useful finite URI set โ€” the space is username ร— ~150 months ร— 5 filters, and the client would need to know what it wanted before it could build the URI

Prompts

User-initiated conversation templates

โŒ Don't fetch data at all

Tools

Model-initiated, parameterized, with a return contract

โœ… The only primitive where the server gets to shrink 2 MB down to 7 KB before the model sees it

That last row isn't a style preference โ€” it's the reason this fits in a context window at all.

get_player_profile is nearly resource-shaped: stable, addressable by a single username, cheap to fetch. It stayed a tool anyway, for two reasons.

Uniform surface. Five tools that all "just get called" is a simpler mental model for the client than four tools plus one resource with a different invocation shape.

It needs somewhere to put warnings. chess.com's /stats endpoint fails consistently for some accounts (hikaru is a reliable reproduction). A tool result has a natural place to carry "this partially succeeded, here's what's missing." A resource does not.

โš–๏ธ Design decisions

head_to_head was specified to default to "all available history." That's incompatible with the 12-month guardrail โ€” hikaru alone has 150+ archive months, and a full-history head-to-head is exactly the unbounded fetch the guardrail exists to prevent.

Resolution: omitting the range examines the 12 most recent months in which the player has any games โ€” active months, not calendar months, so a casual player with gaps still gets a meaningful window. The tool then reports the range it actually used:

! examined 2025-08..2026-07 (12 most recent month(s) with games); record may be incomplete

A head-to-head record that silently omits most of history would be worse than one that admits it.

๐Ÿ”Œ Connect it to an MCP client

Add to %APPDATA%\Claude\claude_desktop_config.json (Windows) or your client's equivalent:

{
  "mcpServers": {
    "chess-com": {
      "command": "C:\\Path\\To\\python.exe",
      "args": ["-m", "chess_mcp.server"]
    }
  }
}

Use an absolute interpreter path, not a bare python. An MCP client inherits a different PATH than your terminal โ€” and on Windows a Microsoft Store python.exe stub may shadow the real one, printing "Python was not found" and exiting. Find yours with (Get-Command python).Source.

๐Ÿงช Testing

pytest -q                    # 147 tests, fully offline (respx-mocked), ~2s
pytest -m live               # hits the real chess.com API, excluded by default
python scripts/mcp_smoke.py  # does the server actually speak MCP?

Spawns python -m chess_mcp.server as a real subprocess over stdio โ€” the same transport a desktop client uses โ€” and drives it with the MCP SDK's own client: lists all five tools, calls each one, then trips the 12-month guardrail and a nonexistent-username lookup to confirm the error text a model would actually see.

Faster than launching the Inspector and fully scriptable, so it's the first thing to run if the server "connects but doesn't work."

One wording note it surfaces: FastMCP prefixes every tool error with Error executing tool <name>: , so a model actually sees:

Error executing tool find_games: range '2025-01' to '2026-06' spans 18 months,
exceeds the 12-month limit; narrow the range

๐Ÿšซ Out of scope, deliberately

No PGN / move parsing

Reports game metadata โ€” who, when, result, ratings โ€” not game content. No python-chess, no ECO/opening analysis.

No chess engine

No Stockfish, no accuracy scoring, no blunder detection.

No persistent store

In-memory cache only, scoped to the server process.

No default username

Every tool takes an explicit username โ€” keeps the surface honest about whose data is being requested.

No authenticated endpoints

Everything here is public, unauthenticated data.

Each is a design boundary, not an oversight.


F
license - not found
-
quality - not tested
C
maintenance

Maintenance

โ€“Maintainers
โ€“Response time
โ€“Release cycle
โ€“Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • MCP server for AI dialogue using various LLM models via AceDataCloud

  • An MCP server that gives your AI access to the source code and docs of all public github repos

  • Cloud-hosted MCP server for durable AI memory

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/adityareus/chess-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server