arcticaurora commited on
Commit
7140708
·
verified ·
1 Parent(s): 4b6713b

Update tools/weather.py

Browse files
Files changed (1) hide show
  1. tools/weather.py +90 -20
tools/weather.py CHANGED
@@ -1,13 +1,42 @@
1
  from mcp.server.fastmcp import FastMCP
2
  import requests
3
  import os
4
- from typing import Dict, Optional
5
 
6
  mcp = FastMCP("Weather")
7
 
8
  @mcp.tool()
9
  def get_current_weather(location: str) -> Dict:
10
- """Get current weather for a location using OpenWeatherMap API"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  api_key = os.getenv("OPENWEATHER_API_KEY")
12
 
13
  if not api_key:
@@ -18,6 +47,7 @@ def get_current_weather(location: str) -> Dict:
18
  "condition": "sunny",
19
  "humidity": "65%",
20
  "wind_speed": "10 km/h",
 
21
  "status": "mock_data",
22
  "message": f"Mock weather data for {location} (set OPENWEATHER_API_KEY for real data)"
23
  }
@@ -35,37 +65,68 @@ def get_current_weather(location: str) -> Dict:
35
  data = response.json()
36
 
37
  return {
38
- "location": data["name"],
39
  "temperature": f"{data['main']['temp']}°C",
40
  "condition": data["weather"][0]["description"],
41
  "humidity": f"{data['main']['humidity']}%",
42
  "wind_speed": f"{data['wind']['speed']} m/s",
43
  "pressure": f"{data['main']['pressure']} hPa",
 
44
  "status": "real_data"
45
  }
46
  except requests.exceptions.RequestException as e:
47
  return {
48
  "error": f"Failed to fetch weather data: {str(e)}",
49
  "location": location,
50
- "status": "error"
 
51
  }
52
 
53
  @mcp.tool()
54
  def get_forecast(location: str, days: int = 5) -> Dict:
55
- """Get weather forecast for specified days (1-5 days)"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  if days < 1 or days > 5:
57
- days = 5
58
 
59
  api_key = os.getenv("OPENWEATHER_API_KEY")
60
 
61
  if not api_key:
62
  # Return mock forecast
63
  mock_forecast = []
64
- conditions = ["sunny", "cloudy", "rainy", "partly cloudy", "stormy"]
 
 
65
  for day in range(days):
66
  mock_forecast.append({
67
  "day": day + 1,
68
- "temperature": f"{20 + day}°C",
69
  "condition": conditions[day % len(conditions)],
70
  "humidity": f"{60 + day * 2}%"
71
  })
@@ -74,7 +135,8 @@ def get_forecast(location: str, days: int = 5) -> Dict:
74
  "location": location,
75
  "forecast_days": days,
76
  "forecast": mock_forecast,
77
- "status": "mock_data"
 
78
  }
79
 
80
  try:
@@ -90,19 +152,26 @@ def get_forecast(location: str, days: int = 5) -> Dict:
90
  response.raise_for_status()
91
  data = response.json()
92
 
93
- # Process forecast data (simplified - take one forecast per day)
94
  forecast = []
