Skip to main content
Glama
AdhipathiK

Weather MCP Server

by AdhipathiK
README.md
## Overview

This project implements a Model Context Protocol (MCP) server that exposes weather forecast tools, backed by the Open-Meteo API. It can be deployed as a Databricks App and integrated with Agent Bricks to answer natural-language weather questions.

## Architecture

```
┌────────────────────────────────────────────┐
│  Weather MCP Server (Databricks App)      │
│  ┌──────────────────────────────────────┐ │
│  │  weather_mcp_server.py               │ │
│  │  - FastMCP with @mcp.tool decorators │ │
│  │  - get_current_weather()             │ │
│  │  - get_forecast()                    │ │
│  │  - predict_umbrella_needed()         │ │
│  └──────────────────────────────────────┘ │
│             ↓                              │
│  ┌──────────────────────────────────────┐ │
│  │  weather_broker.py                   │ │
│  │  - HTTP calls to Open-Meteo API      │ │
│  │  - Geocoding (city → lat/lon)        │ │
│  │  - Weather code decoding (WMO)       │ │
│  │  - Error handling                    │ │
│  └──────────────────────────────────────┘ │
└────────────────────────────────────────────┘
                   ↓ MCP protocol
┌────────────────────────────────────────────┐
│  Agent Bricks Agent                        │
│  - Uses weather tools via MCP              │
│  - Answers natural language questions      │
│  - Makes recommendations                   │
└────────────────────────────────────────────┘
```

## Project Structure

```
weather_mcp_server/
├── weather_mcp_server.py   # FastMCP server with tool decorators
├── weather_broker.py        # API adapter (HTTP calls, parsing)
├── app.yaml                 # Databricks App configuration
├── requirements.txt         # Python dependencies
└── README.md                # This file
```

## MCP Tools (3 Required)

### 1. `get_current_weather(location: str)`
**Purpose**: Fetch real-time weather conditions for any location.

**Arguments**:
- `location` (str): City name or "City, Country" format

**Returns**: JSON with temperature (C/F), conditions, humidity, wind speed, precipitation, cloud cover

**Example**:
```python
get_current_weather("Chicago")
# Returns: {"location": {"name": "Chicago", "country": "United States"}, 
#           "current": {"temperature_c": 22.5, "conditions": "Partly cloudy", ...}}
```

---

### 2. `get_forecast(location: str, days: int = 7)`
**Purpose**: Multi-day weather forecast (1-16 days ahead).

**Arguments**:
- `location` (str): City name
- `days` (int): Number of forecast days (1-16, default 7)

**Returns**: JSON with daily high/low temps, precipitation chance/amount, conditions, wind speed

**Example**:
```python
get_forecast("Seattle", 3)
# Returns: {"location": {...}, "forecast": [
#   {"date": "2026-08-09", "temp_max_c": 24.0, "precipitation_chance": 60, ...},
#   {...}, {...}
# ]}
```

---

### 3. `predict_umbrella_needed(location: str, date: str = None, threshold_percent: int = 40)`
**Purpose**: Smart recommendation - should you bring an umbrella?

**Arguments**:
- `location` (str): City name
- `date` (str, optional): Target date in "YYYY-MM-DD" format (default: tomorrow)
- `threshold_percent` (int, optional): Precipitation probability threshold (default: 40)

**Decision Logic** (NOT just a passthrough):
- Recommends umbrella if **EITHER**:
  1. Precipitation chance > `threshold_percent` (default 40%), OR
  2. Expected rainfall >= 2mm

**Returns**: JSON with recommendation, reasoning, forecast details, and decision rule explanation

**Example**:
```python
predict_umbrella_needed("Portland", "2026-08-15")
# Returns: {
#   "recommendation": "Yes, bring an umbrella",
#   "reasoning": "High chance of rain (65% > 40% threshold) with significant rainfall...",
#   "forecast_details": {"precipitation_chance": 65, "precipitation_mm": 4.5, ...},
#   "decision_rule": "Umbrella recommended if: (precipitation_chance > 40%) OR (expected_rainfall >= 2mm)"
# }
```

---

## Weather API Details

