Content
# Weather MCP Server
Based on [QWeather](https://www.qweather.com/) API, this is a **Model Context Protocol (MCP)** server, allowing MCP clients like Claude, Cursor, and Cline to query real-time weather, forecasts, and warnings for cities in China.
## ✨ Features
| Tool | Function | Input |
|---|---|---|
| `get_current_weather` | Query real-time weather | City name / Latitude and Longitude / Location ID |
| `get_forecast` | Query 3/7/10/15/30-day weather forecast | City name + Number of days |
| `get_warnings` | Query current weather warnings | City name / Latitude and Longitude / Location ID |
- 🔒 **API Key not in source code** - injected through environment variables or `.mcp.json`
- 🌍 **GeoAPI automatic parsing** - supports Chinese city names like "Beijing" and "Shanghai", as well as latitude and longitude coordinates like `116.41,39.92`
- 📐 **Metric / Imperial unit switching** - `get_current_weather` supports `unit=m/i` parameter
- 🌐 **Multi-language support** - supports `lang=zh/en/...`
## 🚀 Quick Start
### 1. Get QWeather API Key
Go to [QWeather Console](https://console.qweather.com/) → Register → Create project → Get API Key (recommended to reset once to ensure key security).
### 2. Prepare environment
Requires [uv](https://docs.astral.sh/uv/) (recommended) or Python 3.10+.
```bash
# Clone / Enter project directory
cd F:\code\weather
# Sync dependencies
uv sync
```
### 3. Configure environment variables
Write the key to `.mcp.json` (recommended, see MCP client configuration below) or system environment variables:
```bash
# PowerShell
$env:WEATHER_API_KEY = "your_key"
# Bash
export WEATHER_API_KEY="your_key"
```
### 4. Test connectivity
```bash
uv run weather.py
```
The server will wait for MCP client connections on stdio after startup, without producing output - this is normal behavior.
## ⚙️ Configuration
### API Host
Configured in [weather.py:7](weather.py#L7) with a **dedicated subdomain**, using `X-QW-Api-Key` request header authentication:
```python
QWEATHER_HOST = "https://<your-sub>.re.qweatherapi.com"
```
If you need to change to the public domain (`devapi.qweather.com` / `geoapi.qweather.com`), replace the host and change the authentication method to URL `?key=` parameter.
### Environment Variables
| Variable name | Required | Description |
|---|---|---|
| `WEATHER_API_KEY` | ✅ | QWeather API Key |
## 🔌 MCP Client Configuration
### Claude Code (project-level, recommended)
Create a new [`.mcp.json`](.mcp.json):
```json
{
"mcpServers": {
"weather": {
"command": "uv",
"args": ["run", "weather.py"],
"env": {
"WEATHER_API_KEY": "your_key"
}
}
}
}
```
Restart Claude Code, and in the conversation, input `/mcp` should show `weather: connected · 3 tools`.
### Claude Desktop
Edit `%APPDATA%\Claude\claude_desktop_config.json`:
```json
{
"mcpServers": {
"weather": {
"command": "uv",
"args": ["--directory", "F:\\code\\weather", "run", "weather.py"],
"env": { "WEATHER_API_KEY": "your_key" }
}
}
}
```
### MCP Inspector (for debugging)
```bash
uv run --with "mcp[cli]" mcp dev weather.py
```
Automatically opens the browser debugging console.
## 💬 Usage Examples
In the configured MCP client, directly ask natural language questions:
```
What's the weather like in Hangzhou today?
What's the 7-day weather forecast for Shanghai?
Are there any typhoon warnings for Beijing?
What's the weather at coordinates 116.41, 39.92?
Query Tokyo's current weather in imperial units
```
LLM will automatically select and call the appropriate tool.
## 📁 Project Structure
```
weather/
├── .mcp.json # Claude Code MCP configuration
├── .python-version # Python version declaration (3.10)
├── .venv/ # Virtual environment (managed by uv)
├── .gitignore
├── pyproject.toml # Project metadata + dependencies
├── uv.lock # Locked dependency versions
├── main.py # Entry placeholder (not used)
├── weather.py # ⭐ MCP server main program
└── README.md # This file
```
## 🛠️ Development
### Dependencies
| Package | Version | Purpose |
|---|---|---|
| `httpx` | ≥ 0.28.1 | Asynchronous HTTP client |
| `mcp[cli]` | ≥ 1.28.1 | MCP protocol SDK |
### Add Tools
Register new functions in [weather.py](weather.py) with `@mcp.tool()` decorator:
```python
@mcp.tool()
async def my_new_tool(arg: str) -> str:
"""Tool description (LLM decides when to call based on this)."""
...
```
### Interface Specification Adaptation Progress
| Interface | Status |
|---|---|
| `/v7/weather/now` Real-time weather | ✅ Fully expanded according to specification |
| `/v7/weather/{3,7,10,15,30}d` Weather forecast | 🟡 Basic functionality, waiting to supplement fields according to specification |
| `/v7/warning/now` Weather warning | 🟡 Basic functionality, waiting to supplement fields according to specification |
| `/geo/v2/city/lookup` City parsing | 🟡 Only returns Location ID, other fields not exposed |
## ⚠️ Security Tips
- **Never hardcode API Key into source code** - use environment variables or `.mcp.json` `env` field
- **Do not submit `.mcp.json` to public repositories** - if submission is necessary, replace the key with an environment variable placeholder
- Leaked Key should be immediately reset in QWeather Console
## 📝 License
MIT