From 293c35629f69d9da2b8169dad4c3c6df81459ca1 Mon Sep 17 00:00:00 2001 From: priyanshm07 Date: Tue, 8 Apr 2025 15:27:47 +0530 Subject: [PATCH 1/4] fix : code updated --- .../README.md | 43 +++++++++++++ .../ai_travel_planner_mcp_agent_team/app.py | 60 +++++++++++++++++++ .../requirements.txt | 3 + 3 files changed, 106 insertions(+) create mode 100644 mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md create mode 100644 mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py create mode 100644 mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md new file mode 100644 index 0000000..9d9abd1 --- /dev/null +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md @@ -0,0 +1,43 @@ +# 🌍 AI Travel Planner β€” MCP Agent Team (Airbnb, Google Maps, Weather) + +This project is a *multi-agent travel planning assistant* built using [Agno](https://github.com/agnodice/agno), powered by multiple [Model Context Protocol (MCP)](https://modelcontextprotocol.org/) tools. It integrates: + +‒⁠ ⁠🏠 *Airbnb Listings* +‒⁠ β πŸ—ΊοΈ *Google Maps for routing and places* +‒⁠ ⁠🌦️ *Weather information via AccuWeather* +‒⁠ β πŸ“… (Optional) *Google Calendar integration via Gumloop MCP* + +All handled through a simple terminal interface powered by Python + asyncio. + +--- + +## βš™οΈ Requirements + +‒⁠ ⁠Python 3.10+ +‒⁠ ⁠Node.js + ⁠ npx ⁠ +‒⁠ ⁠[uvx](https://github.com/uvx/cli) for running MCP servers from Git +‒⁠ ⁠Internet access for MCP calls + +--- + +## πŸ“¦ Installation + +1.⁠ ⁠*Clone the repo* + +⁠ bash +git clone https://github.com/yourusername/ai-travel-planner.git +cd ai-travel-planner + ⁠ + +1.⁠ ⁠*Create Virtual Env* + +conda create -n env_name python=3.10 -y +conda activate env_name +pip install -r requirements.txt + + +1.⁠ ⁠*Create env file* + +GOOGLE_MAPS_API_KEY=your_google_maps_api_key +ACCUWEATHER_API_KEY=your_accuweather_api_key +OPENAI_API_KEY=your_openai_api_key diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py new file mode 100644 index 0000000..4bcee2e --- /dev/null +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py @@ -0,0 +1,60 @@ +import asyncio +import os + +from agno.agent import Agent +from agno.tools.mcp import MultiMCPTools +import streamlit as st + +from dotenv import load_dotenv +load_dotenv() + +async def run_agent(message: str) -> None: + """Run the Airbnb, Google Maps, Weather agent with the given message.""" + + google_maps_key = os.getenv("GOOGLE_MAPS_API_KEY") + accuweather_key = os.getenv("ACCUWEATHER_API_KEY") + openai_key = os.getenv("OPENAI_API_KEY") + if not google_maps_key: + raise ValueError("🚨 Missing GOOGLE_MAPS_API_KEY in environment variables.") + elif not accuweather_key: + raise ValueError("🚨 Missing ACCUWEATHER_API_KEY in environment variables.") + elif not openai_key: + raise ValueError("🚨 Missing OPENAI_API_KEY in environment variables.") + env = { + **os.environ, + "GOOGLE_MAPS_API_KEY": os.getenv("GOOGLE_MAPS_API_KEY"), + "ACCUWEATHER_API_KEY": os.getenv("ACCUWEATHER_API_KEY"), + "OPENAI_API_KEY": os.getenv("OPENAI_API_KEY") + } + + 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 + # "https://www.gumloop.com/mcp/gcalendar", + + ], + env=env, + ) as mcp_tools: + agent = Agent( + tools=[mcp_tools], + markdown=True, + show_tool_calls=True, + ) + + await agent.aprint_response(message, stream=True) + +# -------------------- Terminal Interaction Loop -------------------- + +if _name_ == "_main_": # type: ignore + print("🌍 Travel Planning Agent β€” Airbnb, Maps, Weather, Calendar (type 'exit' to quit)\n") + try: + while True: + user_input = input("You: ") + if user_input.lower() in ["exit", "quit"]: + print("πŸ‘‹ Bye!") + break + asyncio.run(run_agent(user_input)) + except KeyboardInterrupt: + print("\nπŸ‘‹ Interrupted. Exiting...") \ No newline at end of file diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt new file mode 100644 index 0000000..9c07722 --- /dev/null +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt @@ -0,0 +1,3 @@ +agno==1.2.13 +mcp==1.6.0 +streamlit==1.44.1 \ No newline at end of file From e4cea90a188eb187903a81229d3a02dfeb1a3458 Mon Sep 17 00:00:00 2001 From: priyanshm07 Date: Tue, 8 Apr 2025 17:46:54 +0530 Subject: [PATCH 2/4] feature : agno multi-agent implementation --- .../README.md | 20 +++++++++-- .../ai_travel_planner_mcp_agent_team/app.py | 33 ++++++++++++++++--- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md index 9d9abd1..e7b0fe9 100644 --- a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md @@ -29,15 +29,31 @@ git clone https://github.com/yourusername/ai-travel-planner.git cd ai-travel-planner  ⁠ -1.⁠ ⁠*Create Virtual Env* +2.⁠ ⁠*Create Virtual Env* conda create -n env_name python=3.10 -y conda activate env_name pip install -r requirements.txt -1.⁠ ⁠*Create env file* +3.⁠ ⁠*Create env file* GOOGLE_MAPS_API_KEY=your_google_maps_api_key ACCUWEATHER_API_KEY=your_accuweather_api_key OPENAI_API_KEY=your_openai_api_key + + +--- + +## 🧠 Built With +-- Agno + +-- FastMCP + +-- OpenAI + +-- Google Maps Platform + +-- Airbnb MCP + +-- Accuweather \ No newline at end of file diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py index 4bcee2e..7b465de 100644 --- a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py @@ -2,6 +2,7 @@ import asyncio import os from agno.agent import Agent +from agno.team.team import Team from agno.tools.mcp import MultiMCPTools import streamlit as st @@ -37,17 +38,39 @@ async def run_agent(message: str) -> None: ], env=env, ) as mcp_tools: - agent = Agent( + + #Define sepcialized agents + maps_agent = Agent( tools=[mcp_tools], - markdown=True, - show_tool_calls=True, + name="Maps Agent", + goal="Integrates with Google Maps server to provide routing information, travel time estimates, and points of interest proximity analysis" ) - await agent.aprint_response(message, stream=True) + weather_agent = Agent( + tools=[mcp_tools], + name="Weather Agent", + goal="Pulls data from OpenWeatherMap to provide weather forecasts for planned dates and locations, allowing for weather-appropriate activity planning." + ) + + booking_agent = Agent( + tools=[mcp_tools], + name="Booking Agent", + goal="Connects to Booking.com and Airbnb APIs to search and filter accommodations based on user preferences (price range, amenities, location)" + ) + + team = Team( + members=[maps_agent, weather_agent, booking_agent], + name="Travel Planning Team", + markdown=True, + show_tool_calls=True + ) + + await team.aprint_response(message, stream=True) # -------------------- Terminal Interaction Loop -------------------- -if _name_ == "_main_": # type: ignore +if __name__ == "__main__": # βœ… correct + print("🌍 Travel Planning Agent β€” Airbnb, Maps, Weather, Calendar (type 'exit' to quit)\n") try: while True: From d8f27f6d4b37c2bde1228e370c0f5032a5eced45 Mon Sep 17 00:00:00 2001 From: priyanshm07 Date: Tue, 8 Apr 2025 18:32:50 +0530 Subject: [PATCH 3/4] update : calendar mcp linked --- .../README.md | 30 +++- .../ai_travel_planner_mcp_agent_team/app.py | 15 +- .../calendar_mcp.py | 132 ++++++++++++++++++ .../generate_token.py | 21 +++ .../requirements.txt | 5 +- 5 files changed, 196 insertions(+), 7 deletions(-) create mode 100755 mcp_ai_agents/ai_travel_planner_mcp_agent_team/calendar_mcp.py create mode 100644 mcp_ai_agents/ai_travel_planner_mcp_agent_team/generate_token.py diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md index e7b0fe9..30d924e 100644 --- a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md @@ -41,8 +41,6 @@ pip install -r requirements.txt GOOGLE_MAPS_API_KEY=your_google_maps_api_key ACCUWEATHER_API_KEY=your_accuweather_api_key OPENAI_API_KEY=your_openai_api_key - - --- ## 🧠 Built With @@ -56,4 +54,30 @@ OPENAI_API_KEY=your_openai_api_key -- Airbnb MCP --- Accuweather \ No newline at end of file +-- Accuweather + +--- + +## πŸ“… Calendar MCP Server (`calendar_mcp.py`) + +This script is a dedicated MCP (Modular Cognitive Process) server that integrates with **Google Calendar** to create events via API calls. It works seamlessly with the rest of the multi-agent system built with Agno and FastMCP. + +--- + +### πŸ›  Features + +- Creates Google Calendar events using the `create_event` tool +- Accepts event title, description, date/time, location, attendees, and reminders +- Uses a refresh token for persistent access (no re-authentication needed) + +--- + +### 🌱 Setup + +Add the following to your `.env` file in the root directory: + +```env +GOOGLE_CLIENT_ID=your_google_client_id +GOOGLE_CLIENT_SECRET=your_google_client_secret +GOOGLE_REFRESH_TOKEN=your_refresh_token +``` \ No newline at end of file diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py index 7b465de..bdcd985 100644 --- a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py @@ -10,17 +10,20 @@ from dotenv import load_dotenv load_dotenv() async def run_agent(message: str) -> None: - """Run the Airbnb, Google Maps, Weather agent with the given message.""" + """Run the Airbnb, Google Maps, Weather and Calendar agent with the given message.""" google_maps_key = os.getenv("GOOGLE_MAPS_API_KEY") accuweather_key = os.getenv("ACCUWEATHER_API_KEY") openai_key = os.getenv("OPENAI_API_KEY") + google_maps_key = os.getenv("GOOGLE_CLIENT_ID") if not google_maps_key: raise ValueError("🚨 Missing GOOGLE_MAPS_API_KEY in environment variables.") elif not accuweather_key: raise ValueError("🚨 Missing ACCUWEATHER_API_KEY in environment variables.") elif not openai_key: raise ValueError("🚨 Missing OPENAI_API_KEY in environment variables.") + elif not google_maps_key: + raise ValueError("🚨 Missing GOOGLE_CLIENT_ID in environment variables.") env = { **os.environ, "GOOGLE_MAPS_API_KEY": os.getenv("GOOGLE_MAPS_API_KEY"), @@ -33,7 +36,7 @@ async def run_agent(message: str) -> None: "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 - # "https://www.gumloop.com/mcp/gcalendar", + "/Users/priyanshmaheshwari/Desktop/EchovibeLabs/awesome-llm-apps/mcp_ai_agents/ai_travel_planner_mcp_agent_team/calendar_mcp.py" # βœ… Calendar mcp added ], env=env, @@ -58,8 +61,14 @@ async def run_agent(message: str) -> None: goal="Connects to Booking.com and Airbnb APIs to search and filter accommodations based on user preferences (price range, amenities, location)" ) + calendar_agent = Agent( + tools=[mcp_tools], + name="Calendar Agent", + goal="Creates calendar events for travel plans, including reminders and location details." + ) + team = Team( - members=[maps_agent, weather_agent, booking_agent], + members=[maps_agent, weather_agent, booking_agent, calendar_agent], name="Travel Planning Team", markdown=True, show_tool_calls=True diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/calendar_mcp.py b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/calendar_mcp.py new file mode 100755 index 0000000..f37319e --- /dev/null +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/calendar_mcp.py @@ -0,0 +1,132 @@ +#!/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() \ No newline at end of file diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/generate_token.py b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/generate_token.py new file mode 100644 index 0000000..6fe9f83 --- /dev/null +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/generate_token.py @@ -0,0 +1,21 @@ +from google_auth_oauthlib.flow import InstalledAppFlow +from dotenv import load_dotenv +import os + +load_dotenv() # Loads from .env + +SCOPES = ['https://www.googleapis.com/auth/calendar'] + +flow = InstalledAppFlow.from_client_config({ + "installed": { + "client_id": os.getenv("GOOGLE_CLIENT_ID"), + "client_secret": os.getenv("GOOGLE_CLIENT_SECRET"), + "redirect_uris": ["urn:ietf:wg:oauth:2.0:oob"], + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token" + } +}, SCOPES) + +creds = flow.run_local_server(port=0) +print("\n=== REFRESH TOKEN ===\n") +print(creds.refresh_token) diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt index 9c07722..75b6922 100644 --- a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt @@ -1,3 +1,6 @@ agno==1.2.13 mcp==1.6.0 -streamlit==1.44.1 \ No newline at end of file +streamlit==1.44.1 +google-api-python-client +google-auth +google-auth-oauthlib \ No newline at end of file From cae82dc8b88bf5e07629eff4cce39c992c51a728 Mon Sep 17 00:00:00 2001 From: priyanshm07 Date: Sun, 20 Apr 2025 07:08:20 +0530 Subject: [PATCH 4/4] Update : Streamlit app created --- .../README.md | 149 +++++--- .../ai_travel_planner_mcp_agent_team/app.py | 336 ++++++++++++++++-- .../generate_token.py | 21 -- .../requirements.txt | 9 +- 4 files changed, 398 insertions(+), 117 deletions(-) delete mode 100644 mcp_ai_agents/ai_travel_planner_mcp_agent_team/generate_token.py diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md index 30d924e..9b56b3e 100644 --- a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/README.md @@ -1,83 +1,118 @@ -# 🌍 AI Travel Planner β€” MCP Agent Team (Airbnb, Google Maps, Weather) +## 🌍 AI Travel Planner Agent -This project is a *multi-agent travel planning assistant* built using [Agno](https://github.com/agnodice/agno), powered by multiple [Model Context Protocol (MCP)](https://modelcontextprotocol.org/) tools. It integrates: +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. -‒⁠ ⁠🏠 *Airbnb Listings* -‒⁠ β πŸ—ΊοΈ *Google Maps for routing and places* -‒⁠ ⁠🌦️ *Weather information via AccuWeather* -‒⁠ β πŸ“… (Optional) *Google Calendar integration via Gumloop MCP* +## Features +## MCP Servers Integration -All handled through a simple terminal interface powered by Python + asyncio. +This project utilizes several MCP (Model Context Protocol) servers to provide a comprehensive travel planning experience: ---- +### 1. Weather MCP Server +- **Functionality**: Provides real-time weather data and forecasts -## βš™οΈ Requirements +### 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 -‒⁠ ⁠Python 3.10+ -‒⁠ ⁠Node.js + ⁠ npx ⁠ -‒⁠ ⁠[uvx](https://github.com/uvx/cli) for running MCP servers from Git -‒⁠ ⁠Internet access for MCP calls +### 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` ---- - -## πŸ“¦ Installation - -1.⁠ ⁠*Clone the repo* - -⁠ bash -git clone https://github.com/yourusername/ai-travel-planner.git -cd ai-travel-planner - ⁠ - -2.⁠ ⁠*Create Virtual Env* - -conda create -n env_name python=3.10 -y -conda activate env_name -pip install -r requirements.txt +### 4. Booking MCP Server +- **Functionality**: Airbnb MCP server used -3.⁠ ⁠*Create env file* +## Setup -GOOGLE_MAPS_API_KEY=your_google_maps_api_key -ACCUWEATHER_API_KEY=your_accuweather_api_key -OPENAI_API_KEY=your_openai_api_key ---- +### Requirements -## 🧠 Built With --- Agno +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. --- FastMCP +2. **Python 3.8+**: Ensure you have Python 3.8 or higher installed. --- OpenAI +### Installation --- Google Maps Platform +1. Clone this repository: + ```bash + git clone https://github.com/yourusername/ai_travel_planner_mcp_agent_team + cd ai_travel_planner_mcp_agent_team + ``` --- Airbnb MCP +2. Install the required Python packages: + ```bash + pip install -r requirements.txt + ``` --- Accuweather +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 -## πŸ“… Calendar MCP Server (`calendar_mcp.py`) +1. Generate OAuth token for Google Calendar -This script is a dedicated MCP (Modular Cognitive Process) server that integrates with **Google Calendar** to create events via API calls. It works seamlessly with the rest of the multi-agent system built with Agno and FastMCP. +2. 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 -### πŸ›  Features +## Project Structure -- Creates Google Calendar events using the `create_event` tool -- Accepts event title, description, date/time, location, attendees, and reminders -- Uses a refresh token for persistent access (no re-authentication needed) +- `app.py`: Main Streamlit application +- `calendar_mcp.py`: Calendar mcp integration functionality +- `requirements.txt`: Project dependencies +- `.env`: Environment variables ---- +## Calendar MCP Integration -### 🌱 Setup +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: -Add the following to your `.env` file in the root directory: +- **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 -```env -GOOGLE_CLIENT_ID=your_google_client_id -GOOGLE_CLIENT_SECRET=your_google_client_secret -GOOGLE_REFRESH_TOKEN=your_refresh_token -``` \ No newline at end of file +### 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'} + } + ``` diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py index bdcd985..585360a 100644 --- a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/app.py @@ -4,31 +4,49 @@ import os from agno.agent import Agent from agno.team.team import Team from agno.tools.mcp import MultiMCPTools +from agno.models.openai import OpenAIChat import streamlit as st +from datetime import date -from dotenv import load_dotenv -load_dotenv() +# Remove dotenv import and loading since we'll use sidebar +# from dotenv import load_dotenv +# load_dotenv() -async def run_agent(message: str) -> None: +async def run_agent(message: str): """Run the Airbnb, Google Maps, Weather and Calendar agent with the given message.""" - google_maps_key = os.getenv("GOOGLE_MAPS_API_KEY") - accuweather_key = os.getenv("ACCUWEATHER_API_KEY") - openai_key = os.getenv("OPENAI_API_KEY") - google_maps_key = os.getenv("GOOGLE_CLIENT_ID") + # 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') + if not google_maps_key: - raise ValueError("🚨 Missing GOOGLE_MAPS_API_KEY in environment variables.") + raise ValueError("🚨 Missing Google Maps API Key. Please enter it in the sidebar.") elif not accuweather_key: - raise ValueError("🚨 Missing ACCUWEATHER_API_KEY in environment variables.") + raise ValueError("🚨 Missing AccuWeather API Key. Please enter it in the sidebar.") elif not openai_key: - raise ValueError("🚨 Missing OPENAI_API_KEY in environment variables.") - elif not google_maps_key: - raise ValueError("🚨 Missing GOOGLE_CLIENT_ID in environment variables.") + 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.") + + # πŸ‘‰ Set OPENAI_API_KEY globally + os.environ["OPENAI_API_KEY"] = openai_key + env = { **os.environ, - "GOOGLE_MAPS_API_KEY": os.getenv("GOOGLE_MAPS_API_KEY"), - "ACCUWEATHER_API_KEY": os.getenv("ACCUWEATHER_API_KEY"), - "OPENAI_API_KEY": os.getenv("OPENAI_API_KEY") + "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 } async with MultiMCPTools( @@ -36,57 +54,303 @@ async def run_agent(message: str) -> None: "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 - "/Users/priyanshmaheshwari/Desktop/EchovibeLabs/awesome-llm-apps/mcp_ai_agents/ai_travel_planner_mcp_agent_team/calendar_mcp.py" # βœ… Calendar mcp added - + "./calendar_mcp.py" ], env=env, ) as mcp_tools: - #Define sepcialized agents + #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="Integrates with Google Maps server to provide routing information, travel time estimates, and points of interest proximity analysis" + 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""" ) weather_agent = Agent( tools=[mcp_tools], name="Weather Agent", - goal="Pulls data from OpenWeatherMap to provide weather forecasts for planned dates and locations, allowing for weather-appropriate activity planning." + 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""" ) booking_agent = Agent( tools=[mcp_tools], name="Booking Agent", - goal="Connects to Booking.com and Airbnb APIs to search and filter accommodations based on user preferences (price range, amenities, location)" + 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""" ) calendar_agent = Agent( tools=[mcp_tools], name="Calendar Agent", - goal="Creates calendar events for travel plans, including reminders and location details." + 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""" ) team = Team( members=[maps_agent, weather_agent, booking_agent, calendar_agent], name="Travel Planning Team", markdown=True, - show_tool_calls=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""" ) - await team.aprint_response(message, stream=True) + result = await team.arun(message) + output = result.messages[-1].content + return output + +# -------------------- Streamlit App -------------------- + +# Configure the page +st.set_page_config( + page_title="AI Travel Planner", + page_icon="✈️", + layout="wide" +) -# -------------------- Terminal Interaction Loop -------------------- +# 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 = "" -if __name__ == "__main__": # βœ… correct + # 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" + ) - print("🌍 Travel Planning Agent β€” Airbnb, Maps, Weather, Calendar (type 'exit' to quit)\n") - try: - while True: - user_input = input("You: ") - if user_input.lower() in ["exit", "quit"]: - print("πŸ‘‹ Bye!") - break - asyncio.run(run_agent(user_input)) - except KeyboardInterrupt: - print("\nπŸ‘‹ Interrupted. Exiting...") \ No newline at end of file + # 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!") + +# 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 +""") + +# Create two columns for input +col1, col2 = st.columns(2) + +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" + ) + +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", + "Beach", "Mountain", "Luxury", "Budget-Friendly", "Food & Dining", + "Shopping", "Nightlife", "Family-Friendly"], + help="Select your travel preferences" + ) + +# Additional preferences +st.subheader("Additional Preferences") +col3, col4 = st.columns(2) + +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" + ) + +with col4: + dietary_restrictions = st.multiselect( + "Dietary Restrictions", + ["None", "Vegetarian", "Vegan", "Gluten-Free", "Halal", "Kosher"], + help="Select any dietary restrictions" + ) + +# 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.") + +# Add a footer +st.markdown("---") +st.markdown(""" +
+

