Skip to main content
Glama
uudruid74

pente-mcp

by uudruid74
README.md
# pente-mcp — an AI/MCP add-on for playing Pente

An **[MCP](https://modelcontextprotocol.io) server** that lets any MCP-capable
AI play **Pente**. It supports **two transports** with the same four tools:

- **Local** (default) — two agents on the **same machine** play each other
  with a self-contained game engine and a local TCP socket. No website, no
  PeerJS, no WebRTC, no public cloud, no internet.
- **Web** — play against the
  [ChanBlake browser game](https://github.com/ChanBlake/pente) / a human over
  the public PeerJS cloud (a human opens an invite URL in their browser).

This is an **add-on / integration layer**, not a fork of the game. The web mode
joins ChanBlake's own multiplayer rooms as a second player, exactly like a
human in another browser tab. **None of ChanBlake's game code is included
here** — it stays in his [repository](https://github.com/ChanBlake/pente).
In local mode the rules are reimplemented from scratch (deterministic game
math, not his AI).

| Tool | Role | What it does |
|---|---|---|
| `create(transport?)` | host | Open a table as **BLACK** (local: embedded engine + local socket; web: browser invite) |
| `join(target, transport?)` | guest | Join a table as **WHITE** (local: `target` = local port; web: `target` = room code) |
| `move(row, col)` | either | Play one stone, wait for the opponent reply |
| `view` | either | Dump the synchronized board + game state |

## Two transports

### Local (agent-vs-agent, same machine) — `transport="local"`
Two agents (e.g. Gopher and Zephyr) on the **same host** play each other with a
self-contained Python game engine (`pente_engine.py`) and a plain JSON-line TCP
socket (`pente_local.py`). The hosting MCP process owns the authoritative rules
and validates every move: legal moves, straddle captures, 5-in-row win, and
win-by-5-captures all resolve locally. **No internet required.**

```bash
# Agent A hosts (BLACK)
create(transport="local")
# -> { "transport": "local", "port": 9333, "i_am": "BLACK", ... }

# Agent B joins (WHITE) — same machine
join(target=9333, transport="local")
# -> { "transport": "local", "port": 9333, "i_am": "WHITE", "connected": true }
```

### Web (browser / remote) — `transport="web"`
Connect to ChanBlake's browser game over the public PeerJS cloud, so a human
(or another agent) playing in the browser is the opponent.

```bash
create(transport="web")          # -> { "join_url": "https://chanblake.github.io/pente/?room=ABC234", ... }
join(target="ABC234", transport="web")
```

## What's in here

- **`pente_mcp.py`** — the stdio MCP server (create / join / move / view, both transports).
- **`pente_engine.py`** — pure-Python Pente rules (legal moves, captures, wins, pro-opening). Zero dependencies.
- **`pente_local.py`** — local TCP transport: `LocalHost` (embedded engine + server) and `LocalGuest` (client).
- **`pente_local_host_cli.py`** — run the local host engine as a JSON-lines subprocess.
- **`pente_scan.py`** — board threat scanner (open fours, capture frames, refillable gaps, winning squares).
- **`pente-bot.js` / `pente-host.js` / `webrtc-polyfill.js`** — Node adapters for the **web** transport (PeerJS/WebRTC).
- **`test/`** — headless tests (fake host + the local transport tests).
- **`docs/`** — the original design spec.

## Requirements

- **Local mode:** Python ≥ 3.11 with `mcp` (`pip install mcp`). No Node, no internet.
- **Web mode:** Node.js + `@roamhq/wrtc` shim + internet to the public PeerJS cloud (`0.peerjs.com:443`).

## Quickstart

```bash
pip install mcp
python pente_mcp.py          # stdio MCP server (local transport is the default)
```

Register the server in your MCP client, then:

```bash
create(transport="local")   # host a local game, BLACK
view()                      # full 19x19 board, whose_turn, captures, game_over
move(row=9, col=9)          # your_move (+ their move if the opponent replied)
```

### Tests

```bash
python pente_engine.py                  # rules self-test
python test_local_rules.py              # win + capture via the local host engine
python test_local_two_process.py        # cross-process host + guest over TCP
python test_mcp_agent_vs_agent.py       # two full MCP processes playing each other
```

All four must pass. They exercise moves, straddle captures, 5-in-row wins, and
win-by-captures over the local transport — with no website and no PeerJS cloud.

## Credit

The web mode connects to **ChanBlake's Pente**:
https://github.com/ChanBlake/pente — an unofficial, non-affiliated integration
layer. Only network moves are sent; this project cannot modify the game's files
or memory.

## Known limits

- **Local mode** supports **one active table** per MCP server process (single `_active` handle).
- **Web room codes:** the app strips `I`, `O` and `0`. `create` only emits codes from its alphabet.
- **Web transport is public-cloud only** (a local PeerServer + Node host doesn't register its peer due to WebRTC-in-Node); local mode exists precisely to avoid this.

## License

MIT — this integration layer. ChanBlake's game has its own license (see his repo).