From d8f27f6d4b37c2bde1228e370c0f5032a5eced45 Mon Sep 17 00:00:00 2001 From: priyanshm07 Date: Tue, 8 Apr 2025 18:32:50 +0530 Subject: [PATCH] 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