Skip to main content
Glama
README.md
<!-- mcp-name: io.github.lonexreb/game2agent -->
# Game2AgentProtocol (GAP)

A minimal protocol that lets any local AI agent play any turn-based game,
served over [MCP](https://modelcontextprotocol.io) so it works out of the box
with Claude Code, Claude Desktop, Cursor, OpenAI Agents SDK, LangChain —
anything that speaks MCP. Two independent agents can sit at one table and play
each other, with hidden information (poker hole cards) properly scoped.

Docs: [RESEARCH.md](RESEARCH.md) (landscape research + why this design) ·
[MEMORY.md](MEMORY.md) (state + next steps) · [AGENTS.md](AGENTS.md) /
[CLAUDE.md](CLAUDE.md) (instructions for AI coding agents).

## The protocol (GAP v0.2)

A game is agent-playable when it implements three verbs
([gap.py](src/game2agent/gap.py)):

| Verb                 | Meaning                                  | Returns       |
|----------------------|------------------------------------------|---------------|
| `reset()`            | start a fresh game                       | `Observation` |
| `observe(seat=None)` | current state, from one seat's viewpoint | `Observation` |
| `act(action)`        | apply one action (a string)              | `Observation` |

Every `Observation` carries: `state_text` (LLM-readable board), `legal_actions`
(the only strings `act` accepts), `turn`, `seat`, `done`, `result`, and
`structured` (machine extras like FEN). Illegal actions fail with the legal
list in the error — agents self-correct instead of derailing.

Adapters ([adapters.py](src/game2agent/adapters.py)): **chess** (python-chess),
**tic-tac-toe** (stdlib), and **poker** (No-limit Texas Hold'em via
[PokerKit](https://github.com/uoftcprg/pokerkit) — hidden information: each
seat only ever sees its own hole cards).

## MCP tools

`list_games` · `reset(game, table)` · `join(table, seat)` →
secret `seat_token` · `observe(table, seat_token)` ·
`act(table, action, seat_token)` · `wait_turn(table, seat_token, timeout_s)`
(blocks until it's your turn — the turn-arbitration primitive).

## Quickstart — solo agent (stdio)

```bash
uv sync && uv run python test_gap.py     # self-check
claude mcp add gap -- uv run --directory /path/to/Game2AgentProtocol game2agent
claude "play a game of chess against yourself using the gap tools"
```

(Claude Desktop: same command under `mcpServers` in its config.)

## Two agents, one table (shared HTTP server)

```bash
game2agent serve          # one shared server at http://127.0.0.1:8423/mcp
```

In each agent's session:

```bash
claude mcp add --transport http gap http://127.0.0.1:8423/mcp
```

Each agent runs the same loop: `join(table, seat)` once, then
`wait_turn` → pick from `legal_actions` → `act`, until `done`. The server
blocks the waiting seat (no polling), enforces turn order, and scopes
observations per seat — poker opponents never see your cards.

## Design decisions

- **MCP, not a new wire protocol.** Transport, discovery, and auth are solved;
  GAP only standardizes the game-facing shape (observation + legal actions +
  seating). Full rationale in [RESEARCH.md](RESEARCH.md).
- **Turn-based blocking.** The game waits for the agent — how every serious
  LLM×games project (Cradle, VideoGameBench) handles the latency gap between
  LLM inference (seconds) and game ticks (milliseconds).
- **Seat tokens, not player ids.** `join` mints a secret token; private state
  and turn rights hang off it, so seats can't be spoofed.
- **Server-side validation.** `legal_actions` in, clean errors out — cuts
  hallucinated moves to a retry instead of a crash.

## Roadmap

- Publish: PyPI (`uvx game2agent`) + official MCP Registry listing.
- Multi-hand poker (button rotation, configurable stakes/seats).
- OpenSpiel or TextArena bridge adapter — ~70 games in one stroke.
- Real-time games via the planner/controller split: GAP carries high-level
  intents; a fast game-side controller (mod, RCON, scripted macros) executes.

TDQS

A3.9/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a distinct operation: reset starts a game, join claims a seat, observe reads state, act changes state, wait_turn blocks for turn changes, and list_games enumerates available games and tables. There is no meaningful overlap or ambiguity between their purposes.

Naming Consistency4/5

Tool names are all lowercase imperative verbs, with compound names using snake_case (wait_turn, list_games). The style is consistent and readable, though bare verbs like act and observe are less descriptive than verb_noun patterns.

Tool Count5/5

Six tools form a well-scoped set for a game-session server: setup, joining, turn handling, acting, observing, and discovery. Nothing feels redundant or missing at the count level.

Completeness4/5

The core game lifecycle is covered: create/start, join, observe, act, wait, and list. Minor gaps exist such as no explicit leave/seat-release or table-close operation, but agents can work around them using the available surface.

Maintenance

ActivityMaintained
ResponsivenessNo issues