mcp-openweathermap

NimbleBrainInc/mcp-openweathermap

3.2

If you are the rightful owner of mcp-openweathermap and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.

MCP server for accessing comprehensive weather data from OpenWeatherMap.

Tools
10
Resources
0
Prompts
0

OpenWeatherMap MCP Server

NimbleTools Registry NimbleBrain Platform Discord

Python 3.13+ License: MIT CI

About

Production-ready MCP server for accessing comprehensive weather data from OpenWeatherMap.

Features

  • Hybrid Tool Design: 5 tools balancing convenience with LLM reasoning capability
  • Graceful Degradation: Automatically uses One Call API when available, falls back to free tier
  • Smart Fallback Pattern: When location lookup fails, error message guides LLM to use search_location
  • Flexible Input: All weather tools accept either location string OR direct lat/lon coordinates
  • Strongly Typed: All responses use Pydantic models with full type safety
  • HTTP & Stdio Transport: Supports both streamable-http and stdio for Claude Desktop
  • Async/Await: Built on aiohttp for high performance
  • Type Safe: Full mypy strict mode compliance
  • Comprehensive Tests: Full coverage with pytest + AsyncMock
  • Built-in Skill Resource: Serves a skill://openweathermap/usage resource that teaches LLMs location resolution patterns and tool selection

Architecture

src/mcp_openweathermap/
├── __init__.py          # Package exports
├── server.py            # FastMCP server with 4 intent-based tools
├── api_client.py        # OpenWeatherMapClient with graceful degradation
├── api_models.py        # Pydantic models for type safety
└── utils.py             # Helper functions

tests/
├── test_server.py       # MCP tool tests
└── test_api_client.py   # API client tests

Installation

Prerequisites

Using uv (recommended)

# Install dependencies
uv pip install -e .

# Install with dev dependencies
uv pip install -e . --group dev

Using pip

pip install -e .

Configuration

Set your API key as an environment variable:

export OPENWEATHERMAP_API_KEY=your_api_key_here

Or create a .env file:

OPENWEATHERMAP_API_KEY=your_api_key_here

Running the Server

Stdio Mode (for Claude Desktop)

# Using make
make run

# Or directly
uv run python -m mcp_openweathermap.server

HTTP Mode (for web applications)

# Using make
make run-http

# Or directly
uv run uvicorn mcp_openweathermap.server:app --host 0.0.0.0 --port 8000

Docker

# Build image
make docker-build

# Run container
make docker-run OPENWEATHERMAP_API_KEY=your_key

# Or using docker directly
docker build -t mcp-openweathermap .
docker run -p 8000:8000 -e OPENWEATHERMAP_API_KEY=your_key mcp-openweathermap

Available MCP Tools

1. search_location

Resolve location query to coordinates. Use when direct location lookup fails or for ambiguous queries.

Parameters:

  • query (str): Location search query (city name, landmark, etc.)
  • limit (int, default=5): Max results to return

Returns: List of matching locations with name, state, country, lat, lon

Example:

# Disambiguate "Springfield" (exists in many US states)
search_location(query="Springfield")
# Returns multiple candidates - LLM picks the right one

# Find Waimea in Hawaii (direct lookup fails for "Waimea, HI")
search_location(query="Waimea")
# Returns candidates in Hawaii and elsewhere

2. check_weather

Get current weather conditions. Pass location string OR lat/lon coordinates.

Parameters:

  • location (str, optional): City name (e.g., 'London', 'Tokyo')
  • lat (float, optional): Latitude (use with lon instead of location)
  • lon (float, optional): Longitude (use with lat instead of location)
  • units (str, default='metric'): Temperature units ('metric', 'imperial', 'standard')

Returns: Current temperature, humidity, wind, weather conditions, and location info

Example:

# By city name (fast path)
check_weather(location="London")

# By coordinates (precise path - use after search_location)
check_weather(lat=20.02, lon=-155.66)

# With imperial units
check_weather(location="Tokyo", units="imperial")

Fallback Pattern: If location lookup fails, error suggests using search_location first.

3. get_forecast

Get weather forecast. Pass location string OR lat/lon coordinates.

Parameters:

  • location (str, optional): City name
  • lat (float, optional): Latitude
  • lon (float, optional): Longitude
  • units (str, default='metric'): Temperature units

