Weather MCP

OPen Source Weather

Open-Metro

    def get_current_weather(
        self,
        city: str = Field(
            "Unknown",
            description="City name for the weather"
        ),
    ) -> str:
        """
        Get the current weather + 7-day forecast for a given city using Open-Meteo.
        """

        import requests
        from datetime import datetime

        # Polite follow-up if city is not provided
        if not city or city.strip().lower() == "unknown":
            return "Which city would you like the weather for?"

        # Open-Meteo weather code mapping
        weather_codes = {
            0: "Clear sky",
            1: "Mainly clear",
            2: "Partly cloudy",
            3: "Overcast",
            45: "Fog",
            48: "Depositing rime fog",
            51: "Light drizzle",
            53: "Moderate drizzle",
            55: "Dense drizzle",
            56: "Light freezing drizzle",
            57: "Dense freezing drizzle",
            61: "Slight rain",
            63: "Moderate rain",
            65: "Heavy rain",
            66: "Light freezing rain",
            67: "Heavy freezing rain",
            71: "Slight snow fall",
            73: "Moderate snow fall",
            75: "Heavy snow fall",
            77: "Snow grains",
            80: "Slight rain showers",
            81: "Moderate rain showers",
            82: "Violent rain showers",
            85: "Slight snow showers",
            86: "Heavy snow showers",
            95: "Thunderstorm",
            96: "Thunderstorm with slight hail",
            99: "Thunderstorm with heavy hail",
        }

        def format_date(date_str: str) -> str:
            try:
                d = datetime.fromisoformat(date_str).date()
                return d.strftime("%a %d %b")
            except Exception:
                return date_str

        try:
            # 1) Geocode city → lat/lon
            geo_url = "https://geocoding-api.open-meteo.com/v1/search"
            geo_params = {
                "name": city,
                "count": 1,
                "language": "en",
                "format": "json",
            }

            geo_resp = requests.get(geo_url, params=geo_params, timeout=10)
            geo_resp.raise_for_status()
            geo_data = geo_resp.json()

            if "results" not in geo_data or not geo_data["results"]:
                return f"I couldn’t find a location called “{city}”."

            location = geo_data["results"][0]
            latitude = location["latitude"]
            longitude = location["longitude"]
            location_name = f"{location['name']}, {location.get('country', '')}"

            # 2) Fetch current weather + daily forecast (7 days) with local timezone
            weather_url = "https://api.open-meteo.com/v1/forecast"
            weather_params = {
                "latitude": latitude,
                "longitude": longitude,
                "timezone": "auto",
                "current_weather": True,
                "daily": "weathercode,temperature_2m_max,temperature_2m_min,precipitation_sum,wind_speed_10m_max",
                "forecast_days": 7,
            }

            weather_resp = requests.get(weather_url, params=weather_params, timeout=10)
            weather_resp.raise_for_status()
            weather_data = weather_resp.json()

            if "current_weather" not in weather_data:
                return "Weather data is currently unavailable."

            current = weather_data["current_weather"]
            temperature = current.get("temperature")
            wind_speed = current.get("windspeed")
            weather_code = current.get("weathercode")
            weather_text = weather_codes.get(weather_code, "Unknown conditions")

            # Local time handling
            local_time_str = current.get("time")
            timezone = weather_data.get("timezone", "local time")

            try:
                local_time = datetime.fromisoformat(local_time_str)
                formatted_time = local_time.strftime("%A, %d %B %Y %I:%M %p")
            except Exception:
                formatted_time = local_time_str

            # 3) Daily forecast parsing (7 days)
            daily = weather_data.get("daily", {})
            times = daily.get("time", [])
            codes = daily.get("weathercode", [])
            tmax = daily.get("temperature_2m_max", [])
            tmin = daily.get("temperature_2m_min", [])
            precip = daily.get("precipitation_sum", [])
            windmax = daily.get("wind_speed_10m_max", [])

            forecast_lines = []
            days = min(
                len(times),
                len(codes),
                len(tmax),
                len(tmin),
                len(precip),
                len(windmax),
            )

            for i in range(days):
                day_label = format_date(times[i])
                day_text = weather_codes.get(codes[i], "Unknown")
                forecast_lines.append(
                    f"- {day_label}: {day_text}, {tmin[i]}–{tmax[i]}°C, rain {precip[i]} mm, wind {windmax[i]} km/h"
                )

            forecast_block = "\n".join(forecast_lines) if forecast_lines else "No forecast available."

            return (
                f"Weather in {location_name}:\n"
                f"- Conditions: {weather_text}\n"
                f"- Temperature: {temperature}°C\n"
                f"- Wind: {wind_speed} km/h\n"
                f"- Local time: {formatted_time} ({timezone})\n\n"
                f"7-day forecast:\n"
                f"{forecast_block}"
            )

        except requests.RequestException:
            return (
                "I can’t reach the weather service from this server. "
                "Please check outbound internet access."
            )