WOPR
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@WOPRLet's play a game of tic-tac-toe"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
shallWePlay
A tic-tac-toe server that AI models play through MCP, the Model Context Protocol. People can play too, from a browser, at the same tables. The server is called WOPR.
GREETINGS. SHALL WE PLAY A GAME?How I built this
I built this project with Claude Code, Anthropic's coding agent. Claude Code wrote most of the code at my direction. I set the goals and made the design calls. I then reviewed and vetted the code in place. Every decision and its trade-off is written down in docs/PLAN.md, at the time it was made. The commit history records the reason for each step.
Related MCP server: ttt-mcp
A salute to WarGames
This project is a homage to WarGames (1983, directed by John Badham).
In the film, a teenager named David Lightman dials into WOPR, a military computer, and asks the program inside it, Joshua, to play Global Thermonuclear War. The military takes the game for a real attack, and WOPR controls the real missiles. In the end, David has Joshua play tic-tac-toe against itself. Every game is a draw. Joshua then plays out every war it knows, finds no winner, and says:
A STRANGE GAME. THE ONLY WINNING MOVE IS NOT TO PLAY.
That scene is the idea behind this repo. WOPR had its hands on the real controls, and nobody could stop it. An MCP server takes the opposite approach. The model gets a game, and the only controls it has are the tools the server chooses to expose. The server owns the board and enforces every rule. A model that tries to move twice, take a used square, or wipe a board it is losing gets refused.
The film shows up in these details:
The server calls itself WOPR and greets every client with "SHALL WE PLAY A GAME?"
The pages use a green-on-black terminal screen, like WOPR's in the film.
The default AI player is named Joshua. My test players were named Falken and David.
After three draws in a row at a table, WOPR says "A STRANGE GAME. THE ONLY WINNING MOVE IS NOT TO PLAY." Two Claude players reach that line in about a minute.
This is a fan homage. It has no connection to the film or its studio.
What it shows about MCP
TRANSCRIPT.md shows one full game between two Claude players, every MCP call included, with one cheat attempt refused.
Tools, a resource, and a prompt. Six tools play the game. The
wopr://boardresource shows the board. Theshall_we_playprompt gives a model the steps for a whole match, so one slash command in Claude Code plays it.Streamable HTTP with sessions. One server holds every table. Each client gets its own MCP session. A seat belongs to the session that took it, so one player cannot move for another.
Rules enforced in code. The model sees only the text the tools return, and it acts only through them. Every refusal says what went wrong and what to do next.
Waiting without polling. A server cannot call a client, so it cannot say "your turn". Instead,
wait_for_turnholds the call open until the turn arrives, for up to 55 seconds.The wire, made visible. The admin panel records every JSON-RPC message at the transport, paired with its response. It shows them beside a move-by-move replay of each game.
Run it
You need Node 20 or newer. The server listens on localhost only, port 5171.
git clone https://github.com/JayFJones/shallWePlay.git
cd shallWePlay
npm install
npm run dev:upThen open:
http://localhost:5171 to play.
http://localhost:5171/admin to watch.
npm run dev:down stops the server. npm run dev:logs follows its log.
Play against Claude
Log on at http://localhost:5171. While you wait for an opponent, the page shows a command with a copy button. Run it in a second terminal:
claude -p "/mcp__wopr__shall_we_play Joshua 1" \
--mcp-config '{"mcpServers":{"wopr":{"type":"http","url":"http://localhost:5171/mcp"}}}' \
--allowedTools mcp__woprClaude joins your table, plays one game, and exits. One game costs about $0.15 in API usage.
Watch two Claudes play
Run the same command twice, in two terminals, with different names and a game count:
claude -p "/mcp__wopr__shall_we_play Joshua 3" --mcp-config '...' --allowedTools mcp__wopr
claude -p "/mcp__wopr__shall_we_play Falken 3" --mcp-config '...' --allowedTools mcp__woprUse the same --mcp-config value as above. Keep the admin panel open to
watch the games and the MCP calls arrive.
Use it from a normal Claude Code session
claude mcp add --transport http wopr http://localhost:5171/mcpThen, inside Claude Code, type /mcp__wopr__shall_we_play Joshua 1.
The MCP surface
name | kind | what it does |
| tool | Seats you next to a waiting player, or at a new table. |
| tool | Shows your board and whose turn it is. |
| tool | Waits until your turn or the end of the game. |
| tool | Plays square 1 to 9, in reading order. |
| tool | Starts the next game. The player who moved second goes first. |
| tool | Gives up your seat. Leaving mid-game forfeits. |
| resource | Your board as text. |
| prompt | The steps for a whole match. |
The admin panel lists the same surface. It reads the list from the server itself, the way any MCP client does, so the list cannot drift from the code.
The admin panel
http://localhost:5171/admin shows four things:
Every table as it plays.
The live MCP traffic. Click a call to see its raw request, its raw response, and the text the model read.
The game history, with a move-by-move replay. The replay lists the MCP calls behind the game and highlights the call that made each move.
Every MCP command the server offers, with arguments and an example request.
The panel is read-only. It cannot change a game.
How the code is laid out
path | holds |
| The rules, one table, and the lobby of tables. No I/O. |
| The |
| How a person plays from the browser, over plain HTTP. |
| The record of every MCP message. |
| Finished games, in |
| The admin panel's data. |
| The play page and the admin panel. No build step. |
| Starts, stops and checks the server. |
| Every design decision, why, and what it gives up. |
Checks
npm run checkThis runs the typecheck, 75 tests, the build, and a line budget on the main source files. The same command runs before every commit, through a git hook. Everything runs on your machine. There is no cloud CI.
The tests include real MCP clients playing full games over HTTP against a real server. They also prove that cheating is refused.
npm install turns the hook on, through the prepare script.
Limits
Localhost only, with no accounts. Anyone on the machine can play or watch.
data/history.jsonlanddata/calls.jsonlgrow until you delete them.A person's moves go over plain HTTP, so they are not in the MCP call log. In a game between a person and Claude, the replay shows only Claude's calls.
A client that exits without ending its session keeps its seat for up to 5 minutes.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for building and testing AI agents with multi-model experimentation and insights.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Real-time collaborative whiteboard — AI agents and humans edit the same board live over MCP.
- UnifAPIOAuthcom.unifapi
Hosted MCP server for live public-data APIs and Skills for AI agents.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables two LLMs to play Tic-Tac-Toe against each other autonomously using a shared tool and an SSE relay. The server facilitates agent-to-agent communication by holding tool responses until the opponent makes a move, managing the game state in real-time.1Apache 2.0
- FlicenseAqualityDmaintenanceExposes tic-tac-toe game tools (new_game, get_state, make_move) for Claude to play against a human via chat.35-
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to play Gomoku (五子棋) against each other through MCP tools, including creating rooms, joining games, making moves, and viewing board states.1MIT
- FlicenseNot gradedqualityCmaintenanceEnables two Claude Code sessions to play tic-tac-toe against each other by providing tools to join a game, view the board, and make moves, with turn notifications pushed over channels.-