get_class_schedule
Retrieve your weekly class schedule from the MUSTer campus system. Filter by specific date or view the full week's timetable with a single request.
Instructions
Get class schedule in this week; pass null for full week, or date (YYYY-MM-DD) to filter. If you need multiple days, pass null once instead of multiple calls.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | Date filter YYYY-MM-DD; null returns full week |
Implementation Reference
- main.py:190-196 (handler)MCP tool handler: thin wrapper that delegates to MUSTerClient.get_class_schedule() and handles errors.def tool_get_class_schedule(date: Optional[str] = None) -> Any: try: schedule_data = muster_client.get_class_schedule(date=date) return schedule_data except Exception as e: return {"error": f"Failed to fetch schedule data: {str(e)}"}
- main.py:87-100 (schema)Tool schema definition including input schema for optional date parameter.Tool( name="get_class_schedule", description="Get class schedule in this week; pass null for full week, or date (YYYY-MM-DD) to filter. If you need multiple days, pass null once instead of multiple calls.", inputSchema={ "type": "object", "properties": { "date": { "type": ["string", "null"], "description": "Date filter YYYY-MM-DD; null returns full week", } }, "required": [], }, ),
- main.py:219-220 (registration)Tool dispatch registration in the call_tool handler.if name == "get_class_schedule": return _wrap_json(tool_get_class_schedule(args.get("date")))
- MUSTerClient.py:605-722 (helper)Core helper method in MUSTerClient: authenticates, downloads Excel schedule via Selenium, parses with pandas, and filters by date if provided.def get_class_schedule(self, date: Optional[str] = None) -> Dict[str, Any]: """ Get class schedule data from the MUST schedule website. Args: date: Optional date in YYYY-MM-DD format to filter results """ self._ensure_driver() self.heartBeat() if not self.logged_in: if not self.login(): raise Exception("Login required to get courses.") # Create temporary download directory for Excel file with tempfile.TemporaryDirectory() as download_dir: try: # Update download preferences for this session self.driver.execute_cdp_cmd('Page.setDownloadBehavior', { 'behavior': 'allow', 'downloadPath': download_dir }) # Navigate to schedule page self.driver.get(SCHEDULE_URL) # Login if we're redirected to login page current_url = self.driver.current_url.lower() if "login" in current_url or "signin" in current_url: try: self.login() except Exception as e: return {"error": f"Failed to login to schedule system: {str(e)}"} self.heartBeat() # Export process export_btn = WebDriverWait(self.driver, 10).until( EC.element_to_be_clickable( (By.XPATH, "//button[span[text()='導出']]") ) ) export_btn.click() # Expand collapse panel and download collapse_header = WebDriverWait(self.driver, 10).until( EC.element_to_be_clickable((By.XPATH, "//div[contains(@class,'ivu-collapse-header') and contains(.,'下載任務')]")) ) collapse_header.click() download_buttons = WebDriverWait(self.driver, 10).until( EC.presence_of_all_elements_located((By.XPATH, "//button[.//span[contains(text(),'下载') or contains(text(),'下載')]]")) ) WebDriverWait(self.driver, 5).until(EC.element_to_be_clickable(download_buttons[-1])) download_buttons[-1].click() time.sleep(1) self.heartBeat() # Cancel any dialogs try: cancel_buttons = WebDriverWait(self.driver, 5).until( EC.presence_of_all_elements_located((By.XPATH, "//button[contains(., '取消')]")) ) for button in cancel_buttons: try: button.click() except: pass except: pass # Wait for file download timeout = 30 start = time.time() while True: xlsx_files = glob.glob(os.path.join(download_dir, "*.xlsx")) if xlsx_files: break elif time.time() - start > timeout: return {"error": "Failed to download schedule file within 30 seconds"} else: time.sleep(0.5) self.heartBeat() # Process the downloaded file xlsx_files = sorted( glob.glob(os.path.join(download_dir, "*.xlsx")), key=os.path.getmtime, reverse=True ) latest_xlsx = xlsx_files[0] df = pd.read_excel(latest_xlsx) schedule_data = df.to_dict('records') response = { "success": True, "total_classes": len(schedule_data), "schedule": schedule_data } if date: filtered = [cls for cls in schedule_data if isinstance(cls, dict) and cls.get("日期") == date] response["schedule"] = filtered response["total_classes"] = len(filtered) if not filtered: response["warning"] = "Only current week's schedule is available." return response except Exception as e: return {"error": f"Failed to fetch schedule data: {str(e)}"} finally: self.heartBeat()