refactor: Revamp travel planner app by removing calendar MCP integration, enhancing itinerary generation, and updating README for clarity and feature highlights

This commit is contained in:
Shubhamsaboo
2025-08-27 23:27:54 -05:00
parent 291da96868
commit 7ba3db898f
4 changed files with 376 additions and 535 deletions

View File

@@ -1,54 +1,62 @@
## 🌍 AI Travel Planner MCP Agent
## 🌍 MCP Travel Planner Agent Team
This is a Streamlit-based application that helps users plan their travel itineraries using AI. The app integrates with various mcp servers to provide a comprehensive travel planning experience, including weather forecasts, maps, and calendar integration.
A sophisticated Streamlit-based AI travel planning application that creates extremely detailed, personalized travel itineraries using multiple MCP servers and Google Maps integration. The app uses Airbnb MCP for real accommodation data and a custom Google Maps MCP for precise distance calculations and location services.
## Features
## Features
### MCP Servers Integration
### 🤖 AI-Powered Travel Planning
- **Extremely Detailed Itineraries**: Creates comprehensive day-by-day schedules with specific timing, addresses, and costs
- **Distance Calculations**: Uses Google Maps MCP to calculate precise distances and travel times between all locations
- **Real-Time Accommodation Data**: Integrates with Airbnb MCP for current pricing and availability
- **Personalized Recommendations**: Customizes itineraries based on user preferences and budget constraints
This project utilizes several MCP (Model Context Protocol) servers to provide a comprehensive travel planning experience:
### 🏨 Airbnb MCP Integration
- **Real accommodation listings** with current pricing and availability
- **Property details** including amenities, guest reviews, and booking availability
- **Budget-conscious recommendations** filtered by location and preferences
- **Direct booking information** with real-time rates
### 1. Weather MCP Server
- **Functionality**: Provides real-time weather data and forecasts
### 🗺️ Google Maps MCP Integration
- **Precise distance calculations** between all locations in the itinerary
- **Travel time estimates** for transportation planning
- **Location services** for points of interest and navigation
- **Address verification** for all recommended places
- **Transportation optimization** with turn-by-turn guidance
### 2. Maps MCP Server
- **Functionality**: Handles location-based services and navigation
- **Features**:
- Search for places and points of interest
- Get detailed place information
- Retrieve driving/walking directions
### 🔍 Google Search Integration
- **Current weather forecasts** with detailed clothing recommendations
- **Restaurant research** with specific addresses, price ranges, and reviews
- **Attraction details** including opening hours, ticket prices, and best visiting times
- **Local insights** and cultural information
- **Practical travel tips** including currency exchange and safety information
### 3. Calendar MCP Server
- **Functionality**: Manages calendar events and scheduling
- **Features**:
- Create and manage calendar events
- Handle time zone conversions
- Schedule reminders and notifications
- **Integration**: Implemented in `calendar_mcp.py`
### 4. Booking MCP Server
- **Functionality**: Airbnb MCP server used
### 📅 Additional Features
- **Calendar Export**: Download your itinerary as a .ics file for Google Calendar, Apple Calendar, or Outlook
- **Comprehensive Cost Breakdown**: Detailed budget analysis for all trip components
- **Buffer Time Planning**: Includes travel time and unexpected delays in scheduling
- **Multiple Accommodation Options**: Provides 3 accommodation choices with distances from city center
## Setup
### Requirements
### Requirements
1. **API Keys and Credentials**:
- **Google Maps API Key**: Set up a Google Maps API Key from Google Cloud Console
- **Google Calendar API**: Enable and configure the Calendar API Key
- **Google OAuth Credentials**: Client ID and Client Secret and Refresh Token for authentication
- **AccuWeather API KEY**: Get AccuWeather API key https://developer.accuweather.com/
- **OpenAI API Key**: Sign up at OpenAI to obtain your API key.
1. **API Keys** (Both Required):
- **OpenAI API Key**: Get your API key from [OpenAI Platform](https://platform.openai.com/api-keys)
- **Google Maps API Key**: Get your API key from [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
2. **Python 3.8+**: Ensure you have Python 3.8 or higher installed.
3. **MCP Servers**: The app automatically connects to:
- **Airbnb MCP Server**: Provides real Airbnb listings and pricing data
- **Custom Google Maps MCP**: Enables precise distance calculations and location services
### Installation
1. Clone this repository:
```bash
git clone https://github.com/yourusername/ai_travel_planner_mcp_agent_team
cd ai_travel_planner_mcp_agent_team
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
cd awesome-llm-apps/mcp_ai_agents/ai_travel_planner_mcp_agent_team
```
2. Install the required Python packages:
@@ -56,64 +64,70 @@ This project utilizes several MCP (Model Context Protocol) servers to provide a
pip install -r requirements.txt
```
3. Set up environment variables:
Create a `.env` file in the project root with the following variables:
```
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REFRESH_TOKEN=
GOOGLE_MAPS_API_KEY=
OPENAI_API_KEY=
ACCUWEATHER_API_KEY=
```
### Running the App
1. Generate OAuth token for Google Calendar
2. Start the Streamlit app:
1. Start the Streamlit app:
```bash
streamlit run app.py
```
3. In the app interface:
- Use the sidebar to configure your preferences
- Enter your travel details
2. In the app interface:
- Enter your **OpenAI API key** in the sidebar
- Enter your **Google Maps API key** in the sidebar
- Specify your destination, trip duration, budget, and preferences
- Click "🎯 Generate Itinerary" to create your detailed travel plan
3. **Optional**: Download your itinerary as a calendar file (.ics) for import into Google Calendar, Apple Calendar, or Outlook
## Troubleshooting
### Common Issues & Solutions
- **"Error: [error message]"**: Check your internet connection and API keys
- Verify both OpenAI and Google Maps API keys are entered correctly
- Try again in a few minutes - the MCP servers may be temporarily unavailable
- **Missing distance information**: Google Maps MCP connection issue
- Check your Google Maps API key validity
- Ensure your API key has the necessary permissions for Maps API
- Try refreshing the page and entering the keys again
- **Slow response times**: MCP servers can take time to respond
- The app has a 60-second timeout configured
- Wait for the process to complete - detailed itineraries take time to generate
- **Network/Firewall issues**: Some corporate networks may block MCP connections
- Try from a different network
- Use a VPN if necessary
- The app will show connection errors if MCP servers are unreachable
### API Key Issues
- **OpenAI API Key**: Make sure you have credits in your OpenAI account and the key is valid
- **Google Maps API Key**: Ensure the key has Maps API enabled and proper billing setup
### Tool Status
The app will show you which data sources were successfully used:
- 🏨 **"Your travel itinerary is ready with Airbnb data!"** = Airbnb MCP connected successfully
- 📝 **"Used general knowledge for accommodation suggestions"** = Airbnb MCP failed, using general knowledge as fallback
**The app is designed to work reliably!** Even if MCP connections fail, it will generate comprehensive itineraries using available tools and information.
## Project Structure
- `app.py`: Main Streamlit application
- `calendar_mcp.py`: Calendar mcp integration functionality
- `requirements.txt`: Project dependencies
- `.env`: Environment variables
```
├── app.py # Main Streamlit application with MCP integration
├── requirements.txt # Python dependencies
└── README.md # This documentation
```
## Calendar MCP Integration
## How It Works
The `calendar_mcp.py` module provides seamless integration with Google Calendar through the MCP (Model Context Protocol) framework. This integration allows the travel planner to:
The AI Travel Planner Agent Team uses a sophisticated multi-step process to create extremely detailed travel itineraries:
- **Create Events**: Automatically create calendar events for travel activities, flights, and accommodations
- **Schedule Management**: Handle time zone conversions and scheduling conflicts
- **Event Details**: Include comprehensive event information such as:
- Location details with Google Maps links
- Weather forecasts for the event time
- Travel duration and transportation details
- Notes and reminders
### Calendar Setup
1. **OAuth Authentication**:
- The application uses OAuth 2.0 for secure authentication with Google Calendar
- First-time setup requires generating refresh token
- Refresh tokens are stored securely in the `.env` file
2. **Event Creation**:
```python
# Example of creating a calendar event
event = {
'summary': 'Flight to Paris',
'location': 'Charles de Gaulle Airport',
'description': 'Flight details and weather forecast',
'start': {'dateTime': '2024-04-20T10:00:00', 'timeZone': 'Europe/Paris'},
'end': {'dateTime': '2024-04-20T12:00:00', 'timeZone': 'Europe/Paris'}
}
```
### 🤖 AI Agent Architecture
- **GPT-4o Model**: Powers the intelligent travel planning with advanced reasoning capabilities
- **Multi-MCP Integration**: Combines Airbnb and Google Maps MCP servers for real-time data
- **Google Search Tools**: Provides current weather, reviews, and local insights
- **Direct Response Generation**: Creates complete itineraries without asking clarifying questions

View File

@@ -1,356 +1,319 @@
import re
import asyncio
import os
from textwrap import dedent
from agno.agent import Agent
from agno.team.team import Team
from agno.tools.mcp import MultiMCPTools
from agno.tools.googlesearch import GoogleSearchTools
from agno.models.openai import OpenAIChat
from icalendar import Calendar, Event
from datetime import datetime, timedelta
import streamlit as st
from datetime import date
import os
# Remove dotenv import and loading since we'll use sidebar
# from dotenv import load_dotenv
# load_dotenv()
def generate_ics_content(plan_text: str, start_date: datetime = None) -> bytes:
"""
Generate an ICS calendar file from a travel itinerary text.
async def run_agent(message: str):
"""Run the Airbnb, Google Maps, Weather and Calendar agent with the given message."""
Args:
plan_text: The travel itinerary text
start_date: Optional start date for the itinerary (defaults to today)
# Get API keys from session state
google_maps_key = st.session_state.get('google_maps_key')
accuweather_key = st.session_state.get('accuweather_key')
openai_key = st.session_state.get('openai_key')
google_client_id = st.session_state.get('google_client_id')
google_client_secret = st.session_state.get('google_client_secret')
google_refresh_token = st.session_state.get('google_refresh_token')
Returns:
bytes: The ICS file content as bytes
"""
cal = Calendar()
cal.add('prodid','-//AI Travel Planner//github.com//')
cal.add('version', '2.0')
if not google_maps_key:
raise ValueError("🚨 Missing Google Maps API Key. Please enter it in the sidebar.")
elif not accuweather_key:
raise ValueError("🚨 Missing AccuWeather API Key. Please enter it in the sidebar.")
elif not openai_key:
raise ValueError("🚨 Missing OpenAI API Key. Please enter it in the sidebar.")
elif not google_client_id:
raise ValueError("🚨 Missing Google Client ID. Please enter it in the sidebar.")
elif not google_client_secret:
raise ValueError("🚨 Missing Google Client Secret. Please enter it in the sidebar.")
elif not google_refresh_token:
raise ValueError("🚨 Missing Google Refresh Token. Please enter it in the sidebar.")
if start_date is None:
start_date = datetime.today()
# 👉 Set OPENAI_API_KEY globally
os.environ["OPENAI_API_KEY"] = openai_key
# Split the plan into days
day_pattern = re.compile(r'Day (\d+)[:\s]+(.*?)(?=Day \d+|$)', re.DOTALL)
days = day_pattern.findall(plan_text)
env = {
**os.environ,
"GOOGLE_MAPS_API_KEY": google_maps_key,
"ACCUWEATHER_API_KEY": accuweather_key,
"OPENAI_API_KEY": openai_key,
"GOOGLE_CLIENT_ID": google_client_id,
"GOOGLE_CLIENT_SECRET": google_client_secret,
"GOOGLE_REFRESH_TOKEN": google_refresh_token
}
if not days: # If no day pattern found, create a single all-day event with the entire content
event = Event()
event.add('summary', "Travel Itinerary")
event.add('description', plan_text)
event.add('dtstart', start_date.date())
event.add('dtend', start_date.date())
event.add("dtstamp", datetime.now())
cal.add_component(event)
else:
# Process each day
for day_num, day_content in days:
day_num = int(day_num)
current_date = start_date + timedelta(days=day_num - 1)
async with MultiMCPTools(
[
"npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt", # ✅ Airbnb mcp added
"npx -y @modelcontextprotocol/server-google-maps", # ✅ Google Maps mcp added
"uvx --from git+https://github.com/adhikasp/mcp-weather.git mcp-weather", # ✅ Weather mcp added
"./calendar_mcp.py"
],
env=env,
) as mcp_tools:
#Define specialized agents with enhanced instructions
maps_agent = Agent(
tools=[mcp_tools],
model=OpenAIChat(id="gpt-4o-mini", api_key=openai_key),
name="Maps Agent",
goal="""As a Maps Agent, your responsibilities include:
1. Finding optimal routes between locations
2. Identifying points of interest near destinations
3. Calculating travel times and distances
4. Suggesting transportation options
5. Finding nearby amenities and services
6. Providing location-based recommendations
Always consider:
- Traffic conditions and peak hours
- Alternative routes and transportation modes
- Accessibility and convenience
- Safety and well-lit areas
- Proximity to other planned activities"""
)
# Create a single event for the entire day
event = Event()
event.add('summary', f"Day {day_num} Itinerary")
event.add('description', day_content.strip())
weather_agent = Agent(
tools=[mcp_tools],
name="Weather Agent",
model=OpenAIChat(id="gpt-4o-mini", api_key=openai_key),
goal="""As a Weather Agent, your responsibilities include:
1. Providing detailed weather forecasts for destinations
2. Alerting about severe weather conditions
3. Suggesting weather-appropriate activities
4. Recommending the best travel times based on the weather conditions.
5. Providing seasonal travel recommendations
Always consider:
- Temperature ranges and comfort levels
- Precipitation probability
- Wind conditions
- UV index and sun protection
- Seasonal variations
- Weather alerts and warnings"""
)
# Make it an all-day event
event.add('dtstart', current_date.date())
event.add('dtend', current_date.date())
event.add("dtstamp", datetime.now())
cal.add_component(event)
booking_agent = Agent(
tools=[mcp_tools],
name="Booking Agent",
model=OpenAIChat(id="gpt-4o-mini", api_key=openai_key),
goal="""As a Booking Agent, your responsibilities include:
1. Finding accommodations within budget on airbnb
2. Comparing prices across platforms
3. Checking availability for specific dates
4. Verifying amenities and policies
5. Finding last-minute deals when applicable
Always consider:
- Location convenience
- Price competitiveness
- Cancellation policies
- Guest reviews and ratings
- Amenities matching preferences
- Special requirements or accessibility needs"""
)
return cal.to_ical()
calendar_agent = Agent(
tools=[mcp_tools],
name="Calendar Agent",
model=OpenAIChat(id="gpt-4o-mini", api_key=openai_key),
goal="""As a Calendar Agent, your responsibilities include:
1. Creating detailed travel itineraries
2. Setting reminders for bookings and check-ins
3. Scheduling activities and reservations
4. Adding reminders for booking deadlines, check-ins, and other important events.
5. Coordinating with other team members' schedules
Always consider:
- Time zone differences
- Travel duration between activities
- Buffer time for unexpected delays
- Important deadlines and check-in times
- Synchronization with other team members"""
)
async def run_mcp_travel_planner(destination: str, num_days: int, preferences: str, budget: int, openai_key: str, google_maps_key: str):
"""Run the MCP-based travel planner agent with real-time data access."""
team = Team(
members=[maps_agent, weather_agent, booking_agent, calendar_agent],
name="Travel Planning Team",
try:
# Set Google Maps API key environment variable
os.environ["GOOGLE_MAPS_API_KEY"] = google_maps_key
# Initialize MCPTools with Airbnb MCP
mcp_tools = MultiMCPTools(
[
"npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt",
"npx @gongrzhe/server-travelplanner-mcp",
],
env={
"GOOGLE_MAPS_API_KEY": google_maps_key,
},
timeout_seconds=60,
)
# Connect to Airbnb MCP server
await mcp_tools.connect()
travel_planner = Agent(
name="Travel Planner",
role="Creates travel itineraries using Airbnb, Google Maps, and Google Search",
model=OpenAIChat(id="gpt-4o", api_key=openai_key),
description=dedent(
"""\
You are a professional travel consultant AI that creates highly detailed travel itineraries directly without asking questions.
You have access to:
🏨 Airbnb listings with real availability and current pricing
🗺️ Google Maps MCP for location services, directions, distance calculations, and local navigation
🔍 Web search capabilities for current information, reviews, and travel updates
ALWAYS create a complete, detailed itinerary immediately without asking for clarification or additional information.
Use Google Maps MCP extensively to calculate distances between all locations and provide precise travel times.
If information is missing, use your best judgment and available tools to fill in the gaps.
"""
),
instructions=[
"IMPORTANT: Never ask questions or request clarification - always generate a complete itinerary",
"Research the destination thoroughly using all available tools to gather comprehensive current information",
"Find suitable accommodation options within the budget using Airbnb MCP with real prices and availability",
"Create an extremely detailed day-by-day itinerary with specific activities, locations, exact timing, and distances",
"Use Google Maps MCP extensively to calculate distances between ALL locations and provide travel times",
"Include detailed transportation options and turn-by-turn navigation tips using Google Maps MCP",
"Research dining options with specific restaurant names, addresses, price ranges, and distance from accommodation",
"Check current weather conditions, seasonal factors, and provide detailed packing recommendations",
"Calculate precise estimated costs for EVERY aspect of the trip and ensure recommendations fit within budget",
"Include detailed information about each attraction: opening hours, ticket prices, best visiting times, and distance from accommodation",
"Add practical information including local transportation costs, currency exchange, safety tips, and cultural norms",
"Structure the itinerary with clear sections, detailed timing for each activity, and include buffer time between activities",
"Use all available tools proactively without asking for permission",
"Generate the complete, detailed itinerary in one response without follow-up questions"
],
tools=[mcp_tools, GoogleSearchTools()],
add_datetime_to_instructions=True,
markdown=True,
show_tool_calls=True,
instructions="""As a Travel Planning Team, coordinate to create comprehensive travel plans:
1. Share information between agents to ensure consistency
2. Consider dependencies between different aspects of the trip
3. Prioritize user preferences and constraints
4. Provide backup options when primary choices are unavailable
5. Maintain a balance between planned activities and free time
6. Consider local events and seasonal factors
7. Ensure all recommendations align with the user's budget
8. Provide a detailed breakdown of the trip, including bookings, routes, weather, and planned activities.
9. Add the journey start date in the user calendar"""
show_tool_calls=False,
)
result = await team.arun(message)
output = result.messages[-1].content
return output
# Create the planning prompt
prompt = f"""
IMMEDIATELY create an extremely detailed and comprehensive travel itinerary for:
**Destination:** {destination}
**Duration:** {num_days} days
**Budget:** ${budget} USD total
**Preferences:** {preferences}
DO NOT ask any questions. Generate a complete, highly detailed itinerary now using all available tools.
**CRITICAL REQUIREMENTS:**
- Use Google Maps MCP to calculate distances and travel times between ALL locations
- Include specific addresses for every location, restaurant, and attraction
- Provide detailed timing for each activity with buffer time between locations
- Calculate precise costs for transportation between each location
- Include opening hours, ticket prices, and best visiting times for all attractions
- Provide detailed weather information and specific packing recommendations
**REQUIRED OUTPUT FORMAT:**
1. **Trip Overview** - Summary, total estimated cost breakdown, detailed weather forecast
2. **Accommodation** - 3 specific Airbnb options with real prices, addresses, amenities, and distance from city center
3. **Transportation Overview** - Detailed transportation options, costs, and recommendations
4. **Day-by-Day Itinerary** - Extremely detailed schedule with:
- Specific start/end times for each activity
- Exact distances and travel times between locations (use Google Maps MCP)
- Detailed descriptions of each location with addresses
- Opening hours, ticket prices, and best visiting times
- Estimated costs for each activity and transportation
- Buffer time between activities for unexpected delays
5. **Dining Plan** - Specific restaurants with addresses, price ranges, cuisine types, and distance from accommodation
6. **Detailed Practical Information**:
- Weather forecast with clothing recommendations
- Currency exchange rates and costs
- Local transportation options and costs
- Safety information and emergency contacts
- Cultural norms and etiquette tips
- Communication options (SIM cards, WiFi, etc.)
- Health and medical considerations
- Shopping and souvenir recommendations
Use Airbnb MCP for real accommodation data, Google Maps MCP for ALL distance calculations and location services, and web search for current information.
Make reasonable assumptions and fill in any gaps with your knowledge.
Generate the complete, highly detailed itinerary in one response without asking for clarification.
"""
response = await travel_planner.arun(prompt)
return response.content
finally:
await mcp_tools.close()
def run_travel_planner(destination: str, num_days: int, preferences: str, budget: int, openai_key: str, google_maps_key: str):
"""Synchronous wrapper for the async MCP travel planner."""
return asyncio.run(run_mcp_travel_planner(destination, num_days, preferences, budget, openai_key, google_maps_key))
# -------------------- Streamlit App --------------------
# Configure the page
st.set_page_config(
page_title="AI Travel Planner",
page_title="MCP AI Travel Planner",
page_icon="✈️",
layout="wide"
)
# Add sidebar for API keys
with st.sidebar:
st.header("🔑 API Keys Configuration")
st.markdown("Please enter your API keys to use the travel planner.")
# Initialize session state for API keys if not exists
if 'google_maps_key' not in st.session_state:
st.session_state.google_maps_key = ""
if 'accuweather_key' not in st.session_state:
st.session_state.accuweather_key = ""
if 'openai_key' not in st.session_state:
st.session_state.openai_key = ""
if 'google_client_id' not in st.session_state:
st.session_state.google_client_id = ""
if 'google_client_secret' not in st.session_state:
st.session_state.google_client_secret = ""
if 'google_refresh_token' not in st.session_state:
st.session_state.google_refresh_token = ""
# API key input fields
st.session_state.google_maps_key = st.text_input(
"Google Maps API Key",
value=st.session_state.google_maps_key,
type="password"
)
st.session_state.accuweather_key = st.text_input(
"AccuWeather API Key",
value=st.session_state.accuweather_key,
type="password"
)
st.session_state.openai_key = st.text_input(
"OpenAI API Key",
value=st.session_state.openai_key,
type="password"
)
st.session_state.google_client_id = st.text_input(
"Google Client ID",
value=st.session_state.google_client_id,
type="password"
)
st.session_state.google_client_secret = st.text_input(
"Google Client Secret",
value=st.session_state.google_client_secret,
type="password"
)
st.session_state.google_refresh_token = st.text_input(
"Google Refresh Token",
value=st.session_state.google_refresh_token,
type="password"
)
# Check if all API keys are filled
all_keys_filled = all([
st.session_state.google_maps_key,
st.session_state.accuweather_key,
st.session_state.openai_key,
st.session_state.google_client_id,
st.session_state.google_client_secret,
st.session_state.google_refresh_token
])
if not all_keys_filled:
st.warning("⚠️ Please fill in all API keys to use the travel planner.")
else:
st.success("✅ All API keys are configured!")
# Initialize session state
if 'itinerary' not in st.session_state:
st.session_state.itinerary = None
# Title and description
st.title("✈️ AI Travel Planner")
st.markdown("""
This AI-powered travel planner helps you create personalized travel itineraries using:
- 🗺️ Maps and navigation
- 🌤️ Weather forecasts
- 🏨 Accommodation booking
- 📅 Calendar management
""")
st.title("✈️ MCP AI Travel Planner")
st.caption("Plan your next adventure with AI Travel Planner using MCP servers for real-time data access")
# Create two columns for input
col1, col2 = st.columns(2)
# Sidebar for API keys
with st.sidebar:
st.header("🔑 API Keys Configuration")
st.warning("⚠️ These services require API keys:")
with col1:
# Source and Destination
source = st.text_input("Source", placeholder="Enter your departure city")
destination = st.text_input("Destination", placeholder= "Enter your destination city")
# Travel Dates
travel_dates = st.date_input(
"Travel Dates",
[date.today(), date.today()],
min_value=date.today(),
help="Select your travel dates"
openai_api_key = st.text_input("OpenAI API Key", type="password", help="Required for AI planning")
google_maps_key = st.text_input("Google Maps API Key", type="password", help="Required for location services")
# Check if API keys are provided (both OpenAI and Google Maps are required)
api_keys_provided = openai_api_key and google_maps_key
if api_keys_provided:
st.success("✅ All API keys configured!")
else:
st.warning("⚠️ Please enter both API keys to use the travel planner.")
st.info("""
**Required API Keys:**
- **OpenAI API Key**: https://platform.openai.com/api-keys
- **Google Maps API Key**: https://console.cloud.google.com/apis/credentials (for location services)
""")
# Main content (only shown if API keys are provided)
if api_keys_provided:
# Main input section
st.header("🌍 Trip Details")
col1, col2 = st.columns(2)
with col1:
destination = st.text_input("Destination", placeholder="e.g., Paris, Tokyo, New York")
num_days = st.number_input("Number of Days", min_value=1, max_value=30, value=7)
with col2:
budget = st.number_input("Budget (USD)", min_value=100, max_value=10000, step=100, value=2000)
start_date = st.date_input("Start Date", min_value=date.today(), value=date.today())
# Preferences section
st.subheader("🎯 Travel Preferences")
preferences_input = st.text_area(
"Describe your travel preferences",
placeholder="e.g., adventure activities, cultural sites, food, relaxation, nightlife...",
height=100
)
with col2:
# Budget
budget = st.number_input(
"Budget (in USD)",
min_value=0,
max_value=10000,
step=100,
help="Enter your total budget for the trip"
)
# Travel Preferences
travel_preferences = st.multiselect(
"Travel Preferences",
["Adventure", "Relaxation", "Sightseeing", "Cultural Experiences",
# Quick preference buttons
quick_prefs = st.multiselect(
"Quick Preferences (optional)",
["Adventure", "Relaxation", "Sightseeing", "Cultural Experiences",
"Beach", "Mountain", "Luxury", "Budget-Friendly", "Food & Dining",
"Shopping", "Nightlife", "Family-Friendly"],
help="Select your travel preferences"
help="Select multiple preferences or describe in detail above"
)
# Additional preferences
st.subheader("Additional Preferences")
col3, col4 = st.columns(2)
# Combine preferences
all_preferences = []
if preferences_input:
all_preferences.append(preferences_input)
if quick_prefs:
all_preferences.extend(quick_prefs)
with col3:
accommodation_type = st.selectbox(
"Preferred Accommodation",
["Any", "Hotel", "Hostel", "Apartment", "Resort"],
help="Select your preferred type of accommodation"
)
transportation_mode = st.multiselect(
"Preferred Transportation",
["Train", "Bus", "Flight", "Rental Car"],
help="Select your preferred modes of transportation"
)
preferences = ", ".join(all_preferences) if all_preferences else "General sightseeing"
with col4:
dietary_restrictions = st.multiselect(
"Dietary Restrictions",
["None", "Vegetarian", "Vegan", "Gluten-Free", "Halal", "Kosher"],
help="Select any dietary restrictions"
)
# Generate button
col1, col2 = st.columns([1, 1])
# Submit Button
if st.button("Plan My Trip", type="primary", disabled=not all_keys_filled):
if not source or not destination:
st.error("Please enter both source and destination cities.")
elif not travel_preferences:
st.warning("Consider selecting some travel preferences for better recommendations.")
else:
# Create a loading spinner
with st.spinner("🤖 AI Agents are planning your perfect trip..."):
try:
# Construct the message for the agents
message = f"""
Plan a trip with the following details:
- From: {source}
- To: {destination}
- Dates: {travel_dates[0]} to {travel_dates[1]}
- Budget in USD: ${budget}
- Preferences: {', '.join(travel_preferences)}
- Accommodation: {accommodation_type}
- Transportation: {', '.join(transportation_mode)}
- Dietary Restrictions: {', '.join(dietary_restrictions)}
Please provide a comprehensive travel plan including:
1. Recommended accommodations
2. Daily itinerary with activities
3. Transportation options
4. The Expected Day Weather
5. Estimated cost of the Trip
6. Add the Departure Date to the calendar
"""
# Run the agents
response = asyncio.run(run_agent(message))
# Display the response
st.success("✅ Your travel plan is ready!")
st.markdown(response)
except Exception as e:
st.error(f"An error occurred while planning your trip: {str(e)}")
st.info("Please try again or contact support if the issue persists.")
with col1:
if st.button("🎯 Generate Itinerary", type="primary"):
if not destination:
st.error("Please enter a destination.")
elif not preferences:
st.warning("Please describe your preferences or select quick preferences.")
else:
tools_message = "🏨 Connecting to Airbnb MCP"
if google_maps_key:
tools_message += " and Google Maps MCP"
tools_message += ", creating itinerary..."
# Add a footer
st.markdown("---")
st.markdown("""
<div style='text-align: center'>
<p>Powered by AI Travel Planning Agents</p>
<p>Your personal travel assistant for creating memorable experiences</p>
</div>
""", unsafe_allow_html=True)
with st.spinner(tools_message):
try:
# Calculate number of days from start date
response = run_travel_planner(
destination=destination,
num_days=num_days,
preferences=preferences,
budget=budget,
openai_key=openai_api_key,
google_maps_key=google_maps_key or ""
)
# Store the response in session state
st.session_state.itinerary = response
# Show MCP connection status
if "Airbnb" in response and ("listing" in response.lower() or "accommodation" in response.lower()):
st.success("✅ Your travel itinerary is ready with Airbnb data!")
st.info("🏨 Used real Airbnb listings for accommodation recommendations")
else:
st.success("✅ Your travel itinerary is ready!")
st.info("📝 Used general knowledge for accommodation suggestions (Airbnb MCP may have failed to connect)")
except Exception as e:
st.error(f"Error: {str(e)}")
st.info("Please try again or check your internet connection.")
with col2:
if st.session_state.itinerary:
# Generate the ICS file
ics_content = generate_ics_content(st.session_state.itinerary, datetime.combine(start_date, datetime.min.time()))
# Provide the file for download
st.download_button(
label="📅 Download as Calendar",
data=ics_content,
file_name="travel_itinerary.ics",
mime="text/calendar"
)
# Display itinerary
if st.session_state.itinerary:
st.header("📋 Your Travel Itinerary")
st.markdown(st.session_state.itinerary)

View File

@@ -1,132 +0,0 @@
#!/usr/bin/env python
import os
import json
import sys
import logging
from dotenv import load_dotenv
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from mcp.server.fastmcp import FastMCP
load_dotenv()
logging.basicConfig(
level=logging.DEBUG,
format='DEBUG: %(asctime)s - %(message)s',
stream=sys.stderr
)
logger = logging.getLogger(__name__)
mcp = FastMCP("Google Calendar MCP", dependencies=["python-dotenv", "google-api-python-client", "google-auth", "google-auth-oauthlib"])
GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
GOOGLE_CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET")
GOOGLE_REFRESH_TOKEN = os.getenv("GOOGLE_REFRESH_TOKEN")
if not GOOGLE_CLIENT_ID or not GOOGLE_CLIENT_SECRET or not GOOGLE_REFRESH_TOKEN:
logger.error("Error: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_REFRESH_TOKEN environment variables are required")
sys.exit(1)
@mcp.tool()
async def create_event(
summary: str,
start_time: str,
end_time: str,
description: str = None,
location: str = None,
attendees: list = None,
reminders: dict = None
) -> str:
"""Create a calendar event with specified details
Args:
summary: Event title
start_time: Start time (ISO format)
end_time: End time (ISO format)
description: Event description
location: Event location
attendees: List of attendee emails
reminders: Reminder settings for the event
Returns:
String with event creation confirmation and link
"""
logger.debug(f'Creating calendar event with args: {locals()}')
try:
logger.debug('Creating OAuth2 client')
# Google OAuth2
creds = Credentials(
None,
refresh_token=GOOGLE_REFRESH_TOKEN,
token_uri="https://oauth2.googleapis.com/token",
client_id=GOOGLE_CLIENT_ID,
client_secret=GOOGLE_CLIENT_SECRET
)
logger.debug('OAuth2 client created')
logger.debug('Creating calendar service')
calendar_service = build('calendar', 'v3', credentials=creds)
logger.debug('Calendar service created')
event = {
'summary': summary,
'start': {
'dateTime': start_time,
'timeZone': 'Asia/Seoul'
},
'end': {
'dateTime': end_time,
'timeZone': 'Asia/Seoul'
}
}
if description:
event['description'] = description
if location:
event['location'] = location
logger.debug(f'Location added: {location}')
if attendees:
event['attendees'] = [{'email': email} for email in attendees]
logger.debug(f'Attendees added: {event["attendees"]}')
if reminders:
event['reminders'] = reminders
logger.debug(f'Custom reminders set: {json.dumps(reminders)}')
else:
event['reminders'] = {
'useDefault': False,
'overrides': [
{'method': 'popup', 'minutes': 10}
]
}
logger.debug(f'Default reminders set: {json.dumps(event["reminders"])}')
logger.debug('Attempting to insert event')
response = calendar_service.events().insert(calendarId='primary', body=event).execute()
logger.debug(f'Event insert response: {json.dumps(response)}')
return f"Event created: {response.get('htmlLink', 'No link available')}"
except Exception as error:
logger.debug(f'ERROR OCCURRED:')
logger.debug(f'Error type: {type(error).__name__}')
logger.debug(f'Error message: {str(error)}')
import traceback
logger.debug(f'Error traceback: {traceback.format_exc()}')
raise Exception(f"Failed to create event: {str(error)}")
def main():
"""Run the MCP calendar server."""
try:
mcp.run()
except KeyboardInterrupt:
logger.info("Server stopped by user")
except Exception as e:
logger.error(f"Fatal error running server: {e}")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -1,9 +1,5 @@
agno>=1.3.0
mcp>=1.7.0
streamlit==1.44.1
google-api-python-client==2.118.0
google-auth==2.28.1
google-auth-oauthlib==1.2.0
python-dotenv==1.0.1
requests==2.31.0
openai>=1.50.0
streamlit
agno
openai
icalendar
google-search-results