**API Used**: [Open-Meteo](https://open-meteo.com/en/docs)  
**Authentication**: None required (free tier, up to ~10,000 calls/day for non-commercial use)  
**Endpoints Used**:
- Geocoding API: `https://geocoding-api.open-meteo.com/v1/search`
- Forecast API: `https://api.open-meteo.com/v1/forecast`

**Why Open-Meteo?**
- No signup or API key required
- Free and reliable
- Returns WMO weather codes (decoded to human-readable strings)
- Supports both current conditions and multi-day forecasts

---

## Setup Instructions

### Step 1: Deploy the MCP Server as a Databricks App

1. **Navigate to Databricks Apps**:
   - In your Databricks workspace, go to **Compute** → **Apps**

2. **Create a new app**:
   ```bash
   databricks apps create weather-mcp-server \
     --source-code-path /Workspace/Users/<your-email>/weather_mcp_server
   ```

3. **Deploy the app**:
   ```bash
   databricks apps deploy weather-mcp-server
   ```

4. **Get the app URL**:
   ```bash
   databricks apps get weather-mcp-server
   ```
   Note the `url` field - you'll need this for Agent Bricks registration.

### Step 2: Register the MCP Server with Agent Bricks

1. **Navigate to Agent Bricks**:
   - In Databricks, go to **Machine Learning** → **Agents**

2. **Create a new agent** or **edit an existing one**

3. **Add External Tool**:
   - Click "Add Tool" → "External MCP Tool"
   - **Tool URL**: `<your-app-url>` (from Step 1)
   - **Tool Type**: MCP

4. **Configure System Prompt**:
   ```
   You are a weather assistant powered by real-time weather data.
   
   Available tools:
   - get_current_weather(location): Get current conditions
   - get_forecast(location, days): Get multi-day forecast (1-16 days)
   - predict_umbrella_needed(location, date, threshold_percent): Smart umbrella recommendation
   
   Guidelines:
   - Always call tools to get data - never guess or hallucinate weather information
   - If a location cannot be found, ask the user to clarify or provide a different location
   - For umbrella predictions, explain the reasoning based on the decision rule
   - Present temperatures in both Celsius and Fahrenheit
   - If an API call fails, inform the user clearly rather than making up data
   ```

5. **Save and test**!

### Step 3: Test the Agent

Try these example queries:

1. **Current conditions**:
   - "What's the weather like in Chicago right now?"
   - "Tell me the current temperature in Tokyo"

2. **Forecasts**:
   - "Will it rain in Seattle this weekend?"
   - "What's the 5-day forecast for Austin?"

3. **Recommendations**:
   - "Should I bring an umbrella to Boston tomorrow?"
   - "Do I need a jacket in San Francisco on August 12th?"

---

## Key Design Decisions

### 1. **Separation of Concerns**
- `weather_broker.py`: All HTTP calls, geocoding, error handling
- `weather_mcp_server.py`: Thin MCP tool wrappers, JSON serialization
- **Benefit**: MCP tools stay clean and testable; broker can be mocked

### 2. **No Hardcoded Credentials**
- Open-Meteo requires no API key
- If using a different API, follow this pattern:
  ```python
  from databricks.sdk import WorkspaceClient
  
  def _get_api_key():
      w = WorkspaceClient()
      return w.secrets.get_secret(scope="weather", key="api_key").value
  ```

### 3. **Error Handling**
- Custom `WeatherBrokerError` exception
- All tools return JSON (never raise exceptions to MCP client)
- Clear error messages: `{"error": "Location 'XYZ' not found"}`

### 4. **Prediction Tool Design**
- **NOT** just a passthrough of raw forecast data
- Applies business logic: `(precip_chance > threshold) OR (precip_mm >= 2mm)`
- Explains reasoning in natural language
- Includes decision rule in output for transparency

---

## Testing Locally (Optional)

You can test the MCP server locally before deploying:

```bash
# Install dependencies
pip install -r requirements.txt

# Run the server
python weather_mcp_server.py

# Server will start on http://localhost:8000
# Use MCP client or curl to test tools
```

---

## Example Agent Interactions

### Example 1: Current Weather
**User**: "What's the weather in London right now?"

**Agent**:  
→ Calls `get_current_weather("London")`  
← Returns: `{"current": {"temperature_c": 18.5, "temperature_f": 65.3, "conditions": "Partly cloudy", ...}}`  
**Response**: "In London, it's currently 18.5°C (65.3°F) with partly cloudy skies. Humidity is at 72%, and winds are light at 12 km/h."

---

### Example 2: Forecast Query
**User**: "Will it rain in Portland this week?"

**Agent**:  
→ Calls `get_forecast("Portland", 7)`  
← Returns: `{"forecast": [{"date": "2026-08-09", "precipitation_chance": 65, ...}, ...]}`  
**Response**: "Looking at Portland's 7-day forecast, rain is likely on:
- **Aug 9**: 65% chance, 4.5mm expected (Moderate rain)
- **Aug 11**: 40% chance, 2.1mm expected (Light rain showers)

The rest of the week looks mostly dry!"

---

### Example 3: Umbrella Recommendation
**User**: "Should I bring an umbrella to Austin tomorrow?"

**Agent**:  
→ Calls `predict_umbrella_needed("Austin", "tomorrow")`  
← Returns: `{"recommendation": "No umbrella needed", "reasoning": "Low precipitation chance (15% <= 40% threshold) and minimal expected rainfall (0.2mm < 2mm)..."}`  
**Response**: "**No umbrella needed** for Austin tomorrow (Aug 9)! There's only a 15% chance of rain with minimal expected rainfall (0.2mm). Conditions will be mainly clear with highs of 34°C (93°F)."

---

## Stretch Features (Not Implemented, Ideas for Extra Credit)

1. **Severe weather alerts** (using NWS API for US locations)
2. **Historical weather lookup** ("What was the weather in NYC last Christmas?")
3. **Multi-city comparison** ("Which is warmer this weekend, Miami or LA?")
4. **Packing recommendations** ("What should I pack for a trip to Iceland next week?")
5. **Dashboard app** showing recent agent queries and predictions

---

## Troubleshooting

**Problem**: "Location 'XYZ' not found"  
**Solution**: Try a more specific location (e.g., "Springfield, Illinois" instead of "Springfield")

**Problem**: MCP tools not showing up in Agent Bricks  
**Solution**: Verify the app is deployed and the URL is correct. Check app logs: `databricks apps logs weather-mcp-server`

**Problem**: "Forecast API error: timeout"  
**Solution**: Open-Meteo may be temporarily unavailable. Retry after a minute.

---