smhi-mcp

hniska/smhi-mcp

3.2

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

The SMHI MCP Server is a Model Context Protocol server that provides Swedish weather data through SMHI's open APIs, deployed as a Cloudflare Worker.

Tools
5
Resources
0
Prompts
0

SMHI MCP Server

A Model Context Protocol (MCP) server that provides Swedish weather data through SMHI's open APIs, deployed as a Cloudflare Worker.

Deploy to Cloudflare Workers

🌀️ Features

  • Real-time Weather Data: Access current weather conditions from SMHI weather stations
  • Weather Forecasts: Get detailed forecasts for any location in Sweden
  • Station Search: Find weather stations by name using fuzzy matching
  • Multi-Resolution Data: Access hourly, daily, and monthly weather data
  • Historical Data: Query past weather records with pagination and date filtering
  • MCP Protocol: Full compatibility with Claude and other MCP clients
  • Serverless: Runs on Cloudflare Workers with global edge deployment
  • No API Keys Required: Uses SMHI's free open data APIs
  • Smart Caching: Multi-level caching with Cloudflare Cache API and R2 storage for optimal performance
  • Rate Limiting: Built-in request rate limiting to respect SMHI API limits

πŸš€ Live Demo

Deployed Server: https://smhi-mcp.hakan-3a6.workers.dev

πŸ“‹ Available Tools (19 Total)

Snowmobile Conditions Tools

ToolDescriptionParameters
list_snowmobile_conditionsList weather stations for snowmobile conditions by region with capability infoNone
get_station_temperatureGet latest temperature reading from a specific stationstation_id (string)
get_station_snow_depthGet latest snow depth reading from a specific stationstation_id (string)
get_weather_forecastGet weather forecast for coordinateslat (number), lon (number)

Legacy Tools (Deprecated)

ToolDescriptionParameters
list_temperature_stations[DEPRECATED] Use list_snowmobile_conditions insteadNone
list_snow_depth_stations[DEPRECATED] Use list_snowmobile_conditions insteadNone

Multi-Resolution Data Tools

ToolDescriptionParameters
get_station_precipitationGet precipitation data with multiple resolutionsstation_id, parameter (5=daily, 7=hourly, 14=15min, 23=monthly), period
get_temperature_multi_resolutionGet temperature data with multiple resolutionsstation_id, parameter (1=hourly, 2=daily-mean, 19=min, 20=max, 22=monthly), period
get_station_metadataGet detailed station metadata and available periodsstation_id, parameter

Historical Data & Pagination

ToolDescriptionParameters
get_historical_dataGet historical data with pagination and date filteringstation_id, parameter, period, limit, cursor, reverse, fromDate, toDate
list_all_temperature_stationsGet all temperature stations with paginationcursor (optional)
list_all_snow_depth_stationsGet all snow depth stations with paginationcursor (optional)
list_all_precipitation_stationsGet all precipitation stations with paginationparameter, cursor

Station Search Tools

ToolDescriptionParameters
search_stations_by_nameSearch stations by name within a specific parameter typequery, parameter (1=temp, 5=precip, 8=snow), limit, threshold, active_only
search_stations_by_name_multi_paramSearch stations by name across all parameter typesquery, limit, threshold, active_only
Search Parameters Details
  • query (required): Station name to search for (fuzzy matching)
  • parameter (search_stations_by_name only): Parameter type filter
    • 1 = Temperature stations
    • 5 = Daily precipitation stations
    • 7 = Hourly precipitation stations
    • 8 = Snow depth stations
  • limit (optional, default: 10): Maximum number of results to return
  • threshold (optional, default: 0.3): Minimum similarity score (0.0-1.0) for fuzzy matching
  • active_only (optional, default: true): Only return stations with recent data activity

πŸ› οΈ Quick Start

Option 1: Use the Deployed Server

Connect your MCP client to: https://smhi-mcp.hakan-3a6.workers.dev

Option 2: Deploy Your Own

# Clone the repository
git clone https://github.com/yourusername/smhi-mcp.git
cd smhi-mcp

