> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.iklim.co/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Server

> Connect AI assistants like Claude to the iklim.co Weather API using the Model Context Protocol (MCP).

<Note>
  This guide is intended for **developers and technically proficient users**. Setting up the MCP server requires Node.js, a terminal, and basic familiarity with configuration files.
</Note>

<CardGroup cols={3}>
  <Card title="57 Tools" icon="wrench">
    Every iklim.co API capability is exposed as an MCP tool — lightning, thunderstorm, precipitation, forecast, alarms, and more.
  </Card>

  <Card title="Auto Auth" icon="key">
    JWT tokens are acquired and refreshed automatically. Just provide your credentials and the server handles the rest.
  </Card>

  <Card title="HMAC-Signed" icon="shield-halved">
    Every request is signed with HMAC-SHA256. Credentials never travel in plain text and replay attacks are blocked with a per-request nonce.
  </Card>
</CardGroup>

## Overview

The iklim.co MCP Server implements the [Model Context Protocol](https://modelcontextprotocol.io) and exposes the full iklim.co REST API as **57 tools** across 9 categories. Any MCP-compatible AI client (Claude, OpenClaw, and others) can query live weather data, manage alarms, and handle user accounts through natural language.

| Category           |  Tools | Scope                                                      |
| ------------------ | :----: | ---------------------------------------------------------- |
| ⚡ Lightning        |    2   | Lightning strike data                                      |
| 🌪️ Thunderstorm   |    3   | Thunderstorm cell tracking                                 |
| 🌧️ Precipitation  |    2   | Radar precipitation data                                   |
| 🌤️ Forecast       |    3   | Hourly / daily / current weather                           |
| 👤 Auth & User     |   11   | Authentication and user management                         |
| 🏢 Account         |    8   | Account and subscription management                        |
| 📍 Point Alarms    |    6   | GPS-based alert subscriptions                              |
| 🗺️ Geo Alarms     |   12   | Boundary-based alerts + city/district/neighborhood catalog |
| 📅 Forecast Alarms |   10   | Threshold-based forecast alerts + city/district catalog    |
| **Total**          | **57** |                                                            |

***

## Requirements

* **Node.js** >= 18 (ES2022 support required)
* **npm** >= 9
* iklim.co API credentials: HMAC secret, username, and password

***

## Installation

The source code is publicly available at [git.tarla.io/iklim.co/mcp-server](https://git.tarla.io/iklim.co/mcp-server).

```bash theme={null}
git clone https://git.tarla.io/iklim.co/mcp-server.git
cd mcp-server
npm install
npm run build
```

***

## Environment Variables

The following variables must be set before the server starts. For local development, create a `.env` file in the `mcp-server` directory (already in `.gitignore`):

```bash theme={null}
# .env
IKLIM_ENV=test                     # prod | test | local  (used when IKLIM_BASE_URL is not set)
IKLIM_BASE_URL=                    # Optional. Overrides IKLIM_ENV when set
IKLIM_HMAC_SECRET=<secret>         # Required. HMAC-SHA256 key for request signing
IKLIM_USERNAME=<email>             # Required. API account e-mail
IKLIM_PASSWORD=<password>          # Required. API account password
IKLIM_TOKEN_STORE_PATH=            # Optional. Path for persisting access/refresh tokens
IKLIM_HTTP_LOG_PATH=               # Optional. API request log file path
IKLIM_HTTP_LOG_MAX_BYTES=5242880   # Optional. Rotate threshold in bytes (default: 5 MB)
IKLIM_HTTP_LOG_MAX_FILES=5         # Optional. Number of rotated files to keep
IKLIM_HTTP_LOG_REQUEST_BODY_MAX_BYTES=16384   # Optional. Request body log size limit
IKLIM_HTTP_LOG_RESPONSE_BODY_MAX_BYTES=16384  # Optional. Response body log size limit
```

**Base URL by environment:**

| `IKLIM_ENV` | URL                         |
| ----------- | --------------------------- |
| `prod`      | `https://api.iklim.co`      |
| `test`      | `https://api-test.iklim.co` |
| `local`     | `http://localhost:8080`     |

<Info>
  When `IKLIM_HTTP_LOG_PATH` is set, every API call is written as a single-line JSON log entry. Sensitive fields (`Authorization`, `X-Signature`, `password`, `token`, etc.) are automatically masked.
</Info>

***

## Build & Run

```bash theme={null}
# Compile TypeScript (outputs to dist/)
npm run build

# Start the compiled server
npm start

# Development mode — no build step required
npm run dev
```

A successful start prints:

```
iklim.co MCP server running
```

<Warning>
  The server communicates over **stdio** transport. It is designed to be managed by an MCP client, not run interactively in a terminal.
</Warning>

***

## MCP Client Configuration

### Claude CLI (`.mcp.json`)

Place a `.mcp.json` file in your project root. Claude CLI picks it up automatically:

```json theme={null}
{
  "mcpServers": {
    "iklim": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-server/dist/index.js"],
      "env": {
        "IKLIM_ENV": "test",
        "IKLIM_HMAC_SECRET": "<secret>",
        "IKLIM_USERNAME": "<email>",
        "IKLIM_PASSWORD": "<password>"
      }
    }
  }
}
```

To register the server globally, add the same `mcpServers` block to `~/.claude/settings.json`.

### OpenClaw

The `openclaw mcp set` command does not support a separate `env` flag — pass everything as a single JSON object:

```bash theme={null}
openclaw mcp set iklim '{"type":"stdio","command":"node","args":["/absolute/path/to/mcp-server/dist/index.js"],"env":{"IKLIM_ENV":"test","IKLIM_HMAC_SECRET":"<secret>","IKLIM_USERNAME":"<email>","IKLIM_PASSWORD":"<password>"}}'
```

Or edit `~/.openclaw/openclaw.json` directly:

```json theme={null}
{
  "mcp": {
    "iklim": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/mcp-server/dist/index.js"],
      "env": {
        "IKLIM_ENV": "test",
        "IKLIM_HMAC_SECRET": "<secret>",
        "IKLIM_USERNAME": "<email>",
        "IKLIM_PASSWORD": "<password>"
      }
    }
  }
}
```

### Other MCP Clients

Any client that supports the MCP stdio standard can connect. Required parameters:

| Parameter   | Value                                  |
| ----------- | -------------------------------------- |
| `transport` | `stdio`                                |
| `command`   | `node`                                 |
| `args`      | `["<absolute path to dist/index.js>"]` |
| `env`       | The four variables above               |

***

## Tool Catalog

### ⚡ Lightning

| Tool                    | Description                                                                               |
| ----------------------- | ----------------------------------------------------------------------------------------- |
| `get_lightnings_within` | Queries lightning strikes within a circular area defined by center coordinates and radius |
| `get_lightnings_page`   | Returns paginated lightning data for a time interval                                      |

### 🌪️ Thunderstorm

| Tool                       | Description                                                        |
| -------------------------- | ------------------------------------------------------------------ |
| `get_thunderstorms_within` | Queries thunderstorm cells within a circular area                  |
| `get_thunderstorms_page`   | Returns paginated thunderstorm data for a time interval            |
| `get_thunderstorm_details` | Fetches historical details for a specific storm event by `eventId` |

### 🌧️ Precipitation

| Tool                        | Description                                                                                        |
| --------------------------- | -------------------------------------------------------------------------------------------------- |
| `get_precipitations_within` | Queries radar precipitation data within a circular area; optionally filter by `intensityThreshold` |
| `get_precipitations_page`   | Returns paginated precipitation data; `intensityThreshold` is required                             |

**Intensity levels (lowest → highest):** `DRIZZLE` \< `LIGHT` \< `MODERATE` \< `HEAVY` \< `VERY_HEAVY` \< `EXTREME`

### 🌤️ Forecast

| Tool                  | Description                                                                         |
| --------------------- | ----------------------------------------------------------------------------------- |
| `get_hourly_forecast` | Hourly forecasts for 1–14 days; supports 53 selectable metrics                      |
| `get_daily_forecast`  | Daily aggregate forecasts; same parameters as hourly (excluding solar panel fields) |
| `get_current_weather` | Most recent weather observation for a coordinate                                    |

<Accordion title="53 supported forecast metrics">
  `WEATHER_ICON`, `TEMPERATURE`, `APPARENT_TEMPERATURE`, `DEW_POINT_TEMPERATURE`, `HUMIDITY`, `CLOUD_COVER`, `CLOUD_COVER_LOW`, `CLOUD_COVER_MID`, `CLOUD_COVER_HIGH`, `WIND_SPEED`, `WIND_GUST`, `WIND_DIRECTION`, `WIND_SPEED_AT_100M`, `WIND_DIRECTION_AT_100M`, `PRECIPITATION`, `RAIN`, `SHOWERS`, `SNOWFALL`, `SNOW_DEPTH`, `PRECIPITATION_PROBABILITY`, `WEATHER_CODE`, `PRESSURE_MSL`, `SURFACE_PRESSURE`, `VISIBILITY`, `EVAPOTRANSPIRATION`, `ET0_FAO_EVAPOTRANSPIRATION`, `VAPOUR_PRESSURE_DEFICIT`, `CAPE`, `LIFTED_INDEX`, `CONVECTIVE_INHIBITION`, `SUNSHINE_DURATION`, `SHORTWAVE_RADIATION`, `DIRECT_RADIATION`, `DIFFUSE_RADIATION`, `DIRECT_NORMAL_IRRADIANCE`, `GLOBAL_TILTED_IRRADIANCE`, `TERRESTRIAL_RADIATION`, `SHORTWAVE_RADIATION_INSTANT`, `DIRECT_RADIATION_INSTANT`, `DIFFUSE_RADIATION_INSTANT`, `DIRECT_NORMAL_IRRADIANCE_INSTANT`, `GLOBAL_TILTED_IRRADIANCE_INSTANT`, `TERRESTRIAL_RADIATION_INSTANT`, `SOIL_TEMPERATURE_0CM`, `SOIL_TEMPERATURE_6CM`, `SOIL_TEMPERATURE_18CM`, `SOIL_TEMPERATURE_54CM`, `SOIL_MOISTURE_0_TO_1CM`, `SOIL_MOISTURE_1_TO_3CM`, `SOIL_MOISTURE_3_TO_9CM`, `SOIL_MOISTURE_9_TO_27CM`, `SOIL_MOISTURE_27_TO_81CM`, `IS_DAY`
</Accordion>

### 👤 Auth & User

| Tool                          | Description                                                    |
| ----------------------------- | -------------------------------------------------------------- |
| `auth_register`               | Creates a new user account                                     |
| `auth_logout`                 | Invalidates the current JWT token                              |
| `user_get_me`                 | Returns the authenticated user's profile                       |
| `user_get`                    | Returns a user's details by `userId`                           |
| `user_create`                 | *(Admin)* Creates a new user with `roles` and `status`         |
| `user_update`                 | *(Admin)* Updates user fields by `userId`                      |
| `user_list`                   | Returns a paginated user list; filterable by `roles`, `status` |
| `user_unblock`                | Unblocks a blocked user                                        |
| `user_change_password`        | Changes password with `oldPassword` and `newPassword`          |
| `user_password_reset_request` | Sends a password reset e-mail                                  |
| `user_password_reset`         | Updates password using a reset token                           |

### 🏢 Account

| Tool                               | Description                                              |
| ---------------------------------- | -------------------------------------------------------- |
| `account_get`                      | Returns account details by `userId`                      |
| `account_create`                   | Creates a new account (`INDIVIDUAL` or `ORGANIZATION`)   |
| `account_update`                   | Updates account fields by `accountId`                    |
| `account_activation_request`       | Sends an activation e-mail                               |
| `account_activate`                 | Activates the account using an e-mail verification token |
| `account_phone_activation_request` | Sends an SMS verification code                           |
| `account_activate_phone`           | Verifies the phone number using an SMS token             |
| `account_update_subscription`      | Changes the subscription plan                            |

### 📍 Point Alarms

GPS-coordinate-based alert subscriptions for events within a configurable radius.

| Tool                           | Description                                        |
| ------------------------------ | -------------------------------------------------- |
| `point_alarm_register`         | Creates a new point alarm                          |
| `point_alarm_update`           | Updates an existing alarm                          |
| `point_alarm_delete`           | Deletes an alarm                                   |
| `point_alarm_get_by_id`        | Returns a single alarm's details                   |
| `point_alarm_get_by_recipient` | Lists all alarms for a recipient                   |
| `point_alarm_list`             | Paginated alarm list; filterable by `recipientIds` |

### 🗺️ Geo Alarms

Administrative boundary, polygon, or H3 address-based alert subscriptions.

Three boundary types are supported:

```json theme={null}
// Administrative boundary
{ "type": "ADMINISTRATIVE", "cityId": 6, "districtId": 60 }

// Polygon
{ "type": "POLYGON", "polygon": { "exterior": [{"lat": 39.9, "lng": 32.8}, ...] } }

// H3 cell index
{ "type": "H3INDEX", "h3Address": "8f2830828052d25" }
```

CRUD tools (`geo_alarm_register`, `geo_alarm_update`, `geo_alarm_delete`, `geo_alarm_get_by_id`, `geo_alarm_get_by_recipient`, `geo_alarm_list`) share the same signature as Point Alarms.

**Location catalog:**

| Tool                           | Description                                      |
| ------------------------------ | ------------------------------------------------ |
| `geo_alarm_list_cities`        | Lists all cities                                 |
| `geo_alarm_get_city`           | Returns city details by `cityId`                 |
| `geo_alarm_list_districts`     | Lists districts by `cityId`                      |
| `geo_alarm_get_district`       | Returns district details by `districtId`         |
| `geo_alarm_list_neighborhoods` | Lists neighborhoods by `districtId`              |
| `geo_alarm_get_neighborhood`   | Returns neighborhood details by `neighborhoodId` |

### 📅 Forecast Alarms

Threshold-based alerts delivered at 04:00 UTC (morning) or 16:00 UTC (evening).

**Threshold parameters:**

| Parameter                  | Values                                                    |
| -------------------------- | --------------------------------------------------------- |
| `precipitationThreshold`   | Numeric value in mm                                       |
| `snowFallThreshold`        | `LIGHT` \| `MODERATE` \| `HEAVY`                          |
| `windGustThreshold`        | `STRONG_WIND` \| `STORM` \| `SEVERE_STORM` \| `HURRICANE` |
| `hotTemperatureThreshold`  | `HOT_SNAP` \| `HEAVY_HOT_SNAP` \| `EXTREME_HOT_SNAP`      |
| `coldTemperatureThreshold` | `COLD_SNAP` \| `HEAVY_COLD_SNAP` \| `EXTREME_COLD_SNAP`   |

CRUD tools follow the same signature as Point Alarms. Additional location catalog tools: `forecast_alarm_list_cities`, `forecast_alarm_get_city`, `forecast_alarm_list_districts`, `forecast_alarm_get_district`.

***

## Architecture

```
src/
├── index.ts          # MCP server bootstrap, tool routing
├── config.ts         # Environment variable parsing
├── auth.ts           # JWT token management (auto-refresh)
├── client.ts         # HTTP API client (HMAC signing)
├── security.ts       # HMAC-SHA256, nonce, idempotency key
└── tools/
    ├── lightnings.ts
    ├── thunderstorms.ts
    ├── precipitations.ts
    ├── forecasts.ts
    ├── auth.ts
    ├── accounts.ts
    ├── point-alarms.ts
    ├── geo-alarms.ts
    └── forecast-alarms.ts
```

**Request flow:**

```
MCP Client
    │
    ▼
index.ts  (CallToolRequestSchema)
    │
    ▼
tools/<category>.ts  ← Zod validation
    │
    ▼
client.ts  (apiGet / apiPost / apiPatch / apiDelete)
    │  ├── auth.ts → get valid JWT (auto-refresh if needed)
    │  └── security.ts → generate HMAC-SHA256 signature
    │
    ▼
iklim.co REST API
```

***

## Authentication & Security

Every API interaction uses two independent security layers: **JWT-based authentication** and **HMAC-SHA256 request signing**. Both are applied to every request.

### Automatic Auth Flow

The server logs in automatically on the first tool call. No manual login step is needed.

```
First tool call
    │
    ▼
getValidAccessToken()          ← auth.ts
    │
    ├─ No token state → login()
    │       POST /v1/auth/login  { username, password }
    │       ← { accessToken, refreshToken }
    │       Decode JWT payload → calculate expiry
    │       Save to tokenState
    │
    ├─ accessToken expiring soon (< 30 s) → refresh()
    │       POST /v1/auth/refresh  { refreshToken }
    │       ← { accessToken, refreshToken }
    │       Update tokenState
    │
    └─ accessToken valid → return directly
```

<Warning>
  The `login` and `refresh` endpoints do **not** include an `Authorization: Bearer` header — they are authenticated by HMAC signature alone.
</Warning>

### HTTP Request Headers

| Header              | Value                  | Notes                                               |
| ------------------- | ---------------------- | --------------------------------------------------- |
| `Content-Type`      | `application/json`     | Fixed                                               |
| `Authorization`     | `Bearer <accessToken>` | Normal API requests only; omitted for login/refresh |
| `X-Signature`       | hex string             | HMAC-SHA256 signature                               |
| `X-Timestamp`       | Unix epoch (ms)        | `Date.now()` as a string                            |
| `X-Nonce`           | UUID v4                | Unique per request — prevents replay attacks        |
| `X-Idempotency-Key` | UUID v4                | `POST`, `PUT`, `PATCH`, and `DELETE` requests       |

### HMAC-SHA256 Signature

The `X-Signature` value is the HMAC-SHA256 of four components joined by `|`:

```
data_to_sign = "METHOD|PATH_WITH_QUERY|TIMESTAMP|BODY"
X-Signature  = HMAC-SHA256(data_to_sign, IKLIM_HMAC_SECRET) → hex
```

**Example — GET request:**

```
METHOD    = "GET"
PATH      = "/v1/users?pageNumber=0&pageSize=10"
TIMESTAMP = "1774349677000"
BODY      = ""   ← empty for GET

data_to_sign = "GET|/v1/users?pageNumber=0&pageSize=10|1774349677000|"
X-Signature  = HMAC-SHA256(data_to_sign, secret) → "a3f9c2..."
```

**Example — POST request:**

```
METHOD    = "POST"
PATH      = "/v1/lightnings/within"
TIMESTAMP = "1774349677000"
BODY      = '{"center":{"lat":39.87,"lng":32.74},"radius":50000,...}'

data_to_sign = "POST|/v1/lightnings/within|1774349677000|{\"center\":...}"
X-Signature  = HMAC-SHA256(data_to_sign, secret) → "7be41d..."
```

### Security Recommendations

* Never commit `IKLIM_HMAC_SECRET` or `IKLIM_PASSWORD` to source control or git history
* In production, use system environment variables or a secrets manager instead of a `.env` file
* Use separate credentials for each environment (prod / test / local)
* Rotate the HMAC secret regularly
