Skip to main content
Glama
hniska
by hniska
README.md
# Trafikverket MCP Server

A Model Context Protocol (MCP) server providing real-time access to Swedish road weather, traffic cameras, road conditions, and traffic flow data from Trafikverket (Swedish Transport Administration).

## Features

- **Real-time weather data** from 850+ Swedish road weather stations
- **Traffic camera access** with live images and geographic search
- **Traffic situations** including accidents, roadwork, and closures
- **Traffic flow data** with vehicle counts and average speeds
- **Road surface conditions** including ice, snow, and water depth
- **Geographic proximity search** for cameras and weather stations
- **County-based filtering** for regional queries

## Available Tools

### Weather Tools

#### `get_weather_station`
Get current weather data for a specific station by name.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `stationName` | string | Yes | Station name (e.g., "Kiruna", "Stockholm") |

Returns: Air/road temperatures, humidity, visibility, wind, precipitation, road conditions.

#### `list_weather_stations`
List available weather stations with optional filtering.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `namePattern` | string | No | - | Substring filter (case-insensitive) |
| `limit` | number | No | 100 | Maximum stations to return (1-1000) |

#### `get_weather_stations_near_location`
Find weather stations near geographic coordinates.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `latitude` | number | Yes | - | WGS84 latitude (-90 to 90) |
| `longitude` | number | Yes | - | WGS84 longitude (-180 to 180) |
| `radiusKm` | number | No | 30 | Search radius in kilometers |
| `limit` | number | No | 50 | Maximum stations to return |

#### `get_weather_observations`
Get historical weather observations for trend analysis.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `measurepointId` | number | Yes | - | Measurement point ID |
| `limit` | number | No | 10 | Maximum observations (1-100) |

### Camera Tools

#### `get_cameras`
Get traffic cameras with optional filtering.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `namePattern` | string | No | - | Substring filter (e.g., "E4") |
| `county` | number | No | - | Swedish county code (1-25) |
| `limit` | number | No | 10 | Maximum cameras (1-100) |

Returns: Camera locations, GPS coordinates, bearings, photo URLs.

#### `get_cameras_near_location`
Find cameras near geographic coordinates.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `latitude` | number | Yes | - | WGS84 latitude |
| `longitude` | number | Yes | - | WGS84 longitude |
| `radiusKm` | number | No | 30 | Search radius in kilometers |
| `county` | number | No | - | County filter for efficiency |
| `limit` | number | No | 50 | Maximum cameras (1-1000) |

#### `get_camera_image`
Fetch the actual image from a traffic camera.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `photoUrl` | string | Yes | Photo URL from `get_cameras` |

Returns: Base64-encoded camera image.

### Traffic Tools

#### `get_traffic_situations`
Get current traffic incidents, accidents, roadwork, and closures.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `roadNumber` | string | No | - | Road filter (e.g., "E4", "väg 862") |
| `county` | number | No | - | County code (1-25) |
| `limit` | number | No | 50 | Maximum situations |

Supports SQL-style wildcards: `E%` matches E4, E20, etc.

#### `get_traffic_flow`
Get real-time traffic density and speed data.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `county` | number | No | - | County code (1-25) |
| `region` | number | No | - | Trafikverket region (1-6) |
| `dataQuality` | string | No | - | Filter: "good", "degraded", "bad" |
| `limit` | number | No | 50 | Maximum measurements |

#### `get_road_conditions`
Get road surface conditions including ice, snow, and water.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `roadNumber` | string | No | - | Road filter (e.g., "E4") |
| `limit` | number | No | 50 | Maximum conditions |

## Swedish County Reference

| Code | County | Code | County |
|------|--------|------|--------|
| 1 | Stockholm | 14 | Västra Götaland |
| 3 | Uppsala | 17 | Värmland |
| 4 | Södermanland | 18 | Örebro |
| 5 | Östergötland | 19 | Västmanland |
| 6 | Jönköping | 20 | Dalarna |
| 7 | Kronoberg | 21 | Gävleborg |
| 8 | Kalmar | 22 | Västernorrland |
| 9 | Gotland | 23 | Jämtland |
| 10 | Blekinge | 24 | Västerbotten |
| 12 | Skåne | 25 | Norrbotten |
| 13 | Halland | | |

## Installation

### Prerequisites