# Install dependencies
npm install

# Create R2 bucket for caching (required)
wrangler r2 bucket create smhi-historical-data

# Deploy to Cloudflare Workers
npm run deploy

Option 3: Local Development

# Start local development server
npm run dev

# The server will be available at http://localhost:8787

πŸ“‘ MCP Protocol Examples

Initialize Connection

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {}
  }
}

List Available Tools

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list"
}

Get Weather Forecast (Stockholm)

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "get_weather_forecast",
    "arguments": {
      "lat": 59.3293,
      "lon": 18.0686
    }
  }
}

List Snowmobile Conditions Stations

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "list_snowmobile_conditions",
    "arguments": {}
  }
}

Get Station Temperature

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "get_station_temperature",
    "arguments": {
      "station_id": "159880"
    }
  }
}

Search for Weather Stations

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "search_stations_by_name_multi_param",
    "arguments": {
      "query": "Stockholm",
      "limit": 5,
      "threshold": 0.3,
      "active_only": true
    }
  }
}

Get Historical Data with Pagination

{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "tools/call",
  "params": {
    "name": "get_historical_data",
    "arguments": {
      "station_id": "159880",
      "parameter": "1",
      "period": "corrected-archive",
      "limit": 20,
      "fromDate": "2024-01-01",
      "toDate": "2024-01-31"
    }
  }
}

πŸ§ͺ Testing

Using cURL

# Test MCP initialization
curl -X POST -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2024-11-05", "capabilities": {}}}' \
  https://smhi-mcp.hakan-3a6.workers.dev

# List snowmobile conditions stations
curl -X POST -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "list_snowmobile_conditions", "arguments": {}}}' \
  https://smhi-mcp.hakan-3a6.workers.dev

# Test weather forecast for Stockholm
curl -X POST -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": {"name": "get_weather_forecast", "arguments": {"lat": 59.3293, "lon": 18.0686}}}' \
  https://smhi-mcp.hakan-3a6.workers.dev

# Search for weather stations
curl -X POST -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 5, "method": "tools/call", "params": {"name": "search_stations_by_name_multi_param", "arguments": {"query": "Stockholm", "limit": 3}}}' \
  https://smhi-mcp.hakan-3a6.workers.dev

Using Make Commands

# Run built-in tests
make test-mcp
make test-forecast
make test-stations

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   MCP Client    β”‚    β”‚  Cloudflare     β”‚    β”‚   SMHI APIs     β”‚
β”‚   (Claude)      │◄──►│    Worker       │◄──►│  (opendata)     β”‚
β”‚                 β”‚    β”‚  (smhi-mcp)     β”‚    β”‚                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The server acts as a bridge between MCP clients and SMHI's weather APIs:

  1. MCP Client sends JSON-RPC requests
  2. Cloudflare Worker processes requests and calls SMHI APIs
  3. SMHI APIs provide real-time weather data
  4. Worker formats response according to MCP protocol

⚑ Performance & Caching

The server implements a multi-level caching strategy for optimal performance:

Cloudflare Cache API

  • Current weather data: 15 minutes TTL
  • Weather forecasts: 30 minutes TTL
  • Station metadata: 1 week TTL
  • Historical data: 24 hours TTL

R2 Storage (CSV Data)

  • Standard CSV files: 24 hours TTL
  • Recent year data: 1 hour TTL (more volatile)
  • Historical data (>2 years): 1 week TTL (stable)

Rate Limiting

  • 30 requests per minute maximum to respect SMHI API limits
  • Automatic request throttling with user-friendly error messages

Configuration Requirements

# wrangler.toml - R2 bucket for CSV caching
[[r2_buckets]]
binding = "HISTORICAL_DATA"
bucket_name = "smhi-historical-data"

πŸ“Š Data Sources

All weather data comes from SMHI (Swedish Meteorological and Hydrological Institute):

  • Observations API: Real-time weather station data
  • Forecast API: Weather predictions up to 10 days
  • Station Metadata: Information about monitoring stations