95
- for i in range(0, min(len(data["list"]), days * 8), 8):
96
- item = data["list"][i]
97
- forecast.append({
98
- "day": (i // 8) + 1,
99
- "temperature": f"{item['main']['temp']}°C",
100
- "condition": item["weather"][0]["description"],
101
- "humidity": f"{item['main']['humidity']}%"
102
- })
 
 
 
 
 
 
 
103
 
104
  return {
105
- "location": data["city"]["name"],
106
  "forecast_days": len(forecast),
107
  "forecast": forecast,
108
  "status": "real_data"
@@ -111,7 +180,8 @@ def get_forecast(location: str, days: int = 5) -> Dict:
111
  return {
112
  "error": f"Failed to fetch forecast data: {str(e)}",
113
  "location": location,
114
- "status": "error"
 
115
  }
116
 
117
  if __name__ == "__main__":
 
1
  from mcp.server.fastmcp import FastMCP
2
  import requests
3
  import os
4
+ from typing import Dict
5
 
6
  mcp = FastMCP("Weather")
7
 
8
  @mcp.tool()
9
  def get_current_weather(location: str) -> Dict:
10
+ """Get current weather conditions for a specific location.
11
+
12
+ Args:
13
+ location (str): The city name, state, and/or country. Can be in various formats:
14
+ - "London" (city only)
15
+ - "New York, NY" (city, state)
16
+ - "Tokyo, Japan" (city, country)
17
+ - "Paris, France" (city, country)
18
+ - "Miami, FL, USA" (city, state, country)
19
+
20
+ Returns:
21
+ Dict: Weather information containing:
22
+ - location (str): Confirmed location name from API
23
+ - temperature (str): Current temperature with unit (e.g., "22°C")
24
+ - condition (str): Weather description (e.g., "clear sky", "light rain")
25
+ - humidity (str): Humidity percentage (e.g., "65%")
26
+ - wind_speed (str): Wind speed with unit (e.g., "3.2 m/s")
27
+ - pressure (str): Atmospheric pressure (e.g., "1013 hPa")
28
+ - status (str): "real_data" for API data, "mock_data" for fallback, "error" for failures
29
+ - message (str, optional): Additional information or error details
30
+
31
+ Examples:
32
+ get_current_weather("London") returns real weather data for London, UK
33
+ get_current_weather("Miami, FL") returns weather for Miami, Florida
34
+ get_current_weather("InvalidCity") returns error status with message
35
+
36
+ Note:
37
+ Requires OPENWEATHER_API_KEY environment variable for real data.
38
+ Returns mock data if API key is not provided.
39
+ """
40
  api_key = os.getenv("OPENWEATHER_API_KEY")
41
 
42
  if not api_key:
 
47
  "condition": "sunny",
48
  "humidity": "65%",
49
  "wind_speed": "10 km/h",
50
+ "pressure": "1013 hPa",
51
  "status": "mock_data",
52
  "message": f"Mock weather data for {location} (set OPENWEATHER_API_KEY for real data)"
53
  }
 
65
  data = response.json()
66
 
67
  return {
68
+ "location": f"{data['name']}, {data['sys']['country']}",
69
  "temperature": f"{data['main']['temp']}°C",
70
  "condition": data["weather"][0]["description"],
71
  "humidity": f"{data['main']['humidity']}%",
72
  "wind_speed": f"{data['wind']['speed']} m/s",
73
  "pressure": f"{data['main']['pressure']} hPa",
74
+ "feels_like": f"{data['main']['feels_like']}°C",
75
  "status": "real_data"
76
  }
77
  except requests.exceptions.RequestException as e:
78
  return {
79
  "error": f"Failed to fetch weather data: {str(e)}",
80
  "location": location,
81
+ "status": "error",
82
+ "message": "Check if location name is correct and API key is valid"
83
  }
84
 
85
  @mcp.tool()
86
  def get_forecast(location: str, days: int = 5) -> Dict:
87
+ """Get weather forecast for a specific location over multiple days.
88
+
89
+ Args:
90
+ location (str): The city name, state, and/or country (same format as get_current_weather).
91
+ days (int, optional): Number of forecast days to retrieve. Must be between 1-5.
92
+ Defaults to 5. Values outside range are clamped to 1-5.
93
+
94
+ Returns:
95
+ Dict: Forecast information containing:
96
+ - location (str): Confirmed location name
97
+ - forecast_days (int): Actual number of forecast days returned
98
+ - forecast (List[Dict]): List of daily forecasts, each containing:
99
+ - day (int): Day number (1, 2, 3, etc.)
100
+ - temperature (str): Predicted temperature (e.g., "24°C")
101
+ - condition (str): Weather condition description
102
+ - humidity (str): Predicted humidity percentage
103
+ - status (str): "real_data", "mock_data", or "error"
104
+ - message (str, optional): Additional information
105
+
106
+ Examples:
107
+ get_forecast("London", 3) returns 3-day forecast for London
108
+ get_forecast("New York") returns 5-day forecast (default) for New York
109
+ get_forecast("Paris", 10) returns 5-day forecast (clamped maximum)
110
+
111
+ Note:
112
+ Requires OPENWEATHER_API_KEY environment variable for real data.
113
+ Returns mock forecast if API key is not provided.
114
+ """
115
  if days < 1 or days > 5:
116
+ days = max(1, min(5, days)) # Clamp to 1-5 range
117
 
118
  api_key = os.getenv("OPENWEATHER_API_KEY")
119
 
120
  if not api_key:
121
  # Return mock forecast
122
  mock_forecast = []
123
+ conditions = ["sunny", "partly cloudy", "cloudy", "light rain", "clear sky"]
124
+ base_temp = 20
125
+
126
  for day in range(days):
127
  mock_forecast.append({
128
  "day": day + 1,
129
+ "temperature": f"{base_temp + day}°C",
130
  "condition": conditions[day % len(conditions)],
131
  "humidity": f"{60 + day * 2}%"
132
  })
 
135
  "location": location,
136
  "forecast_days": days,
137
  "forecast": mock_forecast,
138
+ "status": "mock_data",
139
+ "message": f"Mock {days}-day forecast for {location}"
140
  }
141
 
142
  try:
 
152
  response.raise_for_status()
153
  data = response.json()
154
 
155
+ # Process forecast data (take midday forecast for each day)
156
  forecast = []
157
+ processed_days = set()
158
+
159
+ for item in data["list"]:
160
+ # Extract date from timestamp
161
+ day_date = item["dt_txt"].split()[0] # Get YYYY-MM-DD part
162
+
163
+ if day_date not in processed_days and len(forecast) < days:
164
+ processed_days.add(day_date)
165
+ forecast.append({
166
+ "day": len(forecast) + 1,
167
+ "date": day_date,
168
+ "temperature": f"{item['main']['temp']}°C",
169
+ "condition": item["weather"][0]["description"],
170
+ "humidity": f"{item['main']['humidity']}%"
171
+ })
172
 
173
  return {
174
+ "location": f"{data['city']['name']}, {data['city']['country']}",
175
  "forecast_days": len(forecast),
176
  "forecast": forecast,
177
  "status": "real_data"
 
180
  return {
181
  "error": f"Failed to fetch forecast data: {str(e)}",
182
  "location": location,
183
+ "status": "error",
184
+ "message": "Check if location name is correct and API key is valid"
185
  }
186
 
187
  if __name__ == "__main__":