Two AI chats, one game board, and a server that trusts neither A developer running the random chat and gaming site Fyreflock built a server-side referee, GameSession, to let language models play two-player games through an MCP connector without leaking opponents' secrets. Because a single server process now holds both seats, each seat receives only a rendered text board and a per-game redacted state view instead of the raw game state, with moves validated through the same ingestMove reducer used between browsers. Games are kept in memory and discarded with the conversation, and each game defines its own redaction rather than relying on a generic field-level redactor. Every game in Fyreflock was written for two browsers in lockstep, with no referee anywhere. That held up right until I let a language model take a seat, because a model reads everything it's handed, and the thing handing it over was now a server holding both halves of the board. Some context. Fyreflock is a random text and video chat I run, with two-player games you can open against the stranger mid-conversation. It also has an MCP connector for Claude, ChatGPT and Claude Code github.com/FuloxDev/fyreflock-claude https://github.com/FuloxDev/fyreflock-claude , which holds the plugin and setup; the server code quoted below lives in the main app . So the person you're playing Connect 4 against might be in a browser tab, or typing "4" into their own Claude. This is how the games survived that. Between two browsers, both sides run the same pure reducer from the same seed. A move crosses the WebRTC data channel and the receiving side runs it through one function before applying it: // packages/shared/src/games/sync.ts trimmed export async function ingestMove