- Node.js 18+
- Trafikverket API key (free from [api.trafikinfo.trafikverket.se](https://api.trafikinfo.trafikverket.se/))

### Setup

```bash
# Clone the repository
git clone https://github.com/hniska/trafikverket-mcp.git
cd trafikverket-mcp

# Install dependencies
npm install

# Build
npm run build
```

## Configuration

### Claude Desktop / Claude Code

Add to your MCP configuration (use **absolute paths**):

**Production** (compiled JavaScript):
```json
{
  "mcpServers": {
    "trafikverket": {
      "command": "node",
      "args": ["/path/to/trafikverket-mcp/dist/index.js"],
      "env": {
        "TRAFIKVERKET_API_KEY": "YOUR_API_KEY"
      }
    }
  }
}
```

**Development** (TypeScript):
```json
{
  "mcpServers": {
    "trafikverket": {
      "command": "npx",
      "args": ["tsx", "/path/to/trafikverket-mcp/src/index.ts"],
      "env": {
        "TRAFIKVERKET_API_KEY": "YOUR_API_KEY"
      }
    }
  }
}
```

Restart Claude after updating configuration.

## Usage Examples

```
# Weather queries
"What's the current weather at Kiruna?"
"List weather stations near Stockholm"
"Find weather stations within 50km of Gothenburg"

# Camera queries
"Show traffic cameras on E4"
"Get cameras near Skellefteå"
"Fetch the image from camera X"

# Traffic queries
"Any traffic incidents on E4?"
"Check road conditions in Norrbotten"
"What's the traffic flow like in Stockholm county?"
```

## Development

### Scripts

| Command | Description |
|---------|-------------|
| `npm run dev` | Run with tsx (development) |
| `npm run build` | Compile TypeScript |
| `npm start` | Run compiled server |
| `npm test` | Run unit tests |
| `npm run test:integration` | Run E2E tests against real API |
| `npm run lint` | Lint code |
| `npm run format` | Format with Prettier |

### Project Structure

```
trafikverket-mcp/
├── src/
│   ├── index.ts                 # Entry point (STDIO transport)
│   ├── server.ts                # MCP server (tool handlers)
│   ├── lib/
│   │   ├── trafikverket-client.ts  # API client with caching
│   │   ├── xml-builder.ts          # XML query construction
│   │   ├── xml-parser.ts           # Response parsing
│   │   └── county-mapping.ts       # County code lookup
│   └── types/
│       └── trafikverket.ts      # TypeScript interfaces
├── design/
│   └── schemas/                 # Official Trafikverket XML schemas
└── dist/                        # Compiled output
```

### Architecture

```
Claude (MCP Client)
    ↓ JSON-RPC over STDIO
MCP Server
    ↓ XML Request
Trafikverket API
    ↓ XML Response
Parser → TypeScript Types
    ↓ Formatted Response
Claude
```

## Error Handling

- **Invalid API key**: Clear message with registration link
- **Network errors**: Timeout (10s) and connection failures
- **API errors**: Trafikverket error messages forwarded
- **Validation errors**: Zod schema validation with details
- **Not found**: Graceful handling for missing stations/cameras

## Resources

- [Trafikverket Open API](https://api.trafikinfo.trafikverket.se/)
- [Model Context Protocol](https://modelcontextprotocol.io/)
- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)

## License

MIT

TDQS

A3.7/5.0

Scored across 10 tools

Disambiguation4/5

Most tools target distinct resources and actions, such as cameras, weather stations, traffic situations, traffic flow, and road conditions. However, get_weather_station, list_weather_stations, get_weather_stations_near_location, and get_weather_observations have some overlap in weather-station-related retrieval, and get_road_conditions partially overlaps with weather station road condition data. Descriptions help clarify, but an agent could still hesitate between current station weather and historical observations.

Naming Consistency4/5

The set is almost entirely consistent snake_case with a get_ prefix (e.g., get_weather_station, get_cameras, get_traffic_flow), which is predictable. The one deviation is list_weather_stations, which uses a different verb but is still conventional and readable. Overall the naming is coherent with a minor stylistic variation.

Tool Count5/5

Ten tools is a well-scoped size for a domain-specific Swedish traffic and weather data server. Each tool covers a distinct data type or access pattern, and there is no evident bloat or missing essential operation within the count itself.

Completeness4/5

The surface covers cameras (list, near-location, image), weather stations (list, specific, near-location, historical observations), traffic situations, traffic flow, and road conditions. This is broad and lifecycle-appropriate for the apparent domain. Minor gaps may exist, such as no direct near-location query for traffic situations, but agents can likely work around that with existing filters.

Maintenance

ActivityInactive
ResponsivenessNo issues