Production-ready MCP server for accessing comprehensive weather data from OpenWeatherMap.
- Enterprise ready: Production-ready with separation of concerns, strong typing, and comprehensive testing
- Full API Coverage: Current weather, forecasts, air quality, UV index
- 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: 100% coverage with pytest + AsyncMock
- Panama Locations: Built-in coordinates for major Panama cities
src/mcp_openweathermap/
├── __init__.py # Package exports
├── server.py # FastMCP server with 6 MCP tools
├── api_client.py # OpenWeatherMapClient with aiohttp
├── api_models.py # Pydantic models for type safety
└── utils.py # Helper functions and solar calculations
tests/
├── test_server.py # MCP tool tests
└── test_api_client.py # API client tests
- Python >=3.10
- OpenWeatherMap API key from openweathermap.org
# Install dependencies
uv pip install -e .
# Install with dev dependencies
uv pip install -e . --group devpip install -e .Set your API key as an environment variable:
export OPENWEATHERMAP_API_KEY=your_api_key_hereOr create a .env file:
OPENWEATHERMAP_API_KEY=your_api_key_here
# Using make
make run
# Or directly
uv run python -m mcp_openweathermap.server# Using make
make run-http
# Or directly
uv run uvicorn mcp_openweathermap.server:app --host 0.0.0.0 --port 8000# 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-openweathermapGet current weather conditions for a location.
Parameters:
location(str, optional): Location name (e.g., 'Panama City', 'London,GB')lat(float, optional): Latitude coordinate (use with lon)lon(float, optional): Longitude coordinate (use with lat)units(str, default='metric'): Units ('metric', 'imperial', 'standard')
Returns: Current weather data including temperature, humidity, pressure, wind, clouds
Example:
# By location name
get_current_weather(location="Panama City")
# By coordinates
get_current_weather(lat=8.9824, lon=-79.5199)Get 5-day weather forecast with 3-hour intervals.
Parameters:
location(str, optional): Location namelat(float, optional): Latitude coordinate (use with lon)lon(float, optional): Longitude coordinate (use with lat)units(str, default='metric'): Unitsdays(int, optional): Number of days to forecast (max: 5)
Returns: 5-day forecast data with 3-hour intervals
Get air quality index and pollutant concentrations.
Parameters:
location(str, optional): Location namelat(float, optional): Latitude coordinate (use with lon)lon(float, optional): Longitude coordinate (use with lat)
Returns: Air quality data with AQI (1=Good to 5=Very Poor) and pollutant levels (CO, NO, NO2, O3, SO2, PM2.5, PM10, NH3)
Get UV index for a location.
Parameters:
location(str, optional): Location namelat(float, optional): Latitude coordinate (use with lon)lon(float, optional): Longitude coordinate (use with lat)
Returns: UV index data (0-2: Low, 3-5: Moderate, 6-7: High, 8-10: Very High, 11+: Extreme)
Get solar radiation data for solar energy calculations.
Parameters:
location(str, optional): Location namelat(float, optional): Latitude coordinate (use with lon)lon(float, optional): Longitude coordinate (use with lat)
Returns: Solar radiation data including:
avg_daily_kwh_m2: Average daily solar radiation (kWh/m²)peak_sun_hours: Equivalent peak sun hours per daymonthly_averages: Monthly solar radiation estimates for all 12 monthscoordinates: Location coordinatescloud_cover_factor: Cloud cover reduction factoruv_index_avg: Average UV index
Response Format:
{
"location": "Panama City, Panama",
"coordinates": {"lat": 8.9824, "lon": -79.5199},
"avg_daily_kwh_m2": 5.2,
"peak_sun_hours": 5.2,
"monthly_averages": {
"january": 5.8,
"february": 6.1,
...
},
"source": "OpenWeatherMap"
}Convert location name to geographic coordinates.
Parameters:
location(str, required): Location name
Returns: Coordinates and location information including lat, lon, country
Supports:
- Known Panama locations (Panama City, David, Colón, Santiago, Chitré, La Chorrera, Bocas del Toro, Penonomé)
- Any city worldwide via OpenWeatherMap geocoding
The server includes built-in coordinates for major Panama cities:
| City | Latitude | Longitude |
|---|---|---|
| Panama City | 8.9824 | -79.5199 |
| David | 8.4270 | -82.4278 |
| Colón | 9.3592 | -79.9009 |
| Santiago | 8.1000 | -80.9833 |
| Chitré | 7.9614 | -80.4289 |
| La Chorrera | 8.8800 | -79.7833 |
| Bocas del Toro | 9.3400 | -82.2400 |
| Penonomé | 8.5167 | -80.3500 |
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# 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# Format code
make format
# Lint code
make lint
# Type check
make typecheck
# Run all quality checks
make checkThe get_solar_radiation tool calculates solar radiation using:
-
Latitude: Affects solar angle and day length
- Equatorial (0-10°): 5.8 kWh/m²/day base
- Tropical (10-23.5°): 5.5 kWh/m²/day base
- Subtropical (23.5-35°): 4.5 kWh/m²/day base
-
Cloud Cover: Reduces solar radiation by up to 75%
- Clear sky (0% clouds): Full radiation
- Overcast (100% clouds): 25% radiation
-
UV Index: Correlates with solar intensity
- Used as adjustment factor (0.7-1.5x)
-
Seasonal Patterns: Monthly variation based on latitude
- Northern hemisphere: Peak in June
- Southern hemisphere: Peak in December
Formula:
radiation = base_radiation × (1 - cloud_cover × 0.75) × uv_factor × seasonal_factor
For detailed OpenWeatherMap API documentation:
- Python >=3.10
- aiohttp >=3.12.15
- fastapi >=0.117.1
- fastmcp >=2.12.4
- pydantic >=2.0.0
- uvicorn >=0.32.1
- 1,000 calls/day
- 60 calls/minute
- Current weather and 5-day forecast
- Air pollution data
- UV index
For higher limits, see OpenWeatherMap pricing.
When running in HTTP mode, a health check endpoint is available:
curl http://localhost:8000/health
# {"status": "healthy", "service": "openweathermap-mcp"}- Fork the repository
- Create a feature branch
- Make your changes
- Run
make checkto ensure quality - Submit a pull request
For issues or questions:
- OpenWeatherMap API: support.openweathermap.org
- MCP Server: Create an issue in the repository
MIT
Part of the NimbleTools Registry - an open source collection of production-ready MCP servers. For enterprise deployment, check out NimbleBrain.