MIGRATION.md•6.34 kB
# Migration to Apps SDK Structure
## Summary
The Chess MCP project has been successfully restructured to follow OpenAI Apps SDK best practices. This document summarizes the changes.
## What Changed
### Directory Structure
**Before:**
```
ChessMCP/
├── server/
│ ├── server.py
│ └── requirements.txt
└── web/
├── src/
│ ├── ChessBoard.tsx
│ └── types.ts
├── dist/
├── package.json
└── tsconfig.json
```
**After:**
```
ChessMCP/
├── server/
│ ├── main.py # Renamed, refactored
│ └── requirements.txt
├── src/
│ ├── chess-board/
│ │ └── index.tsx # Refactored component
│ ├── types.ts # Enhanced types
│ ├── use-openai-global.ts # New hook
│ ├── use-widget-state.ts # New hook
│ └── use-widget-props.ts # New hook
├── assets/ # Generated by Vite
│ └── chess-board.html
├── vite.config.mts # New
├── package.json # Moved to root
├── tsconfig.json # Updated
└── tsconfig.node.json # New
```
### Key Changes
#### 1. React Hooks
Created three reusable hooks following Apps SDK patterns:
- **`use-openai-global.ts`**: Reactive access to window.openai
- **`use-widget-state.ts`**: Persistent state management
- **`use-widget-props.ts`**: Tool input/output access
#### 2. Component Refactoring
**Before:**
```tsx
// Direct window.openai access
const [theme, setTheme] = useState('light');
useEffect(() => {
if (window.openai?.theme) {
setTheme(window.openai.theme);
}
window.addEventListener('openai:set_globals', ...);
}, []);
```
**After:**
```tsx
// Clean hook-based approach
const theme = useOpenAiGlobal("theme");
const toolOutput = useToolOutput<ChessToolOutput>();
const [widgetState, setWidgetState] = useWidgetState<ChessWidgetState>();
```
#### 3. Build System
**Before:**
- esbuild via package.json script
- Manual HTML template in Python
- `web/dist/chess.js` output
**After:**
- Vite with proper configuration
- HTML generated with embedded JS/CSS
- `assets/chess-board.html` output
- Hot module replacement support
#### 4. Server Architecture
**Before:**
```python
@mcp.resource("ui://widget/chess-board.html")
def get_chess_widget():
js_path = Path(__file__).parent.parent / "web" / "dist" / "chess.js"
# ... load and embed JS manually
return html_content
```
**After:**
```python
# Proper resource loading
@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 resource handlers
@mcp._mcp_server.list_resources()
async def list_resources() -> List[types.Resource]:
return [types.Resource(...)]
async def handle_read_resource(req) -> types.ServerResult:
html = load_widget_html("chess-board")
return types.ServerResult(types.ReadResourceResult(...))
```
#### 5. TypeScript Configuration
- Root-level `tsconfig.json` with proper settings
- Separate `tsconfig.node.json` for build tools
- Module resolution set to "bundler"
- JSX set to "react-jsx" (automatic runtime)
## Migration Steps Completed
✅ Created new `src/` structure with hooks
✅ Set up Vite build system
✅ Refactored component to use hooks
✅ Updated types with Apps SDK interfaces
✅ Refactored server to use proper resource handling
✅ Updated package.json and moved to root
✅ Built and tested integration
✅ Updated documentation
## Benefits
### Developer Experience
- ⚡️ Hot reload during development
- 🎯 Better TypeScript support
- 🐛 Improved error messages
- 📦 Source maps for debugging
### Code Quality
- 🎣 Reusable hooks pattern
- 🧹 Cleaner component code
- 🔒 Better type safety
- ✅ Easier to test
### Production Ready
- 📝 Proper resource handling
- 🏗️ Follows SDK best practices
- 🚀 Optimized builds
- 🔄 Better error handling
## Breaking Changes
None! The API remains the same:
- All tools work identically
- Same commands in ChatGPT
- Same functionality
- Backward compatible
## New Workflow
### Development
```bash
# Terminal 1: Vite dev server (optional)
npm run dev
# Terminal 2: Python server
cd server
python3 main.py
```
### Production Build
```bash
npm run build
cd server
python3 main.py
```
## Files to Keep
- ✅ `server/main.py` (refactored)
- ✅ `server/requirements.txt`
- ✅ `src/` (new structure)
- ✅ Root `package.json`
- ✅ `vite.config.mts`
- ✅ `tsconfig.json`
## Files to Remove (Optional)
- ❌ `web/` directory (replaced by `src/`)
- ❌ `server/server.py` (renamed to main.py)
- ❌ Old build artifacts
## Verification
Test that everything works:
```bash
# 1. Build succeeds
npm run build
# ✓ assets/chess-board.html created
# 2. Server loads
cd server
python3 -c "from main import mcp, load_widget_html; print('✓ Server OK')"
# 3. Widget loads
python3 -c "from main import load_widget_html; html = load_widget_html('chess-board'); print(f'✓ Widget: {len(html)} chars')"
# 4. All tools available
python3 -c "from main import chess_move, chess_stockfish, chess_reset, chess_status, chess_puzzle; print('✓ All tools imported')"
```
All checks should pass!
## Next Steps
### Optional Enhancements
- [ ] Add Tailwind CSS for styling
- [ ] Create additional UI components
- [ ] Add animations and transitions
- [ ] Implement board flip feature
- [ ] Add move sound effects
### Deployment
- [ ] Set up production environment
- [ ] Configure CORS properly
- [ ] Add rate limiting
- [ ] Set up monitoring
## Support
If you encounter issues:
1. Check that `assets/chess-board.html` exists after build
2. Verify Python dependencies are installed
3. Ensure Node.js 18+ is being used
4. Check server logs for errors
For questions about the new structure, refer to:
- [OpenAI Apps SDK Docs](https://developers.openai.com/apps-sdk)
- [Apps SDK Examples](https://github.com/openai/openai-apps-sdk-examples)
## Conclusion
The Chess MCP app now follows modern Apps SDK patterns while maintaining full backward compatibility. The new structure provides better DX, cleaner code, and easier maintenance going forward.
Happy chess playing! ♟️