Sample Weather Stations

Station IDNameLocationNote
159880ArvidsjaurNorthern SwedenTemperature & precipitation
155960TΓ€rnaby/HemavanMountain regionTemperature data
155940MosekΓ€lla/HemavanMountain regionSame location, different parameter names
132170Storlien-StorvallenNorwegian borderAlpine weather station
188850KatterjΓ₯kk/RiksgrΓ€nsenArctic regionNorthernmost station

Note: Some stations have different names depending on the parameter type. Use search_stations_by_name_multi_param to find stations across all data types.

Active Filtering: By default, search tools only return stations with recent data activity. Set active_only: false to include all stations, including inactive ones.

πŸ”§ Configuration

Required Configuration

The worker requires an R2 bucket for CSV caching:

# wrangler.toml - Required R2 configuration
[[r2_buckets]]
binding = "HISTORICAL_DATA" 
bucket_name = "smhi-historical-data"

Optional Environment Variables

# wrangler.toml - Optional configuration
[env.production.vars]
# Add public configuration here

# Optional secrets for authentication
[[env.production.secrets]]
API_KEY = "your-api-key-for-auth"

Authentication (Optional)

To enable API key authentication, set the API_KEY secret:

wrangler secret put API_KEY

πŸ“‹ Development Commands

# Install dependencies
make install

# Start development server
make dev

# Deploy to Cloudflare
make deploy

# View logs
make logs

# Show deployment status
make status

# Run tests
make test-mcp

Modular Architecture

The codebase has been refactored into a modular structure:

src/
β”œβ”€β”€ api/          # SMHI API integration
β”œβ”€β”€ config/       # Constants and configuration
β”œβ”€β”€ data/         # Station data and presets
β”œβ”€β”€ handlers/     # WebSocket and SSE handlers
β”œβ”€β”€ mcp/          # MCP protocol server
β”œβ”€β”€ middleware/   # Rate limiting and middleware
β”œβ”€β”€ services/     # Weather data services
β”œβ”€β”€ tools/        # MCP tool definitions
└── utils/        # Caching and utility functions

🌍 Claude Integration

To use this server with Claude:

  1. Desktop App: Add the server URL in Claude's MCP settings
  2. API: Include the server in your MCP client configuration
  3. Custom Integration: Use the JSON-RPC protocol directly

Example Claude conversations:

You: "Show me weather stations for snowmobile conditions"
Claude: "Let me get the snowmobile conditions monitoring stations for you."
[Uses list_snowmobile_conditions]
Claude: "Here are 18 weather stations organized by region for snowmobile conditions. The Arctic/Mountain region has KatterjΓ₯kk/RiksgrΓ€nsen with both temperature and snow depth data..."

You: "What's the current temperature in Arvidsjaur?"
Claude: "Let me check the current temperature in Arvidsjaur for you."
[Uses get_station_temperature with station_id "159880"]
Claude: "The current temperature in Arvidsjaur is 15.8Β°C."

You: "Find weather stations near Stockholm"
Claude: "Let me search for weather stations near Stockholm."
[Uses search_stations_by_name_multi_param with query "Stockholm"]
Claude: "I found several weather stations near Stockholm, including Stockholm A (98230) and Stockholm-Observatoriekullen (98210)."

You: "Show me temperature data for MosekΓ€lla from January 2024"
Claude: "Let me search for MosekΓ€lla and get the temperature data."
[Uses search_stations_by_name_multi_param with query "MosekΓ€lla"]
[Uses get_historical_data with station_id "155940", fromDate "2024-01-01", toDate "2024-01-31"]
Claude: "Found MosekΓ€lla (station 155940) - here's the temperature data for January 2024..."

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development Setup

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Make your changes
  4. Test locally: npm run dev
  5. Deploy and test: npm run deploy
  6. Submit a pull request

πŸ“„ License

This project is open source and available under the .

πŸ”— Related Projects

πŸ“ž Support


Built with ❀️ for the MCP ecosystem | Powered by SMHI Open Data | Deployed on Cloudflare Workers