Introduces robust HTTP request and tool invocation logging with sensitive data sanitization and configurable file rotation. This improves debuggability and operational oversight. Implements token state persistence to disk, allowing the server to maintain authenticated sessions across restarts. Adds `_with_webhook` variants for alarm registration tools, enabling explicit webhook configuration. Corrects spelling inconsistencies in geographical alarm tools (e.g., 'neighbourhood' to 'neighborhood'). Includes a new build and packaging script.
🌩️ iklim.co MCP Server
Model Context Protocol (MCP) server for the iklim.co Weather API. AI asistanların (Claude, OpenClaw vb.) iklim.co'nun hava durumu, yıldırım, fırtına, yağış ve alarm API'lerine doğal dil ile erişmesini sağlar.
📋 İçindekiler
- 🌐 Genel Bakış
- ⚙️ Gereksinimler
- 🚀 Kurulum
- 🔧 Ortam Değişkenleri
- ▶️ Build ve Çalıştırma
- 🔌 MCP Client Konfigürasyonu
- 🛠️ Araç Kataloğu
- 🏗️ Mimari
- 🔐 Kimlik Doğrulama ve Güvenlik
- 💻 Geliştirici Notları
🌐 Genel Bakış
Bu MCP server, iklim.co REST API'sinin tüm yeteneklerini 57 araç (tool) olarak sunar. Araçlar 9 kategoriye ayrılmıştır:
| Kategori | Araç Sayısı | Kapsam |
|---|---|---|
| ⚡ Lightning | 2 | Yıldırım çarpma verileri |
| 🌪️ Thunderstorm | 3 | Fırtına hücresi takibi |
| 🌧️ Precipitation | 2 | Radar yağış verileri |
| 🌤️ Forecast | 3 | Saatlik / günlük / anlık tahmin |
| 👤 Auth & User | 11 | Kimlik doğrulama, kullanıcı yönetimi |
| 🏢 Account | 8 | Hesap ve abonelik yönetimi |
| 📍 Point Alarms | 6 | Nokta tabanlı uyarı abonelikleri |
| 🗺️ Geo Alarms | 12 | Coğrafi sınır bazlı uyarılar + il/ilçe/mahalle kataloğu |
| 📅 Forecast Alarms | 10 | Eşik bazlı tahmin uyarıları + il/ilçe kataloğu |
| Toplam | 57 |
⚙️ Gereksinimler
- Node.js >= 18 (ES2022 desteği gerekli)
- npm >= 9
- iklim.co API erişim bilgileri (HMAC secret, kullanıcı adı ve şifre)
🚀 Kurulum
cd mcp-server
npm install
npm run build
🔧 Ortam Değişkenleri
Server başlamadan önce aşağıdaki değişkenlerin tanımlı olması gerekir. Geliştirme ortamında .env dosyası oluşturabilirsiniz (projenin .gitignore dosyasına ekli):
# .env
IKLIM_ENV=test # prod | test | local (IKLIM_BASE_URL yoksa kullanılır)
IKLIM_BASE_URL= # Opsiyonel. Tanımlıysa IKLIM_ENV'i override eder
IKLIM_HMAC_SECRET=<secret> # Zorunlu. İstek imzalama için HMAC-SHA256 anahtarı
IKLIM_USERNAME=<email> # Zorunlu. API kullanıcı e-postası
IKLIM_PASSWORD=<password> # Zorunlu. API kullanıcı şifresi
IKLIM_TOKEN_STORE_PATH=/home/murat/iklim-mcp-server/token-state.bin # Opsiyonel. Access/refresh token binary dosyası
IKLIM_HTTP_LOG_PATH= # Opsiyonel. API istek log dosyası (örn: /var/log/iklim-mcp/http.log)
IKLIM_HTTP_LOG_MAX_BYTES=5242880 # Opsiyonel. Rotate eşiği (byte), default: 5MB
IKLIM_HTTP_LOG_MAX_FILES=5 # Opsiyonel. Tutulacak rotated dosya sayısı (0 = geçmiş dosya tutma)
IKLIM_HTTP_LOG_REQUEST_BODY_MAX_BYTES=16384 # Opsiyonel. Request body log limiti (byte)
IKLIM_HTTP_LOG_RESPONSE_BODY_MAX_BYTES=16384 # Opsiyonel. Response body log limiti (byte)
🌍 Ortama göre base URL:
IKLIM_ENV |
URL |
|---|---|
prod |
https://api.iklim.co |
test |
https://api-test.iklim.co |
local |
http://localhost:8080 |
📝 API istek logları (rotate):
IKLIM_HTTP_LOG_PATHtanımlıysa MCP server yaptığı tüm API çağrıları için tek satır JSON log yazar.- Her satırda istek header'ları da (
requestHeaders) bulunur; hassas alanlar maskelenir (Authorization,X-Signature,X-Idempotency-Key,X-Nonce). - Request body (
requestBody) loglanır; JSON ise hassas alanlar maskelenir (örn.password,token) ve değerIKLIM_HTTP_LOG_REQUEST_BODY_MAX_BYTESsınırında kırpılır. - Response header'ları (
responseHeaders) loglanır; hassas alanlar maskelenir (Set-Cookie/Cookiedahil). - Response body (
responseBody) loglanır; JSON ise hassas alanlar maskelenir (password,secret,tokenvb.) ve değerIKLIM_HTTP_LOG_RESPONSE_BODY_MAX_BYTESsınırında kırpılır. - Log dosyası
IKLIM_HTTP_LOG_MAX_BYTESdeğerini aşınca rotate olur:http.log→http.log.1- eski
http.log.1→http.log.2...http.log.<N>
IKLIM_HTTP_LOG_MAX_FILESkadar geçmiş dosya tutulur.
▶️ Build ve Çalıştırma
# TypeScript'i derle (dist/ klasörünü oluşturur)
npm run build
# Derlenmiş server'ı başlat
npm start
# Geliştirme modunda çalıştır (derleme gerekmez, ts-node kullanır)
npm run dev
Başarılı başlatmada çıktı:
iklim.co MCP server running
Server stdio transportu üzerinden iletişim kurar — doğrudan terminal ile çalıştırmak yerine bir MCP istemcisi tarafından yönetilmesi beklenir.
🔌 MCP Client Konfigürasyonu
Claude CLI (.mcp.json)
Projenin kök dizinindeki .mcp.json dosyası Claude CLI tarafından otomatik olarak yüklenir:
{
"mcpServers": {
"iklim": {
"command": "node",
"args": ["/tam/yol/mcp-server/dist/index.js"],
"env": {
"IKLIM_ENV": "test",
"IKLIM_HMAC_SECRET": "<secret>",
"IKLIM_USERNAME": "<email>",
"IKLIM_PASSWORD": "<password>"
}
}
}
}
Global olarak tanımlamak için ~/.claude/settings.json içine aynı mcpServers bloğunu ekleyin.
OpenClaw
openclaw mcp set komutu env parametresini desteklemez. Tüm alanlar tek satır JSON olarak geçirilmeli, env de dahil:
openclaw mcp set iklim '{"type":"stdio","command":"node","args":["/tam/yol/mcp-server/dist/index.js"],"env":{"IKLIM_ENV":"test","IKLIM_HMAC_SECRET":"<secret>","IKLIM_USERNAME":"<email>","IKLIM_PASSWORD":"<password>"}}'
Veya ~/.openclaw/openclaw.json içinde mcp bölümüne doğrudan ekleyin (okunabilir format):
{
"mcp": {
"iklim": {
"type": "stdio",
"command": "node",
"args": ["/tam/yol/mcp-server/dist/index.js"],
"env": {
"IKLIM_ENV": "test",
"IKLIM_HMAC_SECRET": "<secret>",
"IKLIM_USERNAME": "<email>",
"IKLIM_PASSWORD": "<password>"
}
}
}
}
Diğer MCP İstemcileri
MCP stdio standardını destekleyen her istemci kullanılabilir. Gerekli bilgiler:
- transport:
stdio - command:
node - args:
["<dist/index.js tam yolu>"] - env: Yukarıdaki dört değişken
🛠️ Araç Kataloğu
⚡ Yıldırım / Lightning
get_lightnings_within
Belirli bir merkez noktası ve yarıçap içindeki yıldırım çarpmalarını sorgular.
| Parametre | Tip | Açıklama |
|---|---|---|
latitude |
number | Merkez enlem (-90 / 90) |
longitude |
number | Merkez boylam (-180 / 180) |
radius |
number | Yarıçap, metre (0 – 50.000) |
backwardInterval |
number | Geriye dönük süre, saniye (60 – 2.592.000 / 30 gün) |
endTimeEpoch |
number | Sorgu bitiş zamanı, epoch ms |
pageNumber |
number? | Sayfa numarası (default: 0) |
pageSize |
number? | Sayfa boyutu, max 100 (default: 10) |
get_lightnings_page
Zaman aralığına göre yıldırım verilerini sayfalı olarak getirir.
| Parametre | Tip | Açıklama |
|---|---|---|
backwardInterval |
number | Geriye dönük süre, saniye (60 – 432.000 / 5 gün) |
endTimeEpoch |
number | Sorgu bitiş zamanı, epoch ms |
pageNumber |
number? | Sayfa numarası |
pageSize |
number? | Sayfa boyutu, max 100 |
🌪️ Fırtına / Thunderstorm
get_thunderstorms_within
Yarıçap içindeki fırtına hücrelerini sorgular.
| Parametre | Tip | Açıklama |
|---|---|---|
latitude |
number | Merkez enlem |
longitude |
number | Merkez boylam |
radius |
number | Yarıçap, metre (0 – 50.000) |
backwardInterval |
number | Geriye dönük süre, saniye (60 – 2.592.000) |
endTimeEpoch |
number | Bitiş zamanı, epoch ms |
intersectsWith |
string? | THREAT_POLYGON veya CELL_POLYGON |
pageNumber |
number? | |
pageSize |
number? |
get_thunderstorms_page
Zaman aralığına göre fırtına verilerini sayfalı getirir.
| Parametre | Tip | Açıklama |
|---|---|---|
backwardInterval |
number | Geriye dönük süre, saniye (60 – 432.000) |
endTimeEpoch |
number | Bitiş zamanı, epoch ms |
pageNumber |
number? | |
pageSize |
number? |
get_thunderstorm_details
Belirli bir fırtına olayının geçmiş detaylarını getirir.
| Parametre | Tip | Açıklama |
|---|---|---|
eventId |
string | Örn: EVT20240413001 |
pageNumber |
number? | |
pageSize |
number? |
🌧️ Yağış / Precipitation
get_precipitations_within
Dairesel alan içindeki radar yağış verilerini sorgular.
| Parametre | Tip | Açıklama |
|---|---|---|
latitude |
number | Merkez enlem |
longitude |
number | Merkez boylam |
radius |
number | Yarıçap, metre (0 – 50.000) |
backwardInterval |
number | Geriye dönük süre, saniye (60 – 2.592.000) |
endTimeEpoch |
number | Bitiş zamanı, epoch ms |
intensityThreshold |
string? | Min. yoğunluk: DRIZZLE < LIGHT < MODERATE < HEAVY < VERY_HEAVY < EXTREME |
pageNumber |
number? | |
pageSize |
number? |
get_precipitations_page
Zaman aralığına göre yağış verilerini sayfalı getirir. intensityThreshold zorunludur.
🌤️ Hava Tahmini / Forecast
get_hourly_forecast
Saatlik hava durumu tahminlerini getirir (1–14 gün).
| Parametre | Tip | Açıklama |
|---|---|---|
latitude |
number | Enlem |
longitude |
number | Boylam |
forecastDays |
number? | 1–14, default 7 |
metrics |
string[]? | İstenilen metrik listesi (bkz. aşağısı) |
startTime |
string? | ISO 8601 başlangıç zamanı |
solarPanelTiltForRadiation |
number? | Panel eğim açısı (radyasyon metriği için) |
solarPanelAzimuthForRadiation |
number? | Panel azimut açısı |
📊 Desteklenen metrikler (53 adet)
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
get_daily_forecast
Günlük agregat tahminleri getirir. Parametreler get_hourly_forecast ile aynıdır (solarPanel* parametreleri hariç).
get_current_weather
Konum için anlık (en güncel) hava verilerini getirir.
| Parametre | Tip | Açıklama |
|---|---|---|
latitude |
number | Enlem |
longitude |
number | Boylam |
metrics |
string[]? | Yukarıdaki metrik listesinden seçim |
👤 Auth & Kullanıcı
auth_register
Yeni kullanıcı kaydı oluşturur.
| Parametre | Tip |
|---|---|
username |
string (e-posta) |
password |
string |
firstName |
string |
lastName |
string |
midName |
string? |
locale |
string? |
timezone |
string? |
auth_logout
Geçerli JWT token'ı geçersiz kılar.
user_get_me
Oturum açmış kullanıcının profilini getirir.
user_get
userId ile kullanıcı detayını getirir.
user_create
(Admin) Yeni kullanıcı oluşturur. roles ve status zorunludur.
user_update
(Admin) userId ile kullanıcı alanlarını günceller.
user_list
Kullanıcı listesini sayfalı getirir. roles, status, pageNumber, pageSize ile filtrelenir.
user_unblock
Bloke edilmiş kullanıcıyı açar.
user_change_password
oldPassword ve newPassword ile şifre değiştirir.
user_password_reset_request
Şifre sıfırlama e-postası gönderir. userName ve passwordResetPageLink gerekir.
user_password_reset
Sıfırlama token'ı ile şifre günceller. userId, token, newPassword, loginPageLink gerekir.
🏢 Hesap / Account
account_get
userId ile hesap detaylarını getirir.
account_create
Yeni hesap oluşturur.
| Parametre | Tip | Değerler |
|---|---|---|
type |
string | INDIVIDUAL | ORGANIZATION |
subscriptionPlan |
string | NONE | TRIAL | BASIC_MONTHLY | BASIC_YEARLY | PREMIUM_MONTHLY | PREMIUM_YEARLY | CUSTOM |
mobilePhoneNumber |
string? | |
location |
string? | |
company |
string? | |
industry |
string? | |
profilePictureUrl |
string? |
account_update
accountId ile hesap alanlarını günceller.
account_activation_request
Aktivasyon e-postası gönderir.
account_activate
E-posta doğrulama token'ı ile hesabı aktive eder.
account_phone_activation_request
SMS doğrulama kodu gönderir.
account_activate_phone
SMS token'ı ile telefonu doğrular.
account_update_subscription
Abonelik planını değiştirir.
📍 Nokta Alarmları / Point Alarms
Belirli bir GPS koordinatı ve yarıçap etrafındaki olaylar için uyarı abonelikleri.
point_alarm_register
Yeni nokta alarmı oluşturur.
| Parametre | Tip | Açıklama |
|---|---|---|
recipientId |
string | Uyarı alıcısı ID |
latitude |
number | Merkez enlem |
longitude |
number | Merkez boylam |
radius |
number | Yarıçap, metre (0 – 50.000) |
lightningFilter |
object? | Yıldırım filtresi |
thunderstormFilter |
object? | Fırtına filtresi |
precipitationFilter |
object? | Yağış filtresi |
webhook |
object? | Webhook konfigürasyonu |
point_alarm_update
Mevcut kaydı günceller.
point_alarm_delete
Alarm kaydını siler.
point_alarm_get_by_id
Tekil alarm detayını getirir.
point_alarm_get_by_recipient
Alıcıya ait tüm alarmları listeler.
point_alarm_list
Sayfalı alarm listesi. recipientIds ile filtreleme yapılabilir.
🗺️ Coğrafi Alarmlar / Geo Alarms
İdari sınır, poligon veya H3 adresi bazlı uyarı abonelikleri.
geo_alarm_register
Yeni coğrafi alarm oluşturur. Üç sınır tipi desteklenir:
// İdari sınır
{ "type": "ADMINISTRATIVE", "cityId": 6, "districtId": 60 }
// Poligon
{ "type": "POLYGON", "polygon": { "exterior": [{"lat": 39.9, "lng": 32.8}, ...] } }
// H3 hücre indeksi
{ "type": "H3INDEX", "h3Address": "8f2830828052d25" }
geo_alarm_update / geo_alarm_delete / geo_alarm_get_by_id / geo_alarm_get_by_recipient / geo_alarm_list
Nokta alarmlarıyla aynı imza.
🏙️ Konum Kataloğu
| Araç | Açıklama |
|---|---|
geo_alarm_list_cities |
Tüm illeri listeler |
geo_alarm_get_city |
cityId ile il detayı |
geo_alarm_list_districts |
cityId ile ilçeleri listeler |
geo_alarm_get_district |
districtId ile ilçe detayı |
geo_alarm_list_neighborhoods |
districtId ile mahalleleri listeler |
geo_alarm_get_neighborhood |
neighborhoodId ile mahalle detayı |
📅 Tahmin Alarmları / Forecast Alarms
Eşik aşıldığında sabah (04:00 UTC) veya akşam (16:00 UTC) uyarı gönderir.
forecast_alarm_register
Yeni tahmin alarmı oluşturur.
Sınır tipleri:
{ "type": "ADMINISTRATIVE", "cityId": 6, "districtId": 60 }
{ "type": "POINT", "latitude": 39.92, "longitude": 32.85 }
⚠️ Eşik parametreleri:
| Parametre | Değerler |
|---|---|
precipitationThreshold |
mm cinsinden sayısal değer |
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 |
📬 Teslimat:
| Parametre | Açıklama |
|---|---|
forecastDays |
1–7, kaç günlük tahmin |
forecastAlarmDelivery |
MORNING (04:00 UTC) | EVENING (16:00 UTC) |
forecast_alarm_update / forecast_alarm_delete / forecast_alarm_get_by_id / forecast_alarm_get_by_recipient / forecast_alarm_list
Nokta alarmlarıyla aynı imza.
🏙️ Konum Kataloğu
| Araç | Açıklama |
|---|---|
forecast_alarm_list_cities |
Tüm illeri listeler |
forecast_alarm_get_city |
cityId ile il detayı |
forecast_alarm_list_districts |
cityId ile ilçeleri listeler |
forecast_alarm_get_district |
districtId ile ilçe detayı |
🏗️ Mimari
src/
├── index.ts # MCP server başlatma, tool routing
├── config.ts # Ortam değişkenleri
├── auth.ts # JWT token yönetimi (otomatik yenileme)
├── client.ts # HTTP API istemcisi (HMAC imzalama)
├── 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
İstek akışı:
MCP İstemci
│
▼
index.ts (CallToolRequestSchema)
│
▼
tools/<kategori>.ts ← Zod validasyonu
│
▼
client.ts (apiGet / apiPost / apiPatch / apiDelete)
│ ├── auth.ts → geçerli JWT token al (gerekirse otomatik yenile)
│ └── security.ts → HMAC-SHA256 imzası üret
│
▼
iklim.co REST API
🔐 Kimlik Doğrulama ve Güvenlik
API ile iletişim iki katmanlı güvenlik mekanizması üzerine kuruludur: JWT tabanlı kimlik doğrulama ve HMAC-SHA256 istek imzalama. Her ikisi de her istekte birlikte kullanılır.
Dahili Auth Akışı
Server ilk araç çağrısında otomatik olarak login olur; bu işlem dışarıdan tetiklenmez, tamamen içseldir.
İlk araç çağrısı
│
▼
getValidAccessToken() ← auth.ts
│
├─ tokenState yok → login()
│ POST /v1/auth/login
│ { username, password }
│ ← { accessToken, refreshToken }
│ JWT payload decode → expiry hesapla
│ tokenState'e kaydet
│
├─ accessToken süresi dolmak üzere (< 30 sn kaldı) → refresh()
│ POST /v1/auth/refresh
│ { refreshToken }
│ ← { accessToken, refreshToken }
│ tokenState güncelle
│
└─ accessToken geçerli → doğrudan döndür
⚠️ Önemli:
loginverefreshendpoint'leriAuthorization: Bearerheader'ı içermez — bu istekler yalnızca HMAC imzasıyla doğrulanır (bkz. aşağısı).
JWT Token Yaşam Döngüsü
Token state bellekte (tokenState) tutulur ve her araç çağrısından önce kontrol edilir:
tokenState = {
accessToken: string // API isteklerinde kullanılan JWT
refreshToken: string // accessToken yenileme için
accessTokenExpiresAt: number // epoch ms (JWT payload'dan decode edilir)
refreshTokenExpiresAt: number // epoch ms
}
Karar ağacı (EXPIRY_BUFFER_MS = 30.000 ms):
now < accessTokenExpiresAt - 30s → mevcut token'ı kullan
now < refreshTokenExpiresAt - 30s → refresh token ile yenile
aksi hâlde → yeniden login ol
30 saniyelik tampon, istek transit süresinde token'ın geçersiz kalması riskini ortadan kaldırır.
HTTP İstek Header'ları
Her API isteğine (login ve refresh dahil) aşağıdaki header'lar eklenir:
| Header | Değer | Açıklama |
|---|---|---|
Content-Type |
application/json |
Sabit |
Authorization |
Bearer <accessToken> |
Yalnızca normal API isteklerinde; login/refresh'te yoktur |
X-Signature |
hex string | HMAC-SHA256 imzası (bkz. aşağısı) |
X-Timestamp |
Date.now() string |
Unix epoch, milisaniye |
X-Nonce |
UUID v4 | Her istekte tekil, replay saldırısı önleme |
X-Idempotency-Key |
UUID v4 | POST, PUT, PATCH ve DELETE isteklerinde |
HMAC-SHA256 İmza Hesabı
X-Signature değeri şu dört bileşenin | ile birleştirilmesinden elde edilen string'in HMAC-SHA256'sıdır:
imzalanacak_veri = "METHOD|PATH_WITH_QUERY|TIMESTAMP|BODY"
X-Signature = HMAC-SHA256(imzalanacak_veri, IKLIM_HMAC_SECRET) → hex
Bileşenler:
| Bileşen | Açıklama | Örnek |
|---|---|---|
METHOD |
HTTP metodu, büyük harf | POST |
PATH_WITH_QUERY |
Sorgu parametreleri dahil path | /v1/lightnings/within veya /v1/users?page=0 |
TIMESTAMP |
X-Timestamp ile aynı değer |
1774349677000 |
BODY |
JSON body string; body yoksa boş string "" |
{"username":"..."} |
Örnek hesaplama (GET isteği):
METHOD = "GET"
PATH = "/v1/users?pageNumber=0&pageSize=10"
TIMESTAMP = "1774349677000"
BODY = "" ← GET isteğinde body yok
imzalanacak = "GET|/v1/users?pageNumber=0&pageSize=10|1774349677000|"
X-Signature = HMAC-SHA256(imzalanacak, secret) → "a3f9c2..."
Örnek hesaplama (POST isteği):
METHOD = "POST"
PATH = "/v1/lightnings/within"
TIMESTAMP = "1774349677000"
BODY = '{"center":{"lat":39.87,"lng":32.74},"radius":50000,...}'
imzalanacak = "POST|/v1/lightnings/within|1774349677000|{\"center\":...}"
X-Signature = HMAC-SHA256(imzalanacak, secret) → "7be41d..."
Kaynak:
src/security.ts—buildSignature()fonksiyonu
Auth ile Normal İstekler Arasındaki Fark
POST /v1/auth/login |
POST /v1/auth/refresh |
Normal API İstekleri | |
|---|---|---|---|
Authorization |
❌ | ❌ | ✅ Bearer <token> |
X-Signature |
✅ | ✅ | ✅ |
X-Timestamp |
✅ | ✅ | ✅ |
X-Nonce |
✅ | ✅ | ✅ |
X-Idempotency-Key |
✅ | ✅ | ✅ (POST/PUT/PATCH/DELETE) |
Güvenlik Önerileri
- 🔒
IKLIM_HMAC_SECRETveIKLIM_PASSWORDdeğerlerini kaynak koda veya git geçmişine eklemeyin - 🏭 Üretim ortamında
.envdosyası yerine sistem ortam değişkenlerini veya secret manager kullanın - 🌍 Her ortam (prod/test/local) için ayrı kimlik bilgileri kullanın
- 🔄 HMAC secret'ı düzenli olarak rotate edin
💻 Geliştirici Notları
➕ Yeni araç eklemek
src/tools/altında ilgili dosyaya yeni tool tanımı ve handler eklesrc/index.tsiçindetoolHandlerMap'e veallToolsdizisine kaydetnpm run buildile derle
✅ Zod şemaları
Tüm araç girdileri Zod ile çalışma zamanında doğrulanır. Her araç schema.parse(args) çağrısından geçer; geçersiz girdi anlamlı bir hata mesajıyla geri döner.
🔧 TypeScript derleme hedefi
tsconfig.json → target: ES2022, module: Node16
📦 Bağımlılıklar
| Paket | Versiyon | Kullanım |
|---|---|---|
@modelcontextprotocol/sdk |
^1.0.0 | MCP altyapısı |
zod |
^3.23.8 | Girdi validasyonu |
typescript |
^5.5.0 | Derleme |
ts-node |
^10.9.2 | Geliştirme modu |