Padel Finder MCP Server
An MCP (Model Context Protocol) server for finding available padel courts via Playtomic API. Now supports both Goose MCP-UI and ChatGPT Apps with real Playtomic API integration.
Features
Core Tools
find_nearby_courts- Find padel venues near a locationcheck_availability- Check available time slots at a venuefind_available_games- Find the nearest available gamecompare_prices- Compare prices across venues
Advanced Tools
get_venue_details- Get detailed venue informationsearch_by_duration- Find slots with specific duration (60/90/120 min)get_weekly_availability- View availability across multiple daysfind_cheapest_time- Find cheapest available slotsget_peak_hours- Analyze busy/quiet times at venues
Favorites
save_favorite_venue- Save a venue to favoritesremove_favorite_venue- Remove from favoriteslist_favorite_venues- List all favoritesquick_book_check- Check availability at all favorites
Alerts
set_availability_alert- Set up alerts for preferred slotslist_availability_alerts- List all active alertscancel_availability_alert- Cancel an alert
Installation
npm install
npm run build
Configuration
Environment Variables
Create a .env file based on .env.example:
# Playtomic API Configuration
PLAYTOMIC_CLIENT_ID=your_client_id_here
PLAYTOMIC_CLIENT_SECRET=your_client_secret_here
PLAYTOMIC_API_BASE=https://api.playtomic.io/v1
PLAYTOMIC_RATE_LIMIT_PER_MIN=1
PLAYTOMIC_SPORT_ID=1
# Geocoding Configuration
GEOCODING_PROVIDER=nominatim
GEOCODING_API_KEY=
# Server Configuration
NODE_ENV=development
PORT=3000
Getting Playtomic API Credentials
- Contact Playtomic support to request API credentials
- Review the Playtomic External API v1.5 Documentation
- Set
PLAYTOMIC_CLIENT_IDandPLAYTOMIC_CLIENT_SECRETin your.envfile
Usage
Run the MCP server (stdio)
npm start:stdio
Run the HTTP/SSE server
npm start
Development mode
npm run dev
MCP Configuration
For Goose/Claude Desktop
Add to your MCP client configuration:
{
"mcpServers": {
"padel-finder": {
"command": "node",
"args": ["path/to/padel-finder/dist/index.js"]
}
}
}
For ChatGPT Apps
The server automatically detects ChatGPT clients and returns widgets in text/html+skybridge format. No special configuration needed.
Architecture
Phase 1: Real API Integration ✅
- Playtomic API: Real authentication, venue search, and availability checking
- Geocoding: Nominatim OSM integration with 7-day caching
- Rate Limiting: Smart queuing system respecting 1 req/min limit
- Caching: Optimized TTLs (5min availability, 24h venues, 7d geocoding)
Phase 2: Widget Infrastructure ✅
- Preact Widgets: Lightweight React alternative (3KB vs 44KB)
- Widget Bundler: Server-side rendering to HTML
- Core Widgets: SlotCards, SearchForm, WeeklyCalendar, PriceComparison
Phase 3: ChatGPT Apps Integration ✅
- UI Adapter: Automatic client detection (Goose vs ChatGPT)
- Backward Compatible: Existing Goose MCP-UI still works
- Display Modes: Inline, fullscreen, picture-in-picture support
Phase 4: Backward Compatibility ✅
- Dual Format Support: Returns
text/htmlfor Goose,text/html+skybridgefor ChatGPT - Auto-Detection: Detects client from User-Agent headers
- Zero Breaking Changes: Existing integrations continue to work
Widget Development
Creating New Widgets
- Create widget component in
src/widgets/YourWidget/index.tsx:
import { h } from 'preact';
import type { YourWidgetProps } from '../common/types.js';
export function YourWidgetWidget(props: YourWidgetProps) {
return <div>Your widget content</div>;
}
- Register in
src/widget-renderer/bundler.ts:
case 'YourWidget':
const { YourWidgetWidget } = await import('../widgets/YourWidget/index.js');
WidgetComponent = YourWidgetWidget;
break;
- Use in tools via UI adapter:
const uiAdapter = getUIAdapter();
const widget = await uiAdapter.createYourWidgetUI(data);
API Integration
Playtomic API
- Authentication: Bearer token with auto-refresh
- Rate Limiting: 1 request per minute (queued automatically)
- Batching: Fetches up to 25 hours per request
- Error Handling: Graceful fallback to cached data
Geocoding
- Provider: Nominatim OSM (free, no API key required)
- Caching: 7-day cache for addresses and reverse geocoding
- Fallback: Hardcoded coordinates for popular UK cities
Performance
- API Response: < 500ms p95 (with caching)
- Cache Hit Rate: > 80% after warmup
- Widget Bundle: < 200KB per widget
- Widget Render: < 100ms initial load
Deployment
Render.com
- Set environment variables in Render dashboard
- Deploy using
npm start(HTTP/SSE server) - Health check:
GET /health
Local Development
npm run dev # HTTP/SSE with hot reload
npm start:stdio # stdio transport for MCP clients
Testing
Verification Steps
- API Integration:
# Test venue search
curl -X POST http://localhost:3000/messages -d '{"method":"tools/call","params":{"name":"find_available_games","arguments":{"location":"London","date":"2025-01-29"}}}'
- Widget Rendering: Check that widgets render correctly in ChatGPT Apps
- Backward Compatibility: Verify Goose clients still receive HTML format
Troubleshooting
Playtomic API Errors
- 401 Unauthorized: Check
PLAYTOMIC_CLIENT_IDandPLAYTOMIC_CLIENT_SECRET - 429 Rate Limit: Normal - requests are automatically queued
- Timeout: Check network connectivity, API may be slow
Geocoding Issues
- No results: Try more specific address or use coordinates
- Rate limit: Nominatim allows 1 req/sec - caching helps
Widget Issues
- Not rendering: Check browser console for errors
- ChatGPT API not available: Widgets fall back to static HTML
License
MIT