Returns: Forecast data with source field indicating tier:

  • one_call: Hourly (48h) + daily (8-day) forecasts with weather alerts
  • free_tier: 5-day forecast with 3-hour intervals (automatic fallback)

Example Response (One Call):

{
  "source": "one_call",
  "hourly": [...],
  "daily": [...],
  "alerts": [],
  "timezone": "Europe/London"
}

Example Response (Free Tier Fallback):

{
  "source": "free_tier",
  "forecast_list": [...],
  "city": {"name": "London"},
  "alerts": [],
  "note": "Hourly forecast and alerts require One Call API subscription"
}

4. check_air_quality

Get air quality index and pollutant levels. Pass location string OR lat/lon coordinates.

Parameters:

  • location (str, optional): City name
  • lat (float, optional): Latitude
  • lon (float, optional): Longitude

Returns: Air Quality Index (1=Good to 5=Very Poor) and concentrations of CO, NO, NO2, O3, SO2, PM2.5, PM10, NH3

5. get_historical_weather

Get historical weather data for a past date. Requires One Call API subscription.

Parameters:

  • date (str, required): Date in YYYY-MM-DD format (within approximately last 5 days)
  • location (str, optional): City name
  • lat (float, optional): Latitude
  • lon (float, optional): Longitude
  • units (str, default='metric'): Temperature units

Returns: Historical weather data or helpful error if subscription not available

Example Response (Success):

{
  "source": "one_call",
  "lat": 51.5,
  "lon": -0.1,
  "timezone": "Europe/London",
  "current": {"temp": 12.5, ...}
}

Example Response (No Subscription):

{
  "error": "Historical weather requires One Call API subscription",
  "subscription_url": "https://openweathermap.org/api/one-call-3"
}

LLM Fallback Pattern

The tools are designed so that when direct location lookup fails, the LLM can reason about alternatives:

  1. Try direct: check_weather(location="Waimea, HI") → fails with hint
  2. Search: search_location(query="Waimea") → returns candidates
  3. Pick & retry: check_weather(lat=20.02, lon=-155.66) → succeeds

This pattern handles:

  • US state abbreviations ("HI" vs "Hawaii")
  • Country code variations ("UK" vs "GB")
  • Ambiguous locations (multiple "Springfield"s)

API Tiers

FeatureFree TierOne Call API
Current weatherYesYes
5-day/3-hour forecastYesYes
Hourly forecast (48h)NoYes
Daily forecast (8 days)NoYes
Weather alertsNoYes
Historical dataNoYes
Air qualityYesYes
Rate limit1M calls/month1000 free/day

The server automatically detects your API tier and uses the best available data.

Development

Available Make Commands

make help          # Show all commands
make install       # Install dependencies
make dev-install   # Install with dev dependencies
make format        # Format code with ruff
make lint          # Lint code with ruff
make lint-fix      # Lint and auto-fix issues
make typecheck     # Type check with mypy
make test          # Run tests
make test-cov      # Run tests with coverage
make clean         # Clean up artifacts
make run           # Run server (stdio)
make run-http      # Run server (HTTP)
make check         # Run all checks (lint + typecheck + test)
make all           # Full workflow

Running Tests

# Run all tests
make test

# Run with coverage
make test-cov

# Run specific test file
uv run pytest tests/test_server.py -v

# Run specific test
uv run pytest tests/test_server.py::TestMCPTools::test_get_solar_radiation -v

Code Quality

# Format code
make format

# Lint code
make lint

# Type check
make typecheck

# Run all quality checks
make check

API Documentation

For detailed OpenWeatherMap API documentation:

Requirements

  • Python >=3.10
  • aiohttp >=3.12.15
  • fastapi >=0.117.1
  • fastmcp >=2.12.4
  • pydantic >=2.0.0
  • uvicorn >=0.32.1

Rate Limits

  • Free Tier: 1,000,000 calls/month, 60 calls/minute
  • One Call API: 1,000 free calls/day, then pay-per-call

For pricing details, see OpenWeatherMap pricing.

Health Check

When running in HTTP mode, a health check endpoint is available:

curl http://localhost:8000/health
# {"status": "healthy", "service": "openweathermap-mcp"}

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run make check to ensure quality
  5. Submit a pull request

Support

For issues or questions:

License

MIT

Links

Part of the NimbleTools Registry - an open source collection of production-ready MCP servers. For enterprise deployment, check out NimbleBrain.