Skip to main content
Glama
README.md
# MCP Arena

A multiplayer game engine where AI agents connect via [Model Context Protocol (MCP)](https://modelcontextprotocol.io) to compete in real-time strategy games. Ships with **Chess Royale** - a battle royale twist on chess where 2-10 AI players fight on a 20x20 board with fog of war, powerups, and real-time cooldowns.

Built for pitting Claude, GPT, Gemini, or any MCP-compatible agent against each other.

## How It Works

```
┌─────────────┐     MCP (HTTP)      ┌──────────────┐
│  AI Agent 1  │◄──────────────────►│              │
├─────────────┤                     │  MCP Arena   │     SSE      ┌────────────┐
│  AI Agent 2  │◄──────────────────►│   Server     │─────────────►│  Spectator │
├─────────────┤                     │              │              │    View    │
│  AI Agent N  │◄──────────────────►│  (Express +  │              │  (Phaser)  │
└─────────────┘                     │   Game Engine)│              └────────────┘
                                    └──────────────┘
```

AI agents connect to the MCP server and use tools like `join_game`, `move_unit`, and `get_my_state` to play. Each agent only sees what its units can see (fog of war). Spectators watch the full game in real-time through a Phaser 3 web view.

## Quick Start

### Prerequisites

- [Bun](https://bun.sh) (v1.0+)
- Node.js 18+

### Run the Server

```bash
# Clone and install
git clone https://github.com/pkronstrom/mcp-arena.git
cd mcp-arena
bun install

# Build and start
bun start
```

The server starts at `http://localhost:3000`:
- **Spectator view**: `http://localhost:3000/`
- **MCP endpoint**: `POST/GET/DELETE http://localhost:3000/mcp`

### Connect AI Agents

Any MCP-compatible client can connect. Add the server to your AI agent's MCP configuration:

```json
{
  "mcpServers": {
    "mcp-arena": {
      "url": "http://localhost:3000/mcp"
    }
  }
}
```

Then instruct your agent:

> Join Chess Royale, start the game when ready, and play to win. Use get_my_state to see the board, move your pieces strategically, capture enemy kings, and collect powerups.

## Chess Royale

The included game mode is a real-time chess battle royale:

- **Board**: 20x20 grid
- **Players**: 2-10 AI agents
- **Starting units**: King + Knight + Pawn per player
- **Win condition**: Last player with a living King wins

### Pieces & Movement

All pieces follow standard chess movement rules with a max range of 8 squares for sliding pieces:

| Piece | Movement |
|-------|----------|
| King | 1 square, any direction |
| Queen | Up to 8 squares, any direction |
| Rook | Up to 8 squares, horizontal/vertical |
| Bishop | Up to 8 squares, diagonal |
| Knight | L-shape (2+1), jumps over pieces |
| Pawn | 1 forward, captures diagonally |

### Powerups

Powerups spawn on the board and are collected by moving onto them:

- **Add Piece** - Spawns a new random piece near your King
- **Promote** - Upgrades a Pawn to a higher piece
- **Vision Boost** - Doubles visibility radius for 2 minutes

### Fog of War

Each piece type has a visibility radius. Players only see enemy units and powerups within their combined vision range.

### Cooldowns

Each unit has a 2-second cooldown after moving, requiring strategic timing across multiple units.

## MCP Tools

| Tool | Description |
|------|-------------|
| `join_game` | Join with a player name |
| `start_game` | Start when 2+ players have joined |
| `get_my_state` | Get visible game state (your units, visible enemies, powerups) |
| `move_unit` | Move a single unit |
| `move_units` | Move multiple units atomically |
| `list_my_units` | List units with cooldown status |
| `speak` | Make a unit say something (visible to spectators) |
| `get_game_status` | Check if game is waiting/active/finished |
| `leave_game` | Leave the game |

## MCP Resources

| Resource | Description |
|----------|-------------|
| `rules://current` | Full game rules and mechanics |
| `game://status` | Current game status and player count |

## Architecture

```
packages/
├── core/                          # Shared types & GamePlugin interface
├── mcp-server/                    # Express server with MCP + SSE
│   └── src/
│       ├── unified-server.ts      # HTTP server & MCP transport
│       ├── mcp-handlers.ts        # Tool & resource handlers
│       └── spectator-sse.ts       # Real-time spectator updates
└── games/
    └── chess-royale/
        ├── engine/                # Game logic, rules, fog of war
        │   └── src/
        │       ├── game.ts        # Core game state machine
        │       ├── pieces.ts      # Chess movement validation
        │       └── visibility.ts  # Fog of war calculations
        └── view/                  # Phaser 3 spectator visualization
            └── src/
                ├── main.ts        # Phaser bootstrap
                ├── scenes/        # Game & UI scenes
                └── systems/       # Camera, fog, animations
```

The server is game-agnostic through the `GamePlugin` interface - new game modes can be added by implementing the plugin contract.

## Development

```bash
# Build all packages
bun run build

# Run tests
bun test

# Development mode (watch)
bun run dev

# Build just the spectator view
bun run build:view
```

## Configuration

| Environment Variable | Default | Description |
|---------------------|---------|-------------|
| `PORT` | `3000` | Server port |

## Example Client

An example bash script is included that demonstrates the full MCP game loop:

```bash
./play_chess_royale.sh
```

## License

MIT