TypeScript Implementation¶
The TypeScript implementation of kma-mcp provides a type-safe MCP (Model Context Protocol) server for accessing the Korea Meteorological Administration (KMA) API Hub.
All API implementations are based on the official KMA API Hub specifications. This ensures full compatibility with the official KMA weather services and provides access to the same comprehensive meteorological data available through the KMA API Hub portal at https://apihub.kma.go.kr/api.
Features¶
- Type-Safe API Clients: Full TypeScript support with strict typing
- 21 API Clients: Complete coverage of all KMA API categories
- Date Flexibility: Support for both
Dateobjects and string-formatted dates - Error Handling: Comprehensive error handling with custom
KMAAPIErrorclass - MCP Integration: Built with
@modelcontextprotocol/sdk - Testing: Comprehensive test suite with 53+ tests
Installation¶
Quick Start¶
First, obtain an API key from the KMA API Hub: 1. Visit https://apihub.kma.go.kr/ 2. Create an account and navigate to "마이페이지" (My Page) 3. Generate an API key for the weather services
import { ASOSClient } from '@appleparan/kma-mcp-server';
const client = new ASOSClient({
authKey: 'YOUR_KMA_API_KEY' // API key from KMA API Hub
});
// Get hourly observation data
const data = await client.getHourlyData('202501011200', 108);
console.log(data);
API Categories¶
Surface Observations¶
- ASOS: Automated Synoptic Observing System (지상 관측)
- AWS: Automatic Weather Station (방재 기상 관측)
- AWS OA: Objective Analysis (방재 기상 관측 객관분석)
- Dust: PM10 Observations (황사/연무)
- UV: UV Index (자외선지수)
- Snow: Snow Depth (적설)
- Climate: Climate Normals (기후평년값)
- NK: North Korea Observations (북한 지상관측)
- Season: Phenological Observations (계절관측)
- Station: Station Information (관측지점정보)
Aviation & Marine¶
- AMOS: Aviation Meteorology (항공 기상 관측)
- Buoy: Buoy Observations (해양 부이 관측)
Disaster Monitoring¶
- Earthquake: Seismic Observations (지진 관측)
- Typhoon: Tropical Cyclone Data (태풍 정보)
Forecasts & Warnings¶
- Forecast: Weather Forecasts (예보)
- Warning: Weather Warnings (특보)
Remote Sensing¶
- Radar: Radar Imagery (레이더 영상)
- Satellite: Satellite Imagery (위성 영상)
- Integrated: Lightning & Wind Profiler (낙뢰, 윈드프로파일러)
Upper Air¶
- Radiosonde: Upper Air Soundings (고층 기상 관측)
Global Data¶
- GTS: Global Telecommunication System (전지구 기상통신망)
Architecture¶
All API clients extend the BaseKMAClient abstract class, which provides:
- HTTP client configuration with axios
- Request/response handling
- Error management
- Date formatting utilities
export abstract class BaseKMAClient {
protected client: AxiosInstance;
protected authKey: string;
protected async makeRequest<T>(
endpoint: string,
params: Record<string, unknown>
): Promise<T[]>;
protected formatDateTime(date: Date, includeTime?: boolean): string;
}
Error Handling¶
The library provides a custom KMAAPIError class for handling API errors:
try {
const data = await client.getHourlyData('202501011200', 108);
} catch (error) {
if (error instanceof KMAAPIError) {
console.error(`API Error [${error.resultCode}]: ${error.message}`);
}
}
API Reference¶
For detailed API documentation, see:
- TypeScript API Reference - Complete TypeScript API documentation
- Python API Reference - Python implementation reference
Development¶
Building¶
Testing¶
Code Quality¶
# Run linter
bun run lint
# Fix linting issues
bun run lint:fix
# Format code
bun run format
# Check formatting
bun run format:check
Common Station IDs¶
| Station ID | Location | Korean Name |
|---|---|---|
| 108 | Seoul | 서울 |
| 112 | Incheon | 인천 |
| 133 | Daejeon | 대전 |
| 143 | Daegu | 대구 |
| 156 | Gwangju | 광주 |
| 159 | Busan | 부산 |
| 184 | Jeju | 제주 |
| 0 | All stations | 모든 지점 |
Detailed Examples¶
Surface Observations¶
ASOS (Automated Synoptic Observing System)¶
import { ASOSClient } from '@appleparan/kma-mcp-server';
const client = new ASOSClient({
authKey: process.env.KMA_API_KEY!
});
// Get hourly data with string format
const hourly = await client.getHourlyData('202501011200', 108);
console.log(`Temperature: ${hourly[0].ta}°C`);
// Get hourly data with Date object
const date = new Date('2025-01-01T12:00:00');
const data = await client.getHourlyData(date, 108);
// Get hourly period data (up to 31 days)
const period = await client.getHourlyPeriod(
'202501010000',
'202501312300',
108 // Seoul station
);
console.log(`Retrieved ${period.length} hourly records`);
// Get daily data
const daily = await client.getDailyData('20250101', 108);
// Get daily period data
const dailyPeriod = await client.getDailyPeriod(
'20250101',
'20250131',
108
);
// Get specific element data (e.g., temperature only)
const temperature = await client.getElementData(
'202501010000',
'202501012300',
'TA', // Temperature element code
108
);
AWS (Automatic Weather Station)¶
import { AWSClient } from '@appleparan/kma-mcp-server';
const client = new AWSClient({
authKey: process.env.KMA_API_KEY!
});
// Get minutely data for real-time monitoring
const minutely = await client.getMinutelyData('202501011200', 108);
console.log(`Wind speed: ${minutely[0].ws}m/s`);
// Get minutely period data
const minutelyPeriod = await client.getMinutelyPeriod(
'202501011200',
'202501011300', // 1 hour range
108
);
// Get hourly AWS data
const hourly = await client.getHourlyData('202501011200', 108);
// Get hourly period
const hourlyPeriod = await client.getHourlyPeriod(
'202501010000',
'202501020000',
108
);
// Get daily data
const daily = await client.getDailyData('20250101', 108);
// Get daily period
const dailyPeriod = await client.getDailyPeriod(
'20250101',
'20250131',
108
);
Climate Normals¶
import { ClimateClient } from '@appleparan/kma-mcp-server';
const client = new ClimateClient({
authKey: process.env.KMA_API_KEY!
});
// Get daily normals for a month
const dailyNormals = await client.getDailyNormals(
1, // start month
1, // start day
1, // end month
31, // end day
108 // Seoul
);
// Get ten-day normals
const tenDayNormals = await client.getTenDayNormals(
1, // start month
1, // start ten-day period (1, 2, or 3)
12, // end month
3, // end ten-day period
108
);
// Get monthly normals
const monthlyNormals = await client.getMonthlyNormals(
1, // start month
12, // end month
108
);
// Get annual normals
const annualNormals = await client.getAnnualNormals(108);
Specialized Observations¶
Yellow Dust (PM10) Monitoring¶
import { DustClient } from '@appleparan/kma-mcp-server';
const client = new DustClient({
authKey: process.env.KMA_API_KEY!
});
// Get hourly PM10 data
const hourly = await client.getHourlyPM10Data('202501011200', 108);
console.log(`PM10: ${hourly[0].pm10}μg/m³`);
// Get hourly period
const period = await client.getHourlyPM10Period(
'202501010000',
'202501020000',
108
);
// Get daily average PM10
const daily = await client.getDailyPM10Data('20250101', 108);
// Get daily period
const dailyPeriod = await client.getDailyPM10Period(
'20250101',
'20250131',
108
);
UV Index¶
import { UVClient } from '@appleparan/kma-mcp-server';
const client = new UVClient({
authKey: process.env.KMA_API_KEY!
});
// Get hourly UV index
const hourly = await client.getHourlyUVIndex('202501011200', 108);
console.log(`UV Index: ${hourly[0].uv}`);
// Get hourly period
const period = await client.getHourlyUVPeriod(
'202501010000',
'202501020000',
108
);
// Get daily average UV index
const daily = await client.getDailyUVIndex('20250101', 108);
// Get daily period
const dailyPeriod = await client.getDailyUVPeriod(
'20250101',
'20250131',
108
);
Snow Depth¶
import { SnowClient } from '@appleparan/kma-mcp-server';
const client = new SnowClient({
authKey: process.env.KMA_API_KEY!
});
// Get hourly snow depth
const hourly = await client.getHourlySnowDepth('202501011200', 108);
console.log(`Snow depth: ${hourly[0].sndp}cm`);
// Get hourly period
const period = await client.getHourlySnowPeriod(
'202501010000',
'202501020000',
108
);
// Get daily snow depth
const daily = await client.getDailySnowDepth('20250101', 108);
// Get daily period
const dailyPeriod = await client.getDailySnowPeriod(
'20250101',
'20250131',
108
);
Marine and Upper Air¶
Buoy Observations¶
import { BuoyClient } from '@appleparan/kma-mcp-server';
const client = new BuoyClient({
authKey: process.env.KMA_API_KEY!
});
// Get buoy data
const data = await client.getBuoyData('202501011200', 22101); // Buoy ID
// Get buoy period data
const period = await client.getBuoyPeriod(
'202501010000',
'202501020000',
22101
);
// Get comprehensive marine data
const marine = await client.getComprehensiveMarineData(
'202501011200',
22101
);
Radiosonde (Upper Air)¶
import { RadiosondeClient } from '@appleparan/kma-mcp-server';
const client = new RadiosondeClient({
authKey: process.env.KMA_API_KEY!
});
// Get upper air sounding
const sounding = await client.getUpperAirSounding('202501010000', 47138);
// Get stability indices
const indices = await client.getStabilityIndices('202501010000', 47138);
// Get maximum altitude data
const maxAlt = await client.getMaxAltitudeData('202501010000', 47138);
Disaster Monitoring¶
Earthquake Data¶
import { EarthquakeClient } from '@appleparan/kma-mcp-server';
const client = new EarthquakeClient({
authKey: process.env.KMA_API_KEY!
});
// Get recent earthquake (within 30 days)
const recent = await client.getRecentEarthquake();
// Get earthquake list for a period
const list = await client.getEarthquakeList(
'202501010000',
'202501312359'
);
// Filter significant earthquakes
const significant = list.filter(eq => eq.mag >= 3.0);
Typhoon Tracking¶
import { TyphoonClient } from '@appleparan/kma-mcp-server';
const client = new TyphoonClient({
authKey: process.env.KMA_API_KEY!
});
// Get current active typhoons
const current = await client.getCurrentTyphoons('202501');
if (current.length > 0) {
console.log(`Active typhoons: ${current.length}`);
// Get detailed info for first typhoon
const typhoonId = current[0].typ_id;
const details = await client.getTyphoonById('202501', typhoonId);
// Get forecast track
const forecast = await client.getTyphoonForecast('202501', typhoonId);
console.log(`Typhoon ${details[0].typ_nm} forecast positions: ${forecast.length}`);
}
// Get historical typhoon data for a year
const history = await client.getTyphoonHistory(2024);
Forecasts and Warnings¶
Weather Forecasts¶
import { ForecastClient } from '@appleparan/kma-mcp-server';
const client = new ForecastClient({
authKey: process.env.KMA_API_KEY!
});
// Get short-term forecast (up to 3 days)
const shortTerm = await client.getShortTermForecast('11B00000'); // Region code
// Get medium-term forecast (3-10 days)
const mediumTerm = await client.getMediumTermForecast('11B00000');
// Get weekly forecast
const weekly = await client.getWeeklyForecast();
Weather Warnings¶
import { WarningClient } from '@appleparan/kma-mcp-server';
const client = new WarningClient({
authKey: process.env.KMA_API_KEY!
});
// Get current active warnings
const current = await client.getCurrentWarnings();
if (current.length > 0) {
console.log('Active weather warnings:');
current.forEach(warning => {
console.log(`- ${warning.wrn_nm}: ${warning.rgn_nm}`);
});
}
// Get warning history
const history = await client.getWarningHistory(
'202501010000',
'202501312359'
);
// Get special weather reports
const special = await client.getSpecialReport('202501');
Remote Sensing¶
Weather Radar¶
import { RadarClient } from '@appleparan/kma-mcp-server';
const client = new RadarClient({
authKey: process.env.KMA_API_KEY!
});
// Get radar image
const image = await client.getRadarImage('202501011200', 'KWK'); // Radar ID
// Get radar image sequence for animation
const sequence = await client.getRadarImageSequence(
'202501011200',
'202501011300',
'ALL' // All radars
);
// Get reflectivity at specific location
const reflectivity = await client.getRadarReflectivity(
'202501011200',
127.0, // Longitude
37.5 // Latitude
);
Satellite Imagery¶
import { SatelliteClient } from '@appleparan/kma-mcp-server';
const client = new SatelliteClient({
authKey: process.env.KMA_API_KEY!
});
// Get satellite file list
const fileList = await client.getSatelliteFileList(
'202501011200',
'IR1' // Channel
);
// Get satellite imagery
const imagery = await client.getSatelliteImagery(
'202501011200',
'IR1',
'FD' // Full Disk
);
Global and Aviation¶
GTS (Global Telecommunication System)¶
import { GTSClient } from '@appleparan/kma-mcp-server';
const client = new GTSClient({
authKey: process.env.KMA_API_KEY!
});
// Get SYNOP observations
const synop = await client.getSynopObservations('202501011200');
// Get ship observations
const ship = await client.getShipObservations('202501011200');
// Get buoy GTS data
const buoy = await client.getBuoyObservations('202501011200');
// Get aircraft observations
const aircraft = await client.getAircraftObservations('202501011200');
// Get surface analysis chart
const surfaceChart = await client.getSurfaceAnalysisChart('202501011200');
// Get upper air chart
const upperAirChart = await client.getUpperAirChart('202501011200', '500');
Aviation Meteorology¶
import { AMOSClient } from '@appleparan/kma-mcp-server';
const client = new AMOSClient({
authKey: process.env.KMA_API_KEY!
});
// Get airport weather observations
const airport = await client.getAirportObservations('202501011200', 'RKSI'); // Incheon
// Get AMDAR (Aircraft Meteorological Data Relay) data
const amdar = await client.getAMDARData('202501011200');
Integrated Meteorology¶
import { IntegratedClient } from '@appleparan/kma-mcp-server';
const client = new IntegratedClient({
authKey: process.env.KMA_API_KEY!
});
// Get lightning data
const lightning = await client.getLightningData('202501011200');
// Get wind profiler data
const windProfiler = await client.getWindProfilerData('202501011200', 108);
Advanced Usage¶
Date Handling¶
All clients accept both string and Date object formats:
// String format
const data1 = await client.getHourlyData('202501011200', 108);
// Date object
const date = new Date('2025-01-01T12:00:00');
const data2 = await client.getHourlyData(date, 108);
// Current time
const now = new Date();
const data3 = await client.getHourlyData(now, 108);
Error Handling Patterns¶
import { ASOSClient, KMAAPIError } from '@appleparan/kma-mcp-server';
const client = new ASOSClient({
authKey: process.env.KMA_API_KEY!
});
try {
const data = await client.getHourlyData('202501011200', 108);
console.log('Data retrieved successfully');
} catch (error) {
if (error instanceof KMAAPIError) {
console.error(`KMA API Error: ${error.message}`);
console.error(`Result Code: ${error.resultCode}`);
console.error(`Status Code: ${error.statusCode}`);
} else if (error instanceof Error) {
console.error(`Generic Error: ${error.message}`);
}
}
Configuration Options¶
import { ASOSClient } from '@appleparan/kma-mcp-server';
const client = new ASOSClient({
authKey: process.env.KMA_API_KEY!,
baseURL: 'https://apihub.kma.go.kr/api/typ01/url', // Optional
timeout: 30000 // 30 seconds, optional
});
Working with Multiple Stations¶
import { ASOSClient } from '@appleparan/kma-mcp-server';
const client = new ASOSClient({
authKey: process.env.KMA_API_KEY!
});
const stations = [108, 112, 133, 143, 156, 159, 184]; // Major cities
const time = '202501011200';
// Sequential requests
const results = [];
for (const stn of stations) {
const data = await client.getHourlyData(time, stn);
results.push(data[0]);
}
// Or use Promise.all for concurrent requests
const promises = stations.map(stn =>
client.getHourlyData(time, stn)
);
const allData = await Promise.all(promises);
Type Safety¶
TypeScript provides full type information:
import { ASOSClient, type ASOSObservation } from '@appleparan/kma-mcp-server';
const client = new ASOSClient({
authKey: process.env.KMA_API_KEY!
});
// Type is inferred as ASOSObservation[]
const data = await client.getHourlyData('202501011200', 108);
// Access with full autocomplete
const observation: ASOSObservation = data[0];
console.log(`Temperature: ${observation.ta}°C`);
console.log(`Humidity: ${observation.hm}%`);
console.log(`Wind Speed: ${observation.ws}m/s`);
Time Format Reference¶
| Data Type | Format | Example | Description |
|---|---|---|---|
| Hourly | YYYYMMDDHHmm | 202501011200 | Year-Month-Day-Hour-Minute |
| Daily | YYYYMMDD | 20250101 | Year-Month-Day |
| Year-Month | YYYYMM | 202501 | Year-Month |
| Year | YYYY | 2025 | Year |
Performance Considerations¶
Rate Limiting¶
The KMA API Hub has rate limits. Consider:
- Implementing request throttling
- Caching frequently accessed data
- Using period requests instead of multiple single requests
// Good: Single period request
const period = await client.getHourlyPeriod(
'202501010000',
'202501312300',
108
);
// Avoid: Multiple single requests
// Don't do this for large date ranges
for (let day = 1; day <= 31; day++) {
const data = await client.getHourlyData(`202501${day}1200`, 108);
}
Timeout Configuration¶
For slow networks or large data requests:
Contributing¶
Contributions are welcome! Please see the main repository for contribution guidelines.
License¶
MIT