Skip to main content
Glama

MCP Weather Server

by ramonbnuezjr
services.py5.73 kB
# app/services.py import httpx from typing import Dict, Any, Optional from app.core.config import get_settings # To access API key and other settings # Get settings instance settings = get_settings() OPENWEATHERMAP_API_URL = "http://api.openweathermap.org/data/2.5/weather" class WeatherServiceError(Exception): """Custom exception for weather service errors.""" def __init__(self, message: str, status_code: Optional[int] = None): super().__init__(message) self.status_code = status_code async def fetch_weather_data_from_provider(location: str) -> Dict[str, Any]: """ Asynchronously fetches and processes weather data from OpenWeatherMap API. Args: location: The city name for which to fetch weather data. Returns: A dictionary containing processed weather data. Raises: WeatherServiceError: If there's an issue fetching or processing weather data. """ if not settings.OPENWEATHERMAP_API_KEY or settings.OPENWEATHERMAP_API_KEY == "YOUR_ACTUAL_API_KEY_HERE": # This check is crucial. Do not proceed without a valid API key. # Log this error server-side for a real application print("CRITICAL ERROR: OpenWeatherMap API key is not configured correctly.") raise WeatherServiceError("Weather service is not configured on the server.", status_code=500) params = { 'q': location, 'appid': settings.OPENWEATHERMAP_API_KEY, 'units': 'metric' # Get temperature in Celsius, wind speed in meter/sec } async with httpx.AsyncClient() as client: try: response = await client.get(OPENWEATHERMAP_API_URL, params=params) response.raise_for_status() # Raises an HTTPStatusError for bad responses (4XX or 5XX) raw_data = response.json() # Basic check for expected data if not raw_data or 'main' not in raw_data or 'weather' not in raw_data or not raw_data['weather']: # This WeatherServiceError should propagate with status_code=502 raise WeatherServiceError(f"Incomplete data received from weather API for {location}.", status_code=502) # Process and extract relevant information temp_celsius = raw_data.get('main', {}).get('temp') humidity = raw_data.get('main', {}).get('humidity') pressure_hpa = raw_data.get('main', {}).get('pressure') condition = raw_data.get('weather', [{}])[0].get('main', 'N/A') description = raw_data.get('weather', [{}])[0].get('description', 'N/A').capitalize() wind_speed_mps = raw_data.get('wind', {}).get('speed') # meters per second # Convert wind speed from m/s to km/h wind_speed_kph = (wind_speed_mps * 3.6) if wind_speed_mps is not None else None # Convert temperature from Celsius to Fahrenheit temp_fahrenheit = (temp_celsius * 9/5) + 32 if temp_celsius is not None else None processed_data = { "location": raw_data.get('name', location), # Use name from API if available "temperature_celsius": temp_celsius, "temperature_fahrenheit": temp_fahrenheit, "condition": condition, "description": description, "humidity_percent": humidity, "wind_kph": wind_speed_kph, "pressure_hpa": pressure_hpa, } return processed_data except httpx.HTTPStatusError as e: # Log the error for server-side debugging in a real app: print(f"HTTPStatusError: {e.response.status_code} - {e.response.text}") if e.response.status_code == 401: # Unauthorized raise WeatherServiceError("Invalid API key or subscription issue with the weather service.", status_code=e.response.status_code) elif e.response.status_code == 404: # Not Found raise WeatherServiceError(f"Weather data not found for location: {location}.", status_code=e.response.status_code) elif e.response.status_code == 429: # Too Many Requests raise WeatherServiceError("Rate limit exceeded with the weather service. Please try again later.", status_code=e.response.status_code) else: # Other HTTP errors raise WeatherServiceError(f"Error fetching data from weather service: HTTP {e.response.status_code}.", status_code=e.response.status_code) except httpx.RequestError as e: # Network errors or other request issues (e.g., DNS failure, connection refused) # Log the error: print(f"RequestError: {e}") raise WeatherServiceError(f"Could not connect to the weather service. Please check network connectivity.", status_code=503) # Service Unavailable # ---- THIS IS THE KEY CHANGE ---- except WeatherServiceError as wse: # If a WeatherServiceError was already explicitly raised within the try block # (e.g., for incomplete data with status_code=502), # re-raise it as is to preserve its original status code and message. raise wse # ---- END KEY CHANGE ---- except Exception as e: # Catch any *other* unexpected errors during the API call or data processing # that weren't an httpx error or an already specific WeatherServiceError. # Log the error: print(f"Unexpected error in weather service: {type(e).__name__} - {e}") raise WeatherServiceError(f"An unexpected error occurred while fetching weather data: {str(e)}", status_code=500) # Internal Server Error

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ramonbnuezjr/mcp-weather-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server