README.mdā¢10.6 kB
# Chess MCP App
A ChatGPT Chess application built with OpenAI Apps SDK, allowing you to play chess through conversation with an interactive board widget.
**Now following OpenAI Apps SDK best practices!**
## Features
- š® Play chess using algebraic notation (e4, Nf3, O-O, etc.)
- š Interactive chess board widget in ChatGPT
- š¤ AI opponent suggestions (ChatGPT can play moves)
- š Stockfish engine analysis integration
- š Move history tracking
- ā
Full move validation and game state management
- š Game status and player information display
- š§© Mate in 1 tactical puzzles (Easy, Medium, Hard)
## Architecture
- **Backend**: Python MCP Server using FastMCP with python-chess
- **Frontend**: React component with chess.js + react-chessboard
- **Build System**: Vite for optimal development experience
- **Integration**: OpenAI Apps SDK patterns with proper hooks
## Project Structure
```
ChessMCP/
āāā server/
ā āāā main.py # Python MCP server (renamed from server.py)
ā āāā requirements.txt # Python dependencies
āāā src/
ā āāā chess-board/ # Chess board component
ā ā āāā index.tsx
ā āāā types.ts # Shared TypeScript types
ā āāā use-openai-global.ts # Hook for window.openai access
ā āāā use-widget-state.ts # Hook for widget state
ā āāā use-widget-props.ts # Hook for tool props
āāā assets/ # Build output (generated by Vite)
ā āāā chess-board.html
āāā vite.config.mts # Vite configuration
āāā package.json # Root dependencies
āāā tsconfig.json # TypeScript config
āāā README.md
```
## Installation
### Prerequisites
- Python 3.8+
- Node.js 18+
- Stockfish chess engine (optional, for analysis)
### Setup Steps
1. **Install Python dependencies**:
```bash
cd server
pip3 install -r requirements.txt
```
2. **Install Stockfish** (optional, for engine analysis):
```bash
# macOS
brew install stockfish
# Ubuntu/Debian
sudo apt-get install stockfish
```
3. **Install Node.js dependencies**:
```bash
npm install
```
4. **Build the frontend component**:
```bash
npm run build
```
This generates `assets/chess-board.html` which the server loads.
5. **The MCP server is configured** in your `~/.cursor/mcp.json`:
```json
{
"mcpServers": {
"chess": {
"command": "python3",
"args": ["/path/to/ChessMCP/server/main.py"],
"env": {
"PYTHONPATH": "/path/to/ChessMCP/server"
}
}
}
}
```
## Development Workflow
### Build Once (Production)
```bash
npm run build
```
### Development Mode (with hot reload)
```bash
# Terminal 1: Start Vite dev server
npm run dev
# Terminal 2: Start Python server
cd server
python3 main.py
```
### Serve Built Assets (for testing)
```bash
npm run serve
```
## Testing Locally (No ChatGPT Required!)
### Option 1: Direct Local Tester (Recommended)
Play chess directly without server/OAuth:
```bash
python3 chess_local_test.py
```
Commands:
```
āļø > move e4
āļø > move e5
āļø > status
āļø > stockfish
āļø > puzzle medium
```
š **See:** [LOCAL_TESTING.md](./LOCAL_TESTING.md)
### Option 2: HTTP Client
Test via HTTP (requires server running):
```bash
# Terminal 1: Start server
cd server && python3 main.py
# Terminal 2: Start client
python3 chess_client.py
```
š **See:** [CLIENT_USAGE.md](./CLIENT_USAGE.md)
## Testing with ChatGPT
The Chess MCP server now includes **Google OAuth 2.1 authentication** for secure ChatGPT integration!
š **Quick Start:** [OAUTH_QUICK_START.md](./OAUTH_QUICK_START.md) (5 minutes)
š **Detailed Setup:** [GOOGLE_OAUTH_SETUP.md](./GOOGLE_OAUTH_SETUP.md) (Step-by-step)
š **Next Steps:** [NEXT_STEPS.md](./NEXT_STEPS.md) (What to do now)
š **Troubleshooting:** [CHATGPT_CONNECTOR_TROUBLESHOOTING.md](./CHATGPT_CONNECTOR_TROUBLESHOOTING.md)
Quick start:
```bash
# 1. Set up Google OAuth credentials (see GOOGLE_OAUTH_SETUP.md)
# 2. Create server/.env with credentials
# Terminal 1: Start server
cd server
pip3 install -r requirements.txt
python3 main.py
# Terminal 2: Expose with ngrok
ngrok http 8000
# Update server/.env with ngrok URL, restart server
# Then add connector in ChatGPT Settings > Connectors
# URL format: https://YOUR-SUBDOMAIN.ngrok-free.app (no /mcp suffix)
```
## Usage
### Starting a Game
In ChatGPT, start a chess game by making your first move:
```
ChessMCP e4
```
or
```
Let's play chess! I'll start with e4
```
The interactive chess board will appear showing your move.
### Making Moves
Simply type your move in algebraic notation:
```
Nf3
e5
Bc4
Nc6
```
Supported notation:
- Basic moves: `e4`, `Nf3`, `d5`
- Captures: `exd5`, `Nxf7`
- Castling: `O-O` (kingside), `O-O-O` (queenside)
- Pawn promotion: `e8=Q`, `a1=N`
- Check: `Qh5+`
- Checkmate: `Qf7#`
### Additional Commands
**Check game status:**
```
chess_status
What's the current status?
```
**Load a puzzle:**
```
Show me a chess puzzle
Give me a hard puzzle
```
**Get engine analysis:**
```
Ask Stockfish for the best move
```
**Reset game:**
```
chess_reset
Let's start a new game
```
## MCP Tools
The server exposes five tools:
### `chess_move`
- **Input**: `move` (string) - Algebraic notation
- **Output**: Updated board state with FEN, move history, game status
- **Widget**: Renders interactive chess board
### `chess_stockfish`
- **Input**: `depth` (int, default: 15) - Analysis depth
- **Output**: Best move, evaluation, principal variation
- **Widget Accessible**: Can be called from the widget UI
### `chess_reset`
- **Input**: None
- **Output**: Confirmation of reset
- **Widget**: Shows fresh starting position
### `chess_status` ā
- **Input**: None
- **Output**: Game status, current turn, player names, move count, recent moves
- **Use**: Check game progress and who's moving
### `chess_puzzle` ā
- **Input**: `difficulty` (string: "easy", "medium", "hard")
- **Output**: Mate-in-1 puzzle position with hint
- **Widget**: Shows puzzle position on the board
- **Use**: Practice tactical patterns and checkmate recognition
## React Hooks (Apps SDK Patterns)
The component uses OpenAI Apps SDK hooks for clean, reactive code:
### `useOpenAiGlobal(key)`
Access window.openai properties reactively:
```tsx
const theme = useOpenAiGlobal("theme");
const displayMode = useOpenAiGlobal("displayMode");
```
### `useToolOutput<T>()`
Get the current tool output:
```tsx
const toolOutput = useToolOutput<ChessToolOutput>();
// Returns: { fen, move, status, turn }
```
### `useToolResponseMetadata<T>()`
Get tool response metadata:
```tsx
const metadata = useToolResponseMetadata<ChessMetadata>();
// Returns: { move_history_list, legal_moves, etc. }
```
### `useWidgetState<T>(defaultState)`
Persist component state across sessions:
```tsx
const [widgetState, setWidgetState] = useWidgetState<ChessWidgetState>({
lastDepth: 15,
analysisVisible: false
});
```
## Build System (Vite)
### Why Vite?
- ā”ļø Fast hot module replacement during development
- š¦ Optimized production builds
- šÆ TypeScript support out of the box
- š§ Better error messages
- šØ Source maps for debugging
### Build Output
The build creates a single HTML file containing:
- Bundled React component
- All JavaScript dependencies
- Inline CSS
- Proper structure for Skybridge runtime
### Configuration
See `vite.config.mts` for the build configuration. The setup:
1. Bundles `src/chess-board/index.tsx`
2. Includes all dependencies
3. Wraps in HTML with proper structure
4. Outputs to `assets/chess-board.html`
## Server Architecture
### Resource Handling
The server follows Apps SDK patterns:
```python
# Load HTML from assets
@lru_cache(maxsize=None)
def load_widget_html(component_name: str) -> str:
html_path = ASSETS_DIR / f"{component_name}.html"
return html_path.read_text(encoding="utf8")
# Proper MIME type
MIME_TYPE = "text/html+skybridge"
# Resource registration
@mcp._mcp_server.list_resources()
async def list_resources() -> List[types.Resource]:
return [types.Resource(...)]
# Resource handler
async def handle_read_resource(req) -> types.ServerResult:
html = load_widget_html("chess-board")
return types.ServerResult(types.ReadResourceResult(...))
```
### Tool Metadata
All tools include proper metadata:
```python
{
"openai/outputTemplate": "ui://widget/chess-board.html",
"openai/widgetAccessible": True,
"openai/resultCanProduceWidget": True,
"openai/toolInvocation/invoking": "Making move...",
"openai/toolInvocation/invoked": "Move played"
}
```
## Troubleshooting
### Widget Not Rendering
1. Ensure component is built: `npm run build`
2. Verify `assets/chess-board.html` exists
3. Check server logs for errors
### Stockfish Not Found
Update the path in `server/main.py`:
```python
STOCKFISH_PATH = "/path/to/stockfish"
```
### Build Errors
If TypeScript errors occur:
```bash
npm run typecheck
```
### Server Won't Start
Make sure all Python dependencies are installed:
```bash
cd server
pip3 install -r requirements.txt
```
## What's New in This Version
### ⨠Restructured Project
- Moved from `web/` to `src/` directory
- Root-level `package.json` and `vite.config.mts`
- Proper Apps SDK project structure
### š£ React Hooks
- `useOpenAiGlobal` for reactive window.openai access
- `useWidgetState` for persistent state management
- `useToolOutput` and `useToolResponseMetadata` for props
### ā” Vite Build System
- Replaced esbuild with Vite
- Hot module replacement in development
- Better TypeScript support
- Faster builds
### šļø Server Improvements
- Proper resource loading from `assets/`
- Correct MIME type (`text/html+skybridge`)
- Better error handling
- CORS middleware for development
### š Better Types
- Comprehensive TypeScript types
- Apps SDK-compatible interfaces
- Chess-specific type definitions
## Contributing
Feel free to enhance the app with:
- Opening analysis and endgame tablebases
- Multiple game sessions
- PGN import/export
- Time controls
- Online multiplayer
- More puzzle types
## License
MIT License - feel free to use and modify!
## Resources
- [OpenAI Apps SDK Documentation](https://developers.openai.com/apps-sdk)
- [Apps SDK Examples](https://github.com/openai/openai-apps-sdk-examples)
- [python-chess Documentation](https://python-chess.readthedocs.io/)
- [chess.js](https://github.com/jhlywa/chess.js)
- [react-chessboard](https://github.com/Clariity/react-chessboard)