Powered by AI Travel Planning Agents

+

Your personal travel assistant for creating memorable experiences

+
+""", unsafe_allow_html=True) \ No newline at end of file diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/generate_token.py b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/generate_token.py deleted file mode 100644 index 6fe9f83..0000000 --- a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/generate_token.py +++ /dev/null @@ -1,21 +0,0 @@ -from google_auth_oauthlib.flow import InstalledAppFlow -from dotenv import load_dotenv -import os - -load_dotenv() # Loads from .env - -SCOPES = ['https://www.googleapis.com/auth/calendar'] - -flow = InstalledAppFlow.from_client_config({ - "installed": { - "client_id": os.getenv("GOOGLE_CLIENT_ID"), - "client_secret": os.getenv("GOOGLE_CLIENT_SECRET"), - "redirect_uris": ["urn:ietf:wg:oauth:2.0:oob"], - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token" - } -}, SCOPES) - -creds = flow.run_local_server(port=0) -print("\n=== REFRESH TOKEN ===\n") -print(creds.refresh_token) diff --git a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt index 75b6922..c4b42ce 100644 --- a/mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt +++ b/mcp_ai_agents/ai_travel_planner_mcp_agent_team/requirements.txt @@ -1,6 +1,9 @@ agno==1.2.13 mcp==1.6.0 streamlit==1.44.1 -google-api-python-client -google-auth -google-auth-oauthlib \ No newline at end of file +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.12.0 \ No newline at end of file