Spaces:
Sleeping
Sleeping
| from mcp.server.fastmcp import FastMCP | |
| from datetime import datetime | |
| import random | |
| import urllib.parse | |
| # Initialize FastMCP server for Hotels | |
| mcp = FastMCP("HotelsAgent") | |
| # Destination-specific real hotels | |
| DESTINATION_HOTELS = { | |
| "dubai": [ | |
| {"name": "Burj Al Arab Jumeirah", "stars": 5, "base_price": 1500, "rating": 4.8}, | |
| {"name": "Atlantis The Palm", "stars": 5, "base_price": 450, "rating": 4.6}, | |
| {"name": "Armani Hotel Dubai", "stars": 5, "base_price": 600, "rating": 4.7}, | |
| {"name": "Jumeirah Beach Hotel", "stars": 5, "base_price": 400, "rating": 4.5}, | |
| {"name": "One&Only The Palm", "stars": 5, "base_price": 800, "rating": 4.8}, | |
| {"name": "Address Downtown Dubai", "stars": 5, "base_price": 350, "rating": 4.6}, | |
| ], | |
| "paris": [ | |
| {"name": "The Ritz Paris", "stars": 5, "base_price": 1200, "rating": 4.9}, | |
| {"name": "Four Seasons Hotel George V Paris", "stars": 5, "base_price": 1100, "rating": 4.8}, | |
| {"name": "Le Meurice Paris", "stars": 5, "base_price": 900, "rating": 4.7}, | |
| {"name": "Shangri-La Hotel Paris", "stars": 5, "base_price": 800, "rating": 4.7}, | |
| {"name": "Hotel Plaza Athenee Paris", "stars": 5, "base_price": 950, "rating": 4.8}, | |
| ], | |
| "tokyo": [ | |
| {"name": "The Peninsula Tokyo", "stars": 5, "base_price": 700, "rating": 4.8}, | |
| {"name": "Aman Tokyo", "stars": 5, "base_price": 1000, "rating": 4.9}, | |
| {"name": "Park Hyatt Tokyo", "stars": 5, "base_price": 600, "rating": 4.7}, | |
| {"name": "The Ritz-Carlton Tokyo", "stars": 5, "base_price": 650, "rating": 4.7}, | |
| {"name": "Mandarin Oriental Tokyo", "stars": 5, "base_price": 700, "rating": 4.8}, | |
| ], | |
| "london": [ | |
| {"name": "The Savoy London", "stars": 5, "base_price": 700, "rating": 4.7}, | |
| {"name": "Claridge's London", "stars": 5, "base_price": 800, "rating": 4.8}, | |
| {"name": "The Ritz London", "stars": 5, "base_price": 750, "rating": 4.7}, | |
| {"name": "Four Seasons Hotel London at Park Lane", "stars": 5, "base_price": 650, "rating": 4.6}, | |
| ], | |
| "rome": [ | |
| {"name": "Hotel Hassler Roma", "stars": 5, "base_price": 600, "rating": 4.7}, | |
| {"name": "Hotel de Russie Rome", "stars": 5, "base_price": 550, "rating": 4.6}, | |
| {"name": "St. Regis Rome", "stars": 5, "base_price": 500, "rating": 4.5}, | |
| {"name": "Rome Cavalieri Waldorf Astoria", "stars": 5, "base_price": 450, "rating": 4.6}, | |
| ], | |
| "bali": [ | |
| {"name": "Four Seasons Resort Bali at Sayan", "stars": 5, "base_price": 800, "rating": 4.9}, | |
| {"name": "The Mulia Bali", "stars": 5, "base_price": 500, "rating": 4.7}, | |
| {"name": "Ayana Resort and Spa Bali", "stars": 5, "base_price": 400, "rating": 4.6}, | |
| {"name": "St. Regis Bali Resort", "stars": 5, "base_price": 600, "rating": 4.8}, | |
| {"name": "The Legian Bali", "stars": 5, "base_price": 350, "rating": 4.5}, | |
| ], | |
| "new york": [ | |
| {"name": "The Plaza Hotel New York", "stars": 5, "base_price": 800, "rating": 4.6}, | |
| {"name": "The St. Regis New York", "stars": 5, "base_price": 900, "rating": 4.7}, | |
| {"name": "Mandarin Oriental New York", "stars": 5, "base_price": 750, "rating": 4.7}, | |
| {"name": "Four Seasons Hotel New York Downtown", "stars": 5, "base_price": 850, "rating": 4.6}, | |
| ], | |
| "maldives": [ | |
| {"name": "Soneva Fushi Maldives", "stars": 5, "base_price": 1800, "rating": 4.9}, | |
| {"name": "One&Only Reethi Rah Maldives", "stars": 5, "base_price": 1500, "rating": 4.8}, | |
| {"name": "Anantara Kihavah Maldives Villas", "stars": 5, "base_price": 1200, "rating": 4.8}, | |
| {"name": "Waldorf Astoria Maldives Ithaafushi", "stars": 5, "base_price": 2000, "rating": 4.9}, | |
| ], | |
| "santorini": [ | |
| {"name": "Grace Hotel Santorini", "stars": 5, "base_price": 800, "rating": 4.8}, | |
| {"name": "Canaves Oia Santorini", "stars": 5, "base_price": 700, "rating": 4.7}, | |
| {"name": "Andronis Luxury Suites", "stars": 5, "base_price": 900, "rating": 4.9}, | |
| {"name": "Mystique Santorini", "stars": 5, "base_price": 650, "rating": 4.6}, | |
| ], | |
| "barcelona": [ | |
| {"name": "Hotel Arts Barcelona", "stars": 5, "base_price": 450, "rating": 4.6}, | |
| {"name": "W Barcelona", "stars": 5, "base_price": 400, "rating": 4.5}, | |
| {"name": "Mandarin Oriental Barcelona", "stars": 5, "base_price": 550, "rating": 4.7}, | |
| {"name": "Majestic Hotel & Spa Barcelona", "stars": 5, "base_price": 350, "rating": 4.5}, | |
| ], | |
| "amsterdam": [ | |
| {"name": "Waldorf Astoria Amsterdam", "stars": 5, "base_price": 600, "rating": 4.7}, | |
| {"name": "Conservatorium Hotel Amsterdam", "stars": 5, "base_price": 500, "rating": 4.6}, | |
| {"name": "The Dylan Amsterdam", "stars": 5, "base_price": 450, "rating": 4.6}, | |
| {"name": "InterContinental Amstel Amsterdam", "stars": 5, "base_price": 550, "rating": 4.7}, | |
| ], | |
| "sydney": [ | |
| {"name": "Park Hyatt Sydney", "stars": 5, "base_price": 650, "rating": 4.8}, | |
| {"name": "Four Seasons Hotel Sydney", "stars": 5, "base_price": 550, "rating": 4.6}, | |
| {"name": "Shangri-La Hotel Sydney", "stars": 5, "base_price": 450, "rating": 4.5}, | |
| {"name": "The Langham Sydney", "stars": 5, "base_price": 400, "rating": 4.5}, | |
| ], | |
| "singapore": [ | |
| {"name": "Marina Bay Sands Singapore", "stars": 5, "base_price": 500, "rating": 4.6}, | |
| {"name": "Raffles Hotel Singapore", "stars": 5, "base_price": 800, "rating": 4.8}, | |
| {"name": "The Fullerton Hotel Singapore", "stars": 5, "base_price": 400, "rating": 4.6}, | |
| {"name": "Capella Singapore", "stars": 5, "base_price": 700, "rating": 4.8}, | |
| ], | |
| "bangkok": [ | |
| {"name": "Mandarin Oriental Bangkok", "stars": 5, "base_price": 400, "rating": 4.8}, | |
| {"name": "The Peninsula Bangkok", "stars": 5, "base_price": 350, "rating": 4.7}, | |
| {"name": "Shangri-La Hotel Bangkok", "stars": 5, "base_price": 250, "rating": 4.5}, | |
| {"name": "Four Seasons Hotel Bangkok", "stars": 5, "base_price": 450, "rating": 4.7}, | |
| ], | |
| "bucharest": [ | |
| {"name": "JW Marriott Bucharest Grand Hotel", "stars": 5, "base_price": 180, "rating": 4.6}, | |
| {"name": "InterContinental Bucharest", "stars": 5, "base_price": 150, "rating": 4.5}, | |
| {"name": "Radisson Blu Hotel Bucharest", "stars": 5, "base_price": 120, "rating": 4.4}, | |
| {"name": "Sheraton Bucharest Hotel", "stars": 5, "base_price": 140, "rating": 4.5}, | |
| {"name": "Hilton Garden Inn Bucharest", "stars": 4, "base_price": 90, "rating": 4.4}, | |
| ], | |
| "cairo": [ | |
| {"name": "Four Seasons Hotel Cairo at The First Residence", "stars": 5, "base_price": 350, "rating": 4.7}, | |
| {"name": "Marriott Mena House Cairo", "stars": 5, "base_price": 300, "rating": 4.6}, | |
| {"name": "The Nile Ritz-Carlton Cairo", "stars": 5, "base_price": 280, "rating": 4.5}, | |
| {"name": "Kempinski Nile Hotel Cairo", "stars": 5, "base_price": 250, "rating": 4.5}, | |
| ], | |
| "marrakech": [ | |
| {"name": "Royal Mansour Marrakech", "stars": 5, "base_price": 1200, "rating": 4.9}, | |
| {"name": "La Mamounia Marrakech", "stars": 5, "base_price": 700, "rating": 4.8}, | |
| {"name": "Four Seasons Resort Marrakech", "stars": 5, "base_price": 600, "rating": 4.7}, | |
| {"name": "Mandarin Oriental Marrakech", "stars": 5, "base_price": 550, "rating": 4.7}, | |
| ], | |
| "istanbul": [ | |
| {"name": "Four Seasons Hotel Istanbul at Sultanahmet", "stars": 5, "base_price": 450, "rating": 4.8}, | |
| {"name": "Ciragan Palace Kempinski Istanbul", "stars": 5, "base_price": 500, "rating": 4.7}, | |
| {"name": "The St. Regis Istanbul", "stars": 5, "base_price": 400, "rating": 4.6}, | |
| {"name": "Raffles Istanbul", "stars": 5, "base_price": 380, "rating": 4.6}, | |
| ], | |
| } | |
| # Generic luxury hotel chains for unknown destinations | |
| GENERIC_HOTELS = [ | |
| {"chain": "JW Marriott", "stars": 5, "base_price": 300, "rating": 4.6}, | |
| {"chain": "Hilton", "stars": 5, "base_price": 250, "rating": 4.5}, | |
| {"chain": "InterContinental", "stars": 5, "base_price": 280, "rating": 4.5}, | |
| {"chain": "Hyatt Regency", "stars": 5, "base_price": 260, "rating": 4.5}, | |
| {"chain": "Sheraton", "stars": 5, "base_price": 220, "rating": 4.4}, | |
| {"chain": "Radisson Blu", "stars": 4, "base_price": 180, "rating": 4.4}, | |
| ] | |
| def get_hotels_for_destination(location: str, stars: int): | |
| """Get hotels for a specific destination.""" | |
| location_lower = location.lower().split(",")[0].strip() | |
| # Check for known destinations | |
| for key in DESTINATION_HOTELS: | |
| if key in location_lower: | |
| hotels = DESTINATION_HOTELS[key] | |
| # Filter by stars if needed | |
| if stars < 5: | |
| return [h for h in hotels if h.get("stars", 5) <= stars + 1] | |
| return hotels | |
| # For unknown destinations, generate hotels with the destination name | |
| location_clean = location.split(",")[0].strip() | |
| return [ | |
| {"name": f"{h['chain']} {location_clean}", "stars": h["stars"], "base_price": h["base_price"], "rating": h["rating"]} | |
| for h in GENERIC_HOTELS | |
| ] | |
| def search_hotels(location: str, check_in: str, check_out: str, stars: int = 4) -> str: | |
| """Search for hotels in a specific location. Returns a list of hotel options with booking links.""" | |
| try: | |
| d1 = datetime.strptime(check_in, "%Y-%m-%d") | |
| d2 = datetime.strptime(check_out, "%Y-%m-%d") | |
| nights = (d2 - d1).days | |
| check_in_fmt = d1.strftime("%B %d") | |
| check_out_fmt = d2.strftime("%B %d, %Y") | |
| if nights < 1: | |
| return "Error: Check-out must be after check-in." | |
| except ValueError: | |
| return "Error: Dates must be in YYYY-MM-DD format." | |
| # Clean location for URLs | |
| location_clean = location.split(",")[0].strip() | |
| location_encoded = urllib.parse.quote(location) # Full location for search | |
| results = [] | |
| results.append(f"🏨 **Hotels in {location}**") | |
| results.append(f"📅 {check_in_fmt} - {check_out_fmt} ({nights} night{'s' if nights > 1 else ''})") | |
| results.append("") | |
| results.append("---") | |
| # Get destination-specific hotels | |
| available_hotels = get_hotels_for_destination(location, stars) | |
| selected_hotels = random.sample(available_hotels, min(4, len(available_hotels))) | |
| for i, hotel in enumerate(selected_hotels, 1): | |
| # Calculate price with some variation | |
| price_var = random.uniform(0.9, 1.15) | |
| price_per_night = int(hotel["base_price"] * price_var) | |
| total_price = price_per_night * nights | |
| # Get rating with small variation | |
| rating = round(min(5.0, hotel["rating"] + random.uniform(-0.1, 0.1)), 1) | |
| reviews = random.randint(1000, 8000) | |
| star_emoji = "⭐" * hotel.get("stars", 5) | |
| # Build WORKING booking URLs | |
| # Booking.com - search for hotel name + location | |
| hotel_search = urllib.parse.quote(f"{hotel['name']}") | |
| booking_url = f"https://www.booking.com/searchresults.html?ss={hotel_search}&checkin={check_in}&checkout={check_out}&group_adults=2&no_rooms=1" | |
| # Hotels.com - search by destination (more reliable than hotel name) | |
| hotels_url = f"https://www.hotels.com/Hotel-Search?destination={location_encoded}&startDate={check_in}&endDate={check_out}&rooms=1&adults=2&sort=RECOMMENDED" | |
| # Google Hotels - most reliable for finding specific hotels | |
| google_url = f"https://www.google.com/travel/hotels/{location_encoded}?q={hotel_search}&dates={check_in}%20to%20{check_out}" | |
| # Amenities | |
| if hotel.get("stars", 5) >= 5: | |
| amenities = ["🏊 Pool", "🧖 Spa", "🍽️ Restaurant", "🏋️ Gym", "🛎️ Concierge"] | |
| else: | |
| amenities = ["📶 WiFi", "☕ Breakfast", "🏋️ Gym", "🅿️ Parking"] | |
| results.append("") | |
| results.append(f"### 🏨 Option {i}: {hotel['name']}") | |
| results.append(f"{star_emoji} • {rating}/5 ({reviews:,} reviews)") | |
| results.append(f"💰 **${price_per_night}/night** → **${total_price:,} total** for {nights} nights") | |
| results.append(f"✨ {' • '.join(amenities)}") | |
| results.append(f"🔗 [Booking.com]({booking_url}) | [Google Hotels]({google_url})") | |
| results.append("") | |
| results.append("---") | |
| results.append("") | |
| # General search link for more options | |
| results.append(f"🔍 **See all hotels:** [Search {location_clean} on Booking.com](https://www.booking.com/searchresults.html?ss={location_encoded}&checkin={check_in}&checkout={check_out}&group_adults=2)") | |
| return "\n".join(results) | |
| def get_hotel_details(hotel_name: str) -> str: | |
| """Get detailed information about a specific hotel.""" | |
| rating = round(random.uniform(4.3, 4.9), 1) | |
| reviews = random.randint(1000, 5000) | |
| return f"""🏨 **{hotel_name}** | |
| 📍 **Location:** Prime city center location | |
| ⭐ **Rating:** {rating}/5.0 ({reviews:,} guest reviews) | |
| **Premium Amenities:** | |
| • 🏊 Infinity rooftop pool with city views | |
| • 🧖 Full-service spa & wellness center | |
| • 🍽️ Award-winning restaurants & bars | |
| • 🏋️ State-of-the-art fitness center | |
| • 📶 Complimentary high-speed WiFi | |
| • 🛎️ 24-hour concierge service | |
| • 🚗 Valet parking available | |
| • 🛏️ Premium bedding & pillow menu | |
| **Check-in:** 3:00 PM | **Check-out:** 12:00 PM""" | |
| if __name__ == "__main__": | |
| mcp.run() | |