# ๐ฆ๏ธ Malaysian Weather MCP Server
**A production-ready MCP (Model Context Protocol) server that brings real-time Malaysian weather forecasts to your favorite AI assistant.**
This project implements a local MCP server that fetches live weather data from MET Malaysia's API and integrates it seamlessly with any MCP-compatible client (Claude Desktop, Cursor, Cline, etc.). Users can ask their AI assistant about Malaysian weather in natural language, and it will use this server to fetch accurate, up-to-date forecasts.
## What is MCP?
**Model Context Protocol (MCP)** is a standard that allows AI assistants to interact with external tools and services. By integrating this MCP server with your AI assistant, you enable it to:
- Query real-time weather data
- Access current and future forecasts for any Malaysian location
- Provide weather information in natural conversation
- Use weather data to inform responses and recommendations
## What This Project Does
1. **Fetches Weather Data**: Automatically updates Malaysian weather forecasts from MET Malaysia every 15 minutes
2. **Exposes MCP Tools**: Provides two tools (`check_weather_today`, `check_7day_forecast`) that your AI assistant can call
3. **Manages Data**: Stores forecasts in a local MySQL database with automatic cleanup
4. **Runs Locally**: Everything runs on your machine - no cloud dependencies
5. **Works with Any MCP Client**: Add a simple config to your favorite AI tool and start asking about weather!
## Quick Overview
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Your Local Machine โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Your MCP Client (Claude, Cursor, Cline, etc) โ
โ โ โ
โ MCP Server (weather-by-met) โ This Project โ
โ โโ server.py (MCP server) โ
โ โโ scheduler.py (Updates weather data) โ
โ โโ MySQL DB (Stores forecasts) โ
โ โ โ
โ MET Malaysia API (weather data source) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
User: "What's the weather in Kuala Lumpur?"
โ
AI asks MCP Server โ MCP queries database โ AI responds
```
## ๐ฏ Features
- **Real-time Weather Data**: Automatically fetches weather forecasts every 15 minutes
- **7-Day Forecasts**: Access forecasts for up to 7 days ahead
- **Multi-Location Support**: Query weather for states, districts, towns, recreation centres, and divisions across Malaysia
- **AI-Friendly Format**: Returns structured data that works with any AI assistant
- **Optimized Database**: Efficient MySQL storage with automatic cleanup of old records
- **Telegram Alerts**: Error notifications sent to your Telegram channel for immediate awareness
- **Production-Ready**: Comprehensive error handling and logging
## ๐ Quick Start
Get up and running in 5 minutes! This will set everything up locally on your machine.
### Prerequisites
Before starting, ensure you have:
- **Python 3.8+** - Install from python.org
- **MySQL 8.0+** - Install from mysql.com (or use Homebrew: `brew install mysql`)
- **An MCP Client** - One of: Claude Desktop, Cursor IDE, Cline VSCode extension, or any MCP-compatible client
- **Git** - For cloning this repository
### Installation Steps
#### Step 1: Clone the Repository
```bash
git clone https://github.com/zhenkai-dev/weather-by-met.git
cd weather-by-met
```
#### Step 2: Install Python Dependencies
```bash
pip install -r requirements.txt
```
This installs:
- `fastmcp` - MCP server framework
- `mysql-connector-python` - MySQL database driver
- `pydantic` - Input validation
- `requests` - For API calls
- And other utilities
#### Step 3: Set Up MySQL Database
```bash
# Create a .env file from the template
cp .env.example .env
```
Now edit `.env` with your MySQL credentials:
```bash
# macOS/Linux
nano .env
# Windows - use Notepad or your editor
```
Content of `.env`:
```
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=your_mysql_password_here
DB_NAME=weather_by_met
```
Then initialize the database:
```bash
python init_db.py
```
This creates the `weather_by_met` database and `weather_forecasts` table automatically.
#### Step 4: Start the Scheduler (Keep Running)
In one terminal, start the scheduler to fetch weather data:
```bash
python scheduler.py
```
You'll see output like:
```
[2025-11-10 10:30:00] Starting scheduler...
[2025-11-10 10:30:05] โ Fetched weather for 38 locations
[2025-11-10 10:30:07] โ Scheduler ready - will update every 15 minutes
```
**Keep this terminal running** in the background. It will:
- Fetch weather data immediately
- Update every 15 minutes automatically
- Clean old records daily at 12:05 AM (Malaysia Time)
#### Step 5: Configure Your MCP Client
Choose your MCP client below and follow the configuration steps.
##### Option A: Claude Desktop
**Step 5.1: Open config file**
**macOS/Linux**:
```bash
nano ~/Library/Application\ Support/Claude/claude_desktop_config.json
```
**Windows**:
Open `%APPDATA%\Claude\claude_desktop_config.json` with Notepad
**Step 5.2: Add configuration** (replace path with your actual path):
```json
{
"mcpServers": {
"weather-malaysia": {
"command": "python",
"args": ["/path/to/weather-by-met/server.py"],
"env": {
"DB_HOST": "localhost",
"DB_USER": "root",
"DB_PASSWORD": "your_mysql_password",
"DB_NAME": "weather_by_met"
}
}
}
}
```
**Step 5.3: Restart Claude Desktop**
- Completely close the application
- Wait 2 seconds and reopen
---
##### Option B: Cursor IDE
**Step 5.1: Open Cursor settings**
- Open Cursor settings (Cmd+, or Ctrl+,)
- Search for "MCP"
**Step 5.2: Add MCP server config**
- Click "Add MCP Server"
- Select "Standard I/O"
- Fill in:
- **Command**: `python`
- **Arguments**: `/path/to/weather-by-met/server.py`
- **Environment Variables**:
```json
{
"DB_HOST": "localhost",
"DB_USER": "root",
"DB_PASSWORD": "your_mysql_password",
"DB_NAME": "weather_by_met"
}
```
**Step 5.3: Restart Cursor**
- Close Cursor completely
- Reopen the application
---
##### Option C: Cline (VSCode Extension)
**Step 5.1: Open Cline settings**
- Click the Cline icon in VSCode sidebar
- Open Settings โ MCP Servers
**Step 5.2: Add MCP server config**
- Click "Add MCP Server"
- Fill in:
- **Type**: `stdio`
- **Command**: `python`
- **Arguments**: `/path/to/weather-by-met/server.py`
- **Environment Variables**:
```json
{
"DB_HOST": "localhost",
"DB_USER": "root",
"DB_PASSWORD": "your_mysql_password",
"DB_NAME": "weather_by_met"
}
```
**Step 5.3: Restart Cline**
- Click the Cline icon to restart
- Or reload VSCode window (Cmd+Shift+P โ "Reload Window")
---
**Path Examples** (replace with your actual path):
- **macOS**: `/Users/john/weather-by-met/server.py`
- **Windows**: `C:\Users\john\weather-by-met\server.py`
- **Linux**: `/home/john/weather-by-met/server.py`
#### Step 6: Test It!
Try asking your AI assistant:
```
"What's the weather in Kuala Lumpur today?"
"Give me a 3-day forecast for Penang"
"Show me weather for this Sunday in Langkawi"
```
You should see real weather data! ๐
### What Each File Does
| File | Purpose |
|------|---------|
| `server.py` | MCP server - Your AI assistant connects to this |
| `scheduler.py` | Runs in background - fetches weather data every 15 min |
| `init_db.py` | One-time setup - initializes MySQL database |
| `.env` | Your configuration - database credentials (don't commit!) |
| `.env.example` | Template showing what `.env` should contain |
### Important Configuration Details
- `"command": "python"` - Tells your MCP client to run Python
- `"args"` - Full absolute path to `server.py` (NOT relative path like `./server.py`)
- `"env"` - Environment variables passed to the server
- `DB_HOST`: Where MySQL is running (usually `localhost`)
- `DB_USER`: MySQL username (default is `root`)
- `DB_PASSWORD`: MySQL password you set during MySQL installation
- `DB_NAME`: Database name (leave as `weather_by_met`)
**Verify your path is correct**:
```bash
# Run this to check your weather-by-met path
ls -la /path/you/entered/server.py
# Should show: server.py (and not say "No such file or directory")
```
## ๐ ๏ธ Tools Available
Your MCP client can use these tools to fetch weather data:
### 1. check_weather_today
Check **today's weather forecast** for specific Malaysian locations.
**When used**: When asking for today's weather with **no specific timeframe mentioned** (e.g., "What's the weather today?", "Tell me the weather in Kuala Lumpur").
**Parameters**:
- `location_query` (string, optional): Location name (e.g., city, town, state). If not provided, your AI assistant may use device/browser location if available.
**Returns**:
- JSON formatted weather data with Malay forecasts for morning, afternoon, and night
- Includes day of the week for today
**Examples**:
```
"What's the weather in Langkawi today?"
"Tell me the weather in Kuala Lumpur"
"What's the weather in Selangor today?"
```
### 2. check_7day_forecast
Get **custom timeframe or specific day weather forecast** for Malaysian locations.
**Two modes available:**
#### Mode 1: Timeframe (use `days` parameter)
Use when a specific **timeframe** is requested (e.g., "Give me a 2-day forecast", "What's the weather tomorrow?", "Show me next week's weather").
**Parameters**:
- `location_query` (string, optional): Location name (e.g., city, town, state). If not provided, your AI assistant may use device/browser location if available.
- `days` (int): Number of days (1-7). Your AI assistant extracts this from the user's timeframe query.
**Forecast Semantics** (aligned with MET Malaysia's definition):
- `days=1` ("tomorrow"): Returns **only tomorrow's forecast**
- `days=2+` ("N-day forecast"): Returns **today + next (N-1) days** (inclusive of today as day 1)
- "2-day forecast" โ today + tomorrow
- "7-day forecast" โ today through day 7 (matching MET's official 7-day forecast)
**Examples**:
```
"What's the weather tomorrow in Penang?"
โ Returns only tomorrow
"Give me a 2-day forecast for Langkawi"
โ Returns today + tomorrow
"Show me a 7-day forecast for Kuala Lumpur"
โ Returns today through day 7
```
#### Mode 2: Specific Day (use `specific_day_name` parameter)
Use when a **specific day** is requested (e.g., "What's the weather for this Sunday?", "Show me weather for next Tuesday", "How will it be on Wednesday?").
**Parameters**:
- `location_query` (string, optional): Location name (e.g., city, town, state). If not provided, your AI assistant may use device/browser location if available.
- `specific_day_name` (string): Day name (e.g., 'Sunday', 'Monday', 'Tuesday', etc.). Your AI assistant extracts this from the user's query.
**Returns**: **ONLY the requested day's forecast**
**Examples**:
```
"What's the weather for this Sunday in Selangor?"
โ Returns ONLY Sunday's forecast
"Show me weather for next Tuesday"
โ Returns ONLY Tuesday's forecast
"How will it be on Wednesday in Kuala Lumpur?"
โ Returns ONLY Wednesday's forecast
```
**Returns** (both modes):
- JSON formatted weather data with Malay forecasts
- Includes day of the week for each forecast date
**Response Format**:
Your AI assistant presents the JSON data in a compact, easy-to-read format grouped by date:
```
Friday, Nov 7 - 23-32ยฐC
Johor (General):
Morning: Rain in inland areas
Afternoon: Thunderstorms
Night: No rain
Johor Bahru:
Morning: Rain
Afternoon: No rain
Night: No rain
Saturday, Nov 8 - 23-32ยฐC
Johor (General):
Morning: No rain
Afternoon: Thunderstorms
Night: No rain
Johor Bahru:
Morning: No rain
Afternoon: Thunderstorms
Night: No rain
Summary: [Weather pattern analysis]
```
**Important Notes**:
- Your AI assistant displays **ALL dates returned by the tool in the exact order received**
- For "2-day forecast" โ Shows **today + tomorrow** (e.g., Friday + Saturday)
- For "tomorrow" only โ Shows **only tomorrow** (e.g., Saturday)
- The assistant doesn't skip today or reinterpret the dates returned
- **Data Availability**: The tool ONLY provides forecasts from **TODAY onwards**
- Past/historical weather data is **NOT available**
- If users ask "What was the weather yesterday?" or similar, the assistant should inform them that only current and future forecasts are available
All locations are included for each date with their morning, afternoon, and night forecasts displayed on separate lines for clarity.
## ๐ Automated Jobs
### Job 1: Update Weather Forecast (Every 15 minutes)
Automatically fetches the latest weather forecast data from MET Malaysia API.
- **Frequency**: Every 15 minutes
- **API**: `https://api.data.gov.my/weather/forecast`
- **Action**: Inserts new records or updates existing ones
### Job 2: Clean Old Records (Daily at 12:05 AM)
Removes outdated weather forecast records.
- **Frequency**: Daily at 12:05 AM (Malaysia Time, GMT+8)
- **Action**: Deletes records where `forecast_date < today`
## ๐ Data Source
- **Provider**: MET Malaysia (Malaysian Meteorological Department)
- **Official Portal**: https://www.met.gov.my/
- **API Documentation**: https://developer.data.gov.my/realtime-api/weather
## โ๏ธ Configuration
### Environment Variables
| Variable | Description | Default | Required |
|----------|-------------|---------|----------|
| `DB_HOST` | MySQL host | localhost | Yes |
| `DB_USER` | MySQL user | root | Yes |
| `DB_PASSWORD` | MySQL password | (empty) | Yes |
| `DB_NAME` | Database name | weather_by_met | Yes |
| `TELEGRAM_BOT_TOKEN` | Telegram bot API token | (empty) | No |
| `TELEGRAM_CHAT_ID` | Telegram chat ID for alerts | (empty) | No |
### Telegram Alerts Setup (Optional)
To receive error alerts via Telegram when scheduler jobs encounter issues:
1. **Create a Telegram Bot**:
- Open Telegram and message [@BotFather](https://t.me/botfather)
- Send `/newbot` and follow the instructions
- Copy the API token provided
2. **Get Your Chat ID**:
- Create a private Telegram group or use a direct message with your bot
- Send a test message to the group
- Forward the message to [@userinfobot](https://t.me/userinfobot)
- Note the chat ID (negative number for groups)
3. **Configure Environment Variables**:
```bash
# Add to your .env file:
TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_CHAT_ID=your_chat_id_here
```
4. **How It Works**:
- Errors in the scheduler jobs (weather update, record cleanup) trigger Telegram alerts
- Successful operations run silently (no alerts)
- Each alert includes job name, timestamp, and error details
- If credentials are missing, the scheduler continues to work normally
## ๐ Try It Out
Once configured, try these with your AI assistant:
```
"What's the weather in Kuala Lumpur today?"
"Give me a 3-day forecast for Penang"
"Show me today's weather for all Malaysian states"
"What's the weather like in Langkawi this week?"
```
## ๐ Language Support
The server returns weather data in Malay as provided by MET Malaysia. Your AI assistant understands Malay and will:
- Automatically translate forecasts to your preferred language
- Provide context-aware weather interpretation
- Answer follow-up questions about weather in any language
This approach provides better multilingual support compared to fixed server-side translations.
## ๐งช Testing
Verify everything is working by testing the components:
**1. Test Database Connection**:
```bash
python init_db.py
# Should show: "Database connection successful" or create/verify the schema
```
**2. Test Server** (in a new terminal):
```bash
python server.py
# Should start the MCP server without errors
```
**3. Test Scheduler** (in another terminal):
```bash
python scheduler.py
# Should fetch initial weather data and show:
# "โ Fetched weather for X locations"
```
**4. Test with Your MCP Client**:
- Ask your AI assistant: "What's the weather in Kuala Lumpur?"
- Should return real weather data from the database
## ๐ Logging & Alerts
The scheduler logs all operations to `weather_scheduler.log`:
```bash
# View logs
tail -f weather_scheduler.log
# View last 100 lines
tail -n 100 weather_scheduler.log
# Monitor Telegram alerts
grep "โ๏ธ" weather_scheduler.log
```
**Log Entries**:
- โ
Successful operations logged at INFO level
- โ ๏ธ Errors logged at ERROR level
- โ๏ธ Telegram alerts confirmed when sent successfully
## ๐จ Troubleshooting
### Database connection failed
```bash
# Check MySQL is running
sudo systemctl status mysql
# Test connection
mysql -u root -p -e "SELECT 1;"
```
### No weather data
```bash
# Check scheduler is running
ps aux | grep scheduler.py
# Check logs
tail -f weather_scheduler.log
```
### Telegram alerts not working
**Verify credentials are set**:
```bash
# Check if credentials exist in .env
grep TELEGRAM .env
```
**Check Telegram bot token**:
- Ensure token is correctly copied from @BotFather
- Make sure the bot has been started (@BotFather `/start`)
**Verify chat ID**:
- Ensure chat ID is correct (negative number for groups)
- Test by sending a message to the group manually
**View Telegram send attempts in logs**:
```bash
# See if Telegram sends were attempted
grep -i "telegram\|โ๏ธ" weather_scheduler.log
```
**Missing Telegram credentials?**:
- If `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` are empty, the scheduler will still work normally
- Alerts are simply disabled; no errors will occur
## ๐ License
MIT License - see LICENSE file for details.
Data is provided by MET Malaysia through Malaysia's Open API initiative.
## ๐ Acknowledgments
- **MET Malaysia** - For providing free weather API
- **Anthropic** - For the FastMCP framework
- **Malaysian Government** - For the open data initiative
## ๐ Documentation
- **[MCP_CLIENT_SETUP.md](MCP_CLIENT_SETUP.md)** - Setup guide for Claude Desktop, Cline, and other MCP clients
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - How to contribute to this project
- **[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)** - Community guidelines
All times are in **Malaysia Time (GMT+8)**