We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Alexliu13483/weather_mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
# 📋 智能歷史天氣查詢實現計劃
## 🎯 核心概念
**自動判斷邏輯**:根據 `target_date` 與當前日期的關係,自動計算 `past_days` 和 `forecast_days`
```python
if target_date:
today = datetime.now().date()
target = datetime.strptime(target_date, "%Y-%m-%d").date()
delta = (target - today).days
if delta < 0: # 過去日期
past_days = abs(delta)
forecast_days = 0
elif delta > 0: # 未來日期
past_days = 0
forecast_days = delta + 1
else: # 今天
past_days = 0
forecast_days = 1
```
## 📝 實現步驟
### 1. 修改 `server.py` - 智能參數計算
**簡化函數簽名**(移除 forecast_days 和 past_days):
```python
def get_weather(
self,
lat: float,
lon: float,
hours: int = 12,
target_date: str = "" # 唯一的日期參數
) -> List[Content]:
```
**智能計算邏輯**(在函數內部計算所需參數):
```python
from datetime import datetime
# 如果未提供 target_date,使用今天日期
if not target_date:
target_date = datetime.now().strftime("%Y-%m-%d")
# 根據 target_date 自動計算 past_days 和 forecast_days
try:
today = datetime.now().date()
target = datetime.strptime(target_date, "%Y-%m-%d").date()
delta = (target - today).days
if delta < 0: # 過去日期
past_days = min(abs(delta), 92) # API 上限 92 天
forecast_days = 1 # 至少包含今天
elif delta > 0: # 未來日期
past_days = 0
forecast_days = min(delta + 1, 16) # API 上限 16 天
else: # 今天
past_days = 0
forecast_days = 1
except ValueError:
# 日期格式錯誤,使用預設值
past_days = 0
forecast_days = 1
```
**更新 API URL**:
```python
url = (
"https://api.open-meteo.com/v1/forecast"
f"?latitude={lat}&longitude={lon}"
"&hourly=temperature_2m,relative_humidity_2m,precipitation_probability,wind_speed_10m"
f"&forecast_days={forecast_days}"
f"&past_days={past_days}"
"&timezone=auto"
)
```
**優點**:
- ✅ **極簡 API**:只需 `hours` 和 `target_date` 兩個參數
- ✅ 用戶只需提供日期(或不提供,預設為今天)
- ✅ 系統自動判斷過去/未來並計算所需參數
- ✅ `forecast_days` 和 `past_days` 完全內部處理
- ✅ 完全向後兼容
### 2. 修改 `client.py` - 簡化參數
**簡化 get_weather() 方法**(移除 forecast_days 和 past_days):
```python
def get_weather(
self,
lat: float,
lon: float,
hours: int = 12,
target_date: str = "",
timeout: Optional[float] = None
) -> Dict[str, Any]:
return self.arun(self.call_tool(
"get_weather",
{
"lat": lat,
"lon": lon,
"hours": hours,
"target_date": target_date
},
timeout
))
```
**簡化 get_city_weather() 方法**:
```python
def get_city_weather(
self,
city: str,
hours: int = 12,
target_date: str = "",
timeout: Optional[float] = None
) -> Dict[str, Any]:
# First geocode the city
geo_result = self.geocode_city(city, timeout)
if "error" in geo_result or "coord" not in geo_result:
return geo_result
lat = geo_result["coord"]["lat"]
lon = geo_result["coord"]["lon"]
# Get weather data
weather_result = self.get_weather(lat, lon, hours, target_date, timeout)
# Combine results
return {
"geocoding": geo_result,
"weather": weather_result,
"display_name": geo_result.get("display_name"),
"timezone": weather_result.get("timezone")
}
```
### 3. 修改 `tools.py` - 簡化 Schema
**極簡 WeatherInput**(移除 forecast_days 和 past_days):
```python
class WeatherInput(BaseModel):
"""Input schema for weather tool."""
lat: float = Field(..., description="緯度")
lon: float = Field(..., description="經度")
hours: int = Field(12, ge=1, le=24, description="查詢小時數,1~24(若指定 target_date 則忽略此參數)")
target_date: str = Field("", description="指定日期 YYYY-MM-DD(可為過去、今天或未來,系統自動處理)")
```
**極簡 CityWeatherInput**:
```python
class CityWeatherInput(BaseModel):
"""Input schema for combined city weather tool."""
city: str = Field(..., description="城市名稱(中文或英文皆可)")
hours: int = Field(12, ge=1, le=24, description="查詢小時數,1~24(若指定 target_date 則忽略此參數)")
target_date: str = Field("", description="指定日期 YYYY-MM-DD(可為過去、今天或未來,系統自動處理)")
```
**更新工具描述**:
```python
weather_tool = StructuredTool.from_function(
name="get_weather",
description="查詢逐小時天氣。支援多日預報(1-16天)、歷史天氣(1-92天前)和指定日期查詢(自動判斷過去/未來)。",
func=self._tool_weather,
args_schema=WeatherInput,
)
city_weather_tool = StructuredTool.from_function(
name="get_city_weather",
description="一次性查詢城市的完整天氣資訊。支援多日預報、歷史天氣和指定日期查詢(自動判斷過去/未來)。",
func=self._tool_city_weather,
args_schema=CityWeatherInput,
)
```
**簡化工具函數**:
```python
def _tool_weather(
self,
lat: float,
lon: float,
hours: int = 12,
target_date: str = ""
) -> str:
data = self.client.get_weather(lat, lon, int(hours), target_date)
return json.dumps(data, ensure_ascii=False)
def _tool_city_weather(
self,
city: str,
hours: int = 12,
target_date: str = ""
) -> str:
data = self.client.get_city_weather(city, int(hours), target_date)
return json.dumps(data, ensure_ascii=False)
```
### 4. 增強 `agent.py` - 簡化 Prompt
**Agent 只需計算日期,不需計算 past_days/forecast_days**:
```python
AGENT_PROMPT = """
你是一個能使用多種工具的智能天氣助手。
當使用者問題需要查詢天氣時:
1. 優化問題表述,必要時將中文地名轉為英文(對照表如下)。
2. **理解時間表達**,計算對應的日期:
- 「昨天」→ target_date = 昨天日期(今天-1天)
- 「前天」→ target_date = 前天日期(今天-2天)
- 「3天前」→ target_date = 今天-3天
- 「今天」→ target_date = 今天日期
- 「明天」→ target_date = 明天日期(今天+1天)
- 「後天」→ target_date = 後天日期(今天+2天)
- 「未來3天」→ forecast_days = 3(不指定 target_date)
現在是 {current_datetime},請依此計算日期。
3. 選擇最合適的工具並執行。
4. 依流程輸出:
Thought → Action → Action Input → Observation
(可重複多次)
5. 最後輸出 Final Answer,若未調用工具則回答「不知道」。
中文→英文地名對照:
- 日本/東京 -> Tokyo
- 台灣/台北 -> Taipei
- 中國/北京 -> Beijing
- 韓國/首爾 -> Seoul
- 美國/華盛頓 -> Washington
- 英國/倫敦 -> London
- 法國/巴黎 -> Paris
- 德國/柏林 -> Berlin
- 印度/新德里 -> New Delhi
**時間計算範例**:
- 問「昨天東京天氣」→ 計算昨天日期(例如 2025-10-01),使用 get_city_weather(city="Tokyo", target_date="2025-10-01")
- 問「明天東京天氣」→ 計算明天日期(例如 2025-10-03),使用 get_city_weather(city="Tokyo", target_date="2025-10-03")
- 問「3天前台北天氣」→ 計算日期(例如 2025-09-29),使用 get_city_weather(city="Taipei", target_date="2025-09-29")
- 問「未來3天倫敦天氣」→ 使用 get_city_weather(city="London", forecast_days=3)
**重要**:只需提供 target_date,系統會自動判斷是過去還是未來並設定正確的 past_days 或 forecast_days 參數。
優先使用 get_city_weather 工具進行一次性查詢,除非需要特定的地理編碼或天氣數據。
Let's start!
Question: {query}
Final Answer: (只輸出最終答案)
"""
```
### 5. 測試更新
**新增測試案例**:
```python
def test_auto_calculate_past_days(self):
"""測試自動計算過去天數"""
from datetime import datetime, timedelta
from weather_mcp.tools import WeatherInput
# 測試參數接受
yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
weather_input = WeatherInput(
lat=35.6895,
lon=139.6917,
target_date=yesterday # 只需提供日期
)
assert weather_input.target_date == yesterday
assert weather_input.past_days == 0 # 預設值,server 會自動計算
def test_past_days_parameter(self):
"""測試 past_days 參數"""
from weather_mcp.tools import WeatherInput
weather_input = WeatherInput(
lat=35.6895,
lon=139.6917,
past_days=1,
target_date="2025-10-01"
)
assert weather_input.past_days == 1
```
### 6. 文檔更新
**創建 docs/HISTORICAL_WEATHER.md**:
```markdown
# 歷史天氣查詢功能說明
## 🎯 核心特性
系統會自動判斷 `target_date` 是過去還是未來:
- **過去日期**:自動設定 `past_days`(最多 92 天)
- **未來日期**:自動設定 `forecast_days`(最多 16 天)
- **今天**:返回今天的數據
用戶只需提供 `target_date`,無需手動計算參數!
## 📊 使用範例
### 直接 API(自動計算)
```python
from datetime import datetime, timedelta
from weather_mcp import WeatherMCPClient
client = WeatherMCPClient()
yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
tomorrow = (datetime.now() + timedelta(days=1)).strftime("%Y-%m-%d")
# 查詢昨天(自動設定 past_days=1)
result = client.get_city_weather(city="Tokyo", target_date=yesterday)
# 查詢明天(自動設定 forecast_days=2)
result = client.get_city_weather(city="Tokyo", target_date=tomorrow)
```
### Agent 自然語言
```python
from weather_mcp import WeatherAgent
agent = WeatherAgent()
# Agent 只需計算日期,Server 自動判斷
agent.ask_weather("昨天東京天氣如何?")
agent.ask_weather("明天台北天氣?")
agent.ask_weather("3天前倫敦天氣?")
```
```
**更新 docs/MULTI_DAY_FORECAST.md**:
加入歷史天氣查詢說明
**更新 README.md**:
功能列表加入「歷史天氣查詢(最多 92 天前)」
## 🔑 核心優勢
### 1. 用戶體驗提升
```python
# ❌ 舊方式:需要手動計算
result = client.get_city_weather(
city="Tokyo",
past_days=1, # 手動計算
forecast_days=2, # 手動計算
target_date=yesterday
)
# ✅ 新方式:自動計算
result = client.get_city_weather(
city="Tokyo",
target_date=yesterday # 系統自動判斷
)
```
### 2. Agent 更簡單
- Agent 只需計算日期字串
- 不需理解 past_days/forecast_days 概念
- Server 端統一處理邏輯
### 3. 實現位置
- **核心邏輯**:`server.py` 的 `get_weather()` 方法
- **智能判斷**:根據 target_date 與今天比較
- **自動設定**:past_days 或 forecast_days
## 📈 API 行為
### Open-Meteo Forecast API
```
時間軸:←過去 | 今天 | 未來→
past_days=2, forecast_days=3:
[前天] [昨天] [今天] [明天] [後天]
```
### 自動計算邏輯
```python
today = 2025-10-02
target_date = "2025-10-01" # 昨天
→ delta = -1
→ past_days = 1, forecast_days = 1
target_date = "2025-10-03" # 明天
→ delta = 1
→ past_days = 0, forecast_days = 2
target_date = "2025-09-29" # 3天前
→ delta = -3
→ past_days = 3, forecast_days = 1
```
## ✅ 向後兼容與行為變更
### 新行為
- **不提供 `target_date`** → 自動使用今天日期作為 `target_date`
- **提供 `target_date`** → 自動判斷過去/未來並設定參數
### 為什麼這樣設計?
1. **一致性**:所有查詢都經過相同的日期處理邏輯
2. **簡潔性**:統一的 API 行為,更容易理解
3. **智能化**:系統自動處理所有日期計算
### 對現有代碼的影響
```python
# 舊代碼(仍然有效)
result = client.get_city_weather("Tokyo", hours=12)
# 新行為:target_date 自動設為今天,取得今天的數據
# 新代碼(更明確)
result = client.get_city_weather("Tokyo", hours=12)
# 等同於:
from datetime import datetime
today = datetime.now().strftime("%Y-%m-%d")
result = client.get_city_weather("Tokyo", target_date=today)
```
**結論**:行為保持一致,只是內部實作更智能化
## 🧪 測試計劃
1. ✅ 參數驗證測試
2. ✅ 昨天天氣查詢測試
3. ✅ 多天前天氣查詢測試
4. ✅ 未來天氣查詢測試(驗證不影響現有功能)
5. ✅ 自動計算邏輯測試
6. ✅ Agent 時間理解測試
7. ✅ 向後兼容測試
## 📝 實現檢查清單
- [ ] server.py: 新增 past_days 參數
- [ ] server.py: 實作智能計算邏輯
- [ ] server.py: 更新 API URL
- [ ] server.py: 更新日誌記錄
- [ ] client.py: 更新 get_weather() 方法
- [ ] client.py: 更新 get_city_weather() 方法
- [ ] tools.py: 更新 WeatherInput schema
- [ ] tools.py: 更新 CityWeatherInput schema
- [ ] tools.py: 更新工具描述
- [ ] tools.py: 更新工具函數
- [ ] agent.py: 更新 AGENT_PROMPT
- [ ] tests/test_client.py: 新增測試案例
- [ ] docs/HISTORICAL_WEATHER.md: 創建文檔
- [ ] docs/MULTI_DAY_FORECAST.md: 更新文檔
- [ ] README.md: 更新功能說明
- [ ] CHANGELOG.md: 記錄更新
---
**預期效果**:
- 用戶體驗大幅提升
- Agent 實作更簡單
- 程式碼更優雅
- 完全向後兼容
**預計工作時間**:2-3 小時