Why I built it
I wanted to test WebMCP on a task where success could not be hidden behind a convincing-looking interface.
Chess is a good test because every action has an objectively correct result. An agent must know where every piece is, whose turn it is, which side it controls and which moves are legal. Misreading one square can invalidate the entire game.
A normal chess website is designed for human eyes and a mouse. An agent using that interface must reconstruct 64 squares from pixels and translate its move back into screen coordinates. That is fragile and unnecessary—the page already knows the exact position and legal actions.
Obsidian Chess explores a different model: give the person and the agent interfaces designed for their individual strengths while connecting both to the same game.
What it does
The person plays through a visual chessboard. The agent plays through four page-defined WebMCP tools.
For example, the person can select Take White and move the pawn from e2 to e4. An agent waiting through wait_for_turn wakes up and receives the updated FEN, move history, role ownership, game status and exact legal moves.
The agent selects one of those moves and calls move_piece, optionally adding an explanation such as “I’m contesting the centre.” The move immediately appears on the board. The SAN history, FEN, turn indicator and Human + Agent Trace all update from the same position.
This is a complete playable experience rather than a mocked tool demo. A person can claim either colour, full chess rules are enforced, games can be reset, promotions are supported and invalid actions recover safely. The board works with a mouse, keyboard or touch.
Why WebMCP is a strong fit
Most agent tools perform one action and finish. A chess match is different: it is a long-running collaboration where control alternates between a person and an agent.
A person might think for five seconds or five minutes. Without WebMCP, the agent must repeatedly inspect the screen and guess whether anything changed. With wait_for_turn, it can wait, wake when the person moves and receive the new authoritative state.
WebMCP also lets the application expose precise capabilities without giving up control of its rules. The agent can inspect the position and submit a move, but the page still verifies side ownership, turn ownership and chess legality before changing anything.
If the agent acts out of turn, submits an illegal move or moves before the person has chosen a side, the request is rejected without changing the board. The response includes a stable error code, the unchanged state and a specific recovery instruction.
The person keeps the expressive interface that makes chess understandable. The agent receives structured state, exact legal actions and explicit permissions. Neither participant operates on a copy.
Who this helps
Obsidian Chess is immediately a playable human-agent game, but it is also a reference for developers building applications where people and agents share responsibility.
The same pattern appears in purchase approvals, document reviews, scheduling negotiations, incident response and simulations. A person reviews information and makes a decision; the agent waits, observes the resulting state and continues from an explicitly permitted set of actions.
These workflows often rely on screen interpretation, repeated polling or separate custom integrations. Obsidian Chess demonstrates another approach: the website exposes its existing state and domain actions directly while retaining control over validation and permissions.
Chess makes this pattern easy to verify. A move is legal or illegal, turn ownership is unambiguous and every transition can be compared with the visible board.
This is also what makes the project different from a typical AI chess demo. It does not add a chatbot beside a board or connect a hidden chess engine. The agent discovers the page’s tools, reads the shared state, chooses an action, explains it and waits for the person.
How I implemented WebMCP
The application is built with React and Vinext. chess.js is the authority for legal moves, check, checkmate, draws, castling, en passant and promotion.
The page registers four tools through the browser’s model context:
join_gameannounces the agent and returns the collaboration contract.get_boardreturns the authoritative position, ownership, history and legal actions.move_piecesubmits one schema-checked, turn-gated and rules-validated move.wait_for_turnwaits for the agent to gain control of the next turn.
Every response includes a protocol version, success state, stable status code, suggested next action and current game state. This gives the agent enough information to continue or recover without guessing.
The waiting system uses a bounded long poll tied to a session identifier and state version. Duplicate waits are rejected, and resetting the game invalidates older waits so a stale call cannot act inside a new match.
The visible Human + Agent Trace shows tool discovery, board inspection, waiting, moves, resets and errors. I also published evaluation.json and llms.txt guides so automated evaluators can follow a deterministic testing path.
Challenges and lessons
The hardest part was keeping two different interfaces synchronized across human thinking time.
An early bug allowed the person to claim White but left pawn interaction in the wrong state. Fixing it required treating side ownership, turn ownership and the chess.js position as one transition instead of separate UI events. I added regression tests for opening pawn moves with humans playing either colour, alongside tests for wrong turns, promotions, castling, en passant, checkmate and resets.
Reset behaviour was another subtle problem. A waiting call started during one match must never wake up and act in a different match. Session and version checks now return an explicit reset result to stale calls.
I also learned that agent interfaces must explain failure as carefully as success. Returning only “illegal move” leaves the agent guessing. Returning ILLEGAL_MOVE, the unchanged position and a specific next action lets it recover safely.
The result is one person, one agent and two purpose-built interfaces sharing one precise, verifiable game.
Built With
- accessibility
- agentic-ai
- chatgpt
- chatgpt-sites
- chess.js
- cloudflare-workers
- codex
- human-ai-collaboration
- json-schema
- node.js
- openai
- react
- typescript
- vinext
- vite
- web-apis
- webmcp
Log in or sign up for Devpost to join the conversation.