@bashcat/cwa-mcp-weather
Version:
MCP 伺服器整合中央氣象署 (CWA) 開放資料 API - 完整支援所有15個天氣工具
1,586 lines (1,552 loc) • 56.2 kB
JavaScript
#!/usr/bin/env node
import 'dotenv/config';
import { McpServer, } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { CWAAPIClient } from "./cwa-client.js";
import { TAIWAN_COUNTIES, WEATHER_ELEMENTS, CWA_API_ENDPOINTS, COUNTY_API_MAPPING } from "./types.js";
// 從環境變數取得 CWA API 金鑰
const CWA_API_KEY = process.env.CWA_API_KEY;
if (!CWA_API_KEY) {
console.error("錯誤: 請設定環境變數 CWA_API_KEY");
process.exit(1);
}
// 建立 CWA API 客戶端
const cwaClient = new CWAAPIClient(CWA_API_KEY);
// 建立 MCP 伺服器
const server = new McpServer({
name: "cwa-weather-server",
version: "2.0.0",
});
// === 預報類工具 ===
/**
* 工具 1: 取得縣市天氣預報(今明36小時)
*/
server.registerTool("get_county_weather", {
title: "取得縣市天氣預報",
description: "取得台灣特定縣市今明36小時天氣預報。建議一次查詢一個縣市以獲得最佳結果。",
inputSchema: {
locationName: z.array(z.enum(TAIWAN_COUNTIES)).optional()
.describe("要查詢的縣市名稱列表。建議單次查詢1個縣市,如需多個縣市請分別查詢"),
elementName: z.array(z.enum(['Wx', 'PoP', 'CI', 'MinT', 'MaxT'])).optional()
.describe("要查詢的天氣因子:Wx(天氣現象), PoP(降雨機率), CI(舒適度指數), MinT(最低溫度), MaxT(最高溫度)")
}
}, async ({ locationName, elementName }) => {
try {
const data = await cwaClient.getCountyWeather({
locationName,
elementName
});
const formattedData = cwaClient.formatData(data, 'weather');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢縣市天氣預報時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
/**
* 工具 2: 取得鄉鎮天氣預報
*/
server.registerTool("get_township_weather", {
title: "取得鄉鎮天氣預報",
description: "取得台灣特定縣市的鄉鎮天氣預報。建議一次查詢單一縣市以獲得最佳結果。",
inputSchema: {
county: z.enum(Object.keys(COUNTY_API_MAPPING))
.describe("要查詢的縣市"),
period: z.enum(['3days', 'weekly'])
.describe("預報時間範圍:3days(未來3天逐3小時), weekly(未來1週)"),
locationName: z.array(z.string()).optional()
.describe("要查詢的鄉鎮名稱列表。建議指定1-3個鄉鎮,如需多個請分別查詢"),
elementName: z.array(z.string()).optional()
.describe("要查詢的天氣因子名稱列表")
},
}, async ({ county, period, locationName, elementName }) => {
try {
const data = await cwaClient.getTownshipWeather({
county,
period,
locationName,
elementName
});
const formattedData = cwaClient.formatData(data, 'weather');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢鄉鎮天氣預報時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
/**
* 工具 3: 取得潮汐預報
*/
server.registerTool("get_tidal_forecast", {
title: "取得潮汐預報",
description: "取得特定地點和日期的潮汐預報資料。必須指定地點名稱和查詢日期。",
inputSchema: {
locationName: z.array(z.string()).optional()
.describe("要查詢的地點名稱列表"),
date: z.string().optional()
.describe("查詢日期,格式: YYYY-MM-DD")
}
}, async ({ locationName, date }) => {
try {
// 參數驗證
if (!locationName || locationName.length === 0) {
return {
content: [
{
type: "text",
text: `❌ 參數錯誤:缺少地點名稱
🔧 建議調用方式:
{
"tool": "get_tidal_forecast",
"arguments": {
"locationName": ["基隆", "淡水"],
"date": "2025-06-28"
}
}
📍 可用地點包括:
• 海水浴場:頭城、磯崎、墾丁、南灣、小灣、西子灣、福隆、龍洞南口等
• 漁港:八斗子、烏石、新竹、安平、興達、旗津、鼓山等
• 海釣點:基隆港、台北港、台中港、高雄港等各大港口
• 潛點:龍洞灣、杉原海域、後壁湖、萬里桐等
• 衝浪點:中角沙珠灣、福隆、白砂、風吹砂等
請指定至少一個地點名稱。`
}
]
};
}
if (!date) {
return {
content: [
{
type: "text",
text: `❌ 參數錯誤:缺少查詢日期
🔧 建議調用方式:
{
"tool": "get_tidal_forecast",
"arguments": {
"locationName": ["${locationName[0]}"],
"date": "2025-06-28"
}
}
📅 日期格式說明:
• 格式:YYYY-MM-DD
• 範例:2025-06-28(表示2025年6月28日)
• 建議查詢未來7天內的日期以獲得最準確的預報
請提供正確的日期格式。`
}
]
};
}
// 驗證日期格式
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
if (!dateRegex.test(date)) {
return {
content: [
{
type: "text",
text: `❌ 日期格式錯誤:${date}
🔧 建議調用方式:
{
"tool": "get_tidal_forecast",
"arguments": {
"locationName": ["${locationName[0]}"],
"date": "2025-06-28"
}
}
📅 正確的日期格式:
• 格式:YYYY-MM-DD
• 年份:4位數字
• 月份:2位數字(01-12)
• 日期:2位數字(01-31)
• 範例:2025-06-28
請使用正確的日期格式。`
}
]
};
}
// 驗證日期是否有效
const queryDate = new Date(date);
if (isNaN(queryDate.getTime())) {
return {
content: [
{
type: "text",
text: `❌ 無效的日期:${date}
🔧 建議調用方式:
{
"tool": "get_tidal_forecast",
"arguments": {
"locationName": ["${locationName[0]}"],
"date": "${new Date().toISOString().split('T')[0]}"
}
}
請檢查日期是否為有效日期。`
}
]
};
}
// 設定時間範圍為指定日期的整天
const timeFrom = `${date}T00:00:00`;
const nextDate = new Date(queryDate);
nextDate.setDate(nextDate.getDate() + 1);
const timeTo = nextDate.toISOString().split('T')[0] + 'T00:00:00';
const data = await cwaClient.getTidalForecast({
locationName,
timeFrom,
timeTo
});
const formattedData = cwaClient.formatData(data, 'tidal');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : '未知錯誤';
return {
content: [
{
type: "text",
text: `❌ 查詢潮汐預報時發生錯誤: ${errorMessage}
🔧 建議調用方式:
{
"tool": "get_tidal_forecast",
"arguments": {
"locationName": ["基隆", "淡水"],
"date": "${new Date().toISOString().split('T')[0]}"
}
}
💡 常見問題排除:
1. 確認地點名稱正確(可查詢台灣沿海地區)
2. 確認日期格式為 YYYY-MM-DD
3. 建議查詢未來7天內的日期
如問題持續,請檢查網路連線或稍後再試。`
}
]
};
}
});
// === 觀測類工具 ===
/**
* 工具 4: 取得氣象站觀測資料
*/
server.registerTool("get_weather_station_data", {
title: "取得氣象站觀測資料",
description: "取得全台自動氣象站當前即時觀測資料。建議指定特定測站以獲得精確資訊。",
inputSchema: {
stationName: z.array(z.string()).optional()
.describe("要查詢的測站名稱列表。建議指定1-3個測站,如需多個請分別查詢"),
elementName: z.array(z.string()).optional()
.describe("要查詢的觀測要素:TEMP(溫度), HUMD(濕度), WDIR(風向), WDSD(風速), PRES(氣壓)等")
},
}, async ({ stationName, elementName }) => {
try {
const data = await cwaClient.getWeatherStationData({
stationName,
elementName
});
const formattedData = cwaClient.formatData(data, 'observation');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢氣象站資料時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
/**
* 工具 5: 取得雨量站觀測資料
*/
server.registerTool("get_rainfall_data", {
title: "取得雨量站觀測資料",
description: "取得全台自動雨量站當前即時觀測資料。建議指定特定雨量站以獲得精確資訊。",
inputSchema: {
stationName: z.array(z.string()).optional()
.describe("要查詢的雨量站名稱列表。建議指定1-3個雨量站,如需多個請分別查詢")
},
}, async ({ stationName }) => {
try {
const data = await cwaClient.getRainfallStationData({
stationName
});
const formattedData = cwaClient.formatData(data, 'observation');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢雨量資料時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
/**
* 工具 6: 取得現在天氣觀測報告
*/
server.registerTool("get_current_weather", {
title: "取得現在天氣觀測",
description: "取得全台各地現在天氣觀測報告。建議指定特定地點以獲得精確資訊。",
inputSchema: {
locationName: z.array(z.string()).optional()
.describe("要查詢的地點名稱列表。建議指定1-3個地點,如需多個請分別查詢")
},
}, async ({ locationName }) => {
try {
const data = await cwaClient.getCurrentWeatherReport({
locationName
});
const formattedData = cwaClient.formatData(data, 'observation');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢現在天氣時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
/**
* 工具 7: 取得紫外線指數
*/
server.registerTool("get_uv_index", {
title: "取得紫外線指數",
description: "取得當日各地紫外線指數最大值。建議指定特定地點以獲得精確資訊。",
inputSchema: {
locationName: z.array(z.string()).optional()
.describe("要查詢的地點名稱列表。建議指定1-3個地點,如需多個請分別查詢")
},
}, async ({ locationName }) => {
try {
const data = await cwaClient.getUVIndex({
locationName
});
const formattedData = cwaClient.formatData(data, 'observation');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢紫外線指數時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
// === 地震海嘯類工具 ===
/**
* 工具 8: 取得地震報告
*/
server.registerTool("get_earthquake_report", {
title: "取得地震報告",
description: "取得最近的顯著有感地震或小區域有感地震報告(顯示最近3筆)",
inputSchema: {
type: z.enum(['significant', 'local'])
.describe("地震類型:significant(顯著有感地震), local(小區域有感地震)"),
language: z.enum(['zh', 'en']).default('zh')
.describe("報告語言:zh(中文), en(英文)")
},
}, async ({ type, language }) => {
try {
const data = await cwaClient.getEarthquakeReport({
type,
language
});
const formattedData = cwaClient.formatData(data, 'earthquake');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢地震報告時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
/**
* 工具 9: 取得海嘯資訊
*/
server.registerTool("get_tsunami_info", {
title: "取得海嘯資訊",
description: "取得海嘯資訊資料",
inputSchema: {
timeFrom: z.string().optional()
.describe("開始時間,格式: yyyy-MM-ddThh:mm:ss"),
timeTo: z.string().optional()
.describe("結束時間,格式: yyyy-MM-ddThh:mm:ss")
},
}, async ({ timeFrom, timeTo }) => {
try {
const data = await cwaClient.getTsunamiData({
timeFrom,
timeTo
});
const formattedData = cwaClient.formatData(data, 'tsunami');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢海嘯資訊時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
// === 天氣警特報類工具 ===
/**
* 工具 10: 取得天氣警特報
*/
server.registerTool("get_weather_warning", {
title: "取得天氣警特報",
description: "取得各縣市天氣警特報資訊",
inputSchema: {
type: z.enum(['county', 'content'])
.describe("查詢類型:county(各縣市警特報情形), content(警特報內容及影響區域)"),
locationName: z.array(z.string()).optional()
.describe("要查詢的縣市名稱列表"),
timeFrom: z.string().optional()
.describe("開始時間,格式: yyyy-MM-ddThh:mm:ss"),
timeTo: z.string().optional()
.describe("結束時間,格式: yyyy-MM-ddThh:mm:ss")
},
}, async ({ type, locationName, timeFrom, timeTo }) => {
try {
const data = await cwaClient.getWeatherWarning({
type,
locationName,
timeFrom,
timeTo
});
const formattedData = cwaClient.formatData(data, 'warning');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢天氣警特報時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
/**
* 工具 11: 取得颱風資訊
*/
server.registerTool("get_typhoon_info", {
title: "取得颱風資訊",
description: "取得熱帶氣旋路徑和颱風警報資訊",
inputSchema: {
timeFrom: z.string().optional()
.describe("開始時間,格式: yyyy-MM-ddThh:mm:ss"),
timeTo: z.string().optional()
.describe("結束時間,格式: yyyy-MM-ddThh:mm:ss")
},
}, async ({ timeFrom, timeTo }) => {
try {
const data = await cwaClient.getTyphoonData({
timeFrom,
timeTo
});
const formattedData = cwaClient.formatData(data, 'typhoon');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢颱風資訊時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
// === 天文類工具 ===
/**
* 工具 12: 取得日出日沒時刻
*/
server.registerTool("get_sunrise_sunset", {
title: "取得日出日沒時刻",
description: "取得特定縣市當週日出日沒時刻資料(顯示最近7天)。建議指定單一縣市查詢。",
inputSchema: {
locationName: z.array(z.string()).optional()
.describe("要查詢的縣市名稱列表。建議指定1個縣市,如需多個請分別查詢")
},
}, async ({ locationName }) => {
try {
const data = await cwaClient.getSunriseSunset({
locationName
});
const formattedData = cwaClient.formatData(data, 'astronomy');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢日出日沒時刻時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
/**
* 工具 13: 取得月出月沒時刻
*/
server.registerTool("get_moonrise_moonset", {
title: "取得月出月沒時刻",
description: "取得特定縣市當週月出月沒時刻資料(顯示最近7天)。建議指定單一縣市查詢。",
inputSchema: {
locationName: z.array(z.string()).optional()
.describe("要查詢的縣市名稱列表。建議指定1個縣市,如需多個請分別查詢")
},
}, async ({ locationName }) => {
try {
const data = await cwaClient.getMoonriseMoonset({
locationName
});
const formattedData = cwaClient.formatData(data, 'moon');
return {
content: [
{
type: "text",
text: formattedData
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢月出月沒時刻時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
// === 系統工具 ===
/**
* 工具 14: 列出所有可用的 CWA API
*/
server.registerTool("list_cwa_apis", {
title: "列出可用的CWA API",
description: "列出所有支援的中央氣象署開放資料API端點",
inputSchema: {
category: z.enum(['all', 'forecast', 'observation', 'earthquake_tsunami', 'climate', 'warning', 'numerical', 'astronomy']).optional()
.describe("API類別篩選:all(全部), forecast(預報), observation(觀測), earthquake_tsunami(地震海嘯), climate(氣候), warning(警特報), numerical(數值預報), astronomy(天文)")
},
}, async ({ category = 'all' }) => {
let apis = CWA_API_ENDPOINTS;
if (category !== 'all') {
apis = apis.filter(api => api.category === category);
}
let result = `## 中央氣象署開放資料API清單\n\n`;
// 按類別分組顯示
const categoryGroups = {
forecast: '📊 預報類',
observation: '🌡️ 觀測類',
earthquake_tsunami: '🌍 地震海嘯類',
climate: '🌤️ 氣候類',
warning: '⚠️ 警特報類',
numerical: '🔢 數值預報類',
astronomy: '🌙 天文類'
};
Object.entries(categoryGroups).forEach(([cat, title]) => {
if (category === 'all' || category === cat) {
const categoryApis = apis.filter(api => api.category === cat);
if (categoryApis.length > 0) {
result += `### ${title}\n\n`;
categoryApis.forEach(api => {
result += `**${api.id}**: ${api.name}\n`;
result += `- ${api.description}\n`;
result += `- 端點: ${api.path}\n\n`;
});
}
}
});
if (category === 'all' || category === 'forecast') {
result += `### 天氣因子說明\n\n`;
result += `**一般預報因子:**\n`;
Object.entries(WEATHER_ELEMENTS.GENERAL).forEach(([key, value]) => {
result += `- ${key}: ${value}\n`;
});
result += `\n**觀測資料因子:**\n`;
Object.entries(WEATHER_ELEMENTS.OBSERVATION).forEach(([key, value]) => {
result += `- ${key}: ${value}\n`;
});
}
return {
content: [
{
type: "text",
text: result
}
]
};
});
/**
* 工具 15: 測試 CWA API 連線
*/
server.registerTool("test_cwa_connection", {
title: "測試CWA API連線",
description: "測試與中央氣象署開放資料API的連線狀態",
inputSchema: {},
}, async () => {
try {
const isConnected = await cwaClient.testConnection();
if (isConnected) {
return {
content: [
{
type: "text",
text: "✅ CWA API 連線測試成功!\n\n伺服器已準備好接收各種氣象查詢請求。"
}
]
};
}
else {
return {
content: [
{
type: "text",
text: "❌ CWA API 連線測試失敗\n\n請檢查:\n1. 網路連線是否正常\n2. CWA_API_KEY 環境變數是否正確設定\n3. API 授權碼是否有效"
}
]
};
}
}
catch (error) {
return {
content: [
{
type: "text",
text: `連線測試時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
/**
* 工具 16: 取得工具使用指南
*/
server.registerTool("get_tool_usage_guide", {
title: "取得工具使用指南",
description: "提供 CWA 天氣 MCP 伺服器所有工具的詳細使用說明、參數說明和範例",
inputSchema: {
toolName: z.string().optional()
.describe("要查詢的工具名稱。如未指定,將顯示所有工具的使用指南"),
category: z.enum(['all', 'forecast', 'observation', 'earthquake_tsunami', 'warning', 'astronomy', 'system']).optional()
.describe("工具類別篩選:all(全部), forecast(預報), observation(觀測), earthquake_tsunami(地震海嘯), warning(警特報), astronomy(天文), system(系統)")
},
}, async ({ toolName, category = 'all' }) => {
try {
const toolGuides = {
// 預報類工具
get_county_weather: {
category: 'forecast',
title: '📊 縣市天氣預報',
description: '取得台灣特定縣市今明36小時天氣預報',
parameters: {
locationName: {
type: 'array[string]',
required: false,
description: '要查詢的縣市名稱列表。建議單次查詢1個縣市',
options: TAIWAN_COUNTIES
},
elementName: {
type: 'array[string]',
required: false,
description: '要查詢的天氣因子',
options: ['Wx(天氣現象)', 'PoP(降雨機率)', 'CI(舒適度指數)', 'MinT(最低溫度)', 'MaxT(最高溫度)']
}
},
examples: [
{
title: '查詢台北市完整天氣預報',
code: `{
"locationName": ["臺北市"],
"elementName": ["Wx", "PoP", "CI", "MinT", "MaxT"]
}`
},
{
title: '查詢高雄市降雨機率',
code: `{
"locationName": ["高雄市"],
"elementName": ["PoP"]
}`
}
],
tips: [
'建議一次查詢單一縣市以獲得最佳結果',
'不指定參數時會返回所有縣市的基本天氣資訊',
'天氣因子可以組合查詢,如["Wx", "PoP", "MaxT"]'
]
},
get_township_weather: {
category: 'forecast',
title: '🏘️ 鄉鎮天氣預報',
description: '取得台灣特定縣市的鄉鎮天氣預報',
parameters: {
county: {
type: 'string',
required: true,
description: '要查詢的縣市',
options: Object.keys(COUNTY_API_MAPPING)
},
period: {
type: 'string',
required: true,
description: '預報時間範圍',
options: ['3days(未來3天逐3小時)', 'weekly(未來1週)']
},
locationName: {
type: 'array[string]',
required: false,
description: '要查詢的鄉鎮名稱列表。建議指定1-3個鄉鎮'
},
elementName: {
type: 'array[string]',
required: false,
description: '要查詢的天氣因子名稱列表'
}
},
examples: [
{
title: '查詢桃園市中壢區3天天氣',
code: `{
"county": "桃園市",
"period": "3days",
"locationName": ["中壢區"]
}`
},
{
title: '查詢台北市一週天氣預報',
code: `{
"county": "臺北市",
"period": "weekly"
}`
}
],
tips: [
'county 參數必須提供',
'period 參數必須是 "3days" 或 "weekly"',
'不指定 locationName 時會返回該縣市所有鄉鎮資料'
]
},
get_tidal_forecast: {
category: 'forecast',
title: '🌊 潮汐預報',
description: '取得特定地點和日期的潮汐預報資料',
parameters: {
locationName: {
type: 'array[string]',
required: true,
description: '要查詢的地點名稱列表',
options: ['基隆', '淡水', '頭城', '磯崎', '墾丁', '南灣', '小灣', '西子灣', '福隆', '龍洞南口', '八斗子', '烏石', '新竹', '安平', '興達', '旗津', '鼓山', '龍洞灣', '杉原海域', '後壁湖', '萬里桐', '中角沙珠灣', '白砂', '風吹砂等']
},
date: {
type: 'string',
required: true,
description: '查詢日期,格式: YYYY-MM-DD'
}
},
examples: [
{
title: '查詢基隆港今日潮汐',
code: `{
"locationName": ["基隆"],
"date": "2025-07-03"
}`
},
{
title: '查詢淡水和八斗子潮汐',
code: `{
"locationName": ["淡水", "八斗子"],
"date": "2025-07-04"
}`
}
],
tips: [
'地點名稱和日期都是必要參數',
'日期格式必須為 YYYY-MM-DD',
'建議查詢未來7天內的日期以獲得最準確預報',
'可同時查詢多個地點的潮汐資料'
]
},
// 觀測類工具
get_weather_station_data: {
category: 'observation',
title: '🌡️ 氣象站觀測資料',
description: '取得全台自動氣象站當前即時觀測資料',
parameters: {
stationName: {
type: 'array[string]',
required: false,
description: '要查詢的測站名稱列表。建議指定1-3個測站'
},
elementName: {
type: 'array[string]',
required: false,
description: '要查詢的觀測要素',
options: ['TEMP(溫度)', 'HUMD(濕度)', 'WDIR(風向)', 'WDSD(風速)', 'PRES(氣壓)', 'SUN(日照時數)', 'RAIN(雨量)']
}
},
examples: [
{
title: '查詢台北站即時資料',
code: `{
"stationName": ["臺北"],
"elementName": ["TEMP", "HUMD", "WDSD"]
}`
},
{
title: '查詢所有測站溫度',
code: `{
"elementName": ["TEMP"]
}`
}
],
tips: [
'不指定測站時會返回全台測站資料',
'可依需求指定特定觀測要素',
'資料為即時觀測,每小時更新'
]
},
get_rainfall_data: {
category: 'observation',
title: '☔ 雨量站觀測資料',
description: '取得全台自動雨量站當前即時觀測資料',
parameters: {
stationName: {
type: 'array[string]',
required: false,
description: '要查詢的雨量站名稱列表。建議指定1-3個雨量站'
}
},
examples: [
{
title: '查詢台北雨量站資料',
code: `{
"stationName": ["臺北"]
}`
},
{
title: '查詢所有雨量站資料',
code: `{}`
}
],
tips: [
'不指定雨量站時會返回全台雨量站資料',
'資料包含即時雨量、累積雨量等資訊',
'適合用於降雨監測和預警'
]
},
get_current_weather: {
category: 'observation',
title: '🌤️ 現在天氣觀測',
description: '取得全台各地現在天氣觀測報告',
parameters: {
locationName: {
type: 'array[string]',
required: false,
description: '要查詢的地點名稱列表。建議指定1-3個地點'
}
},
examples: [
{
title: '查詢台北現在天氣',
code: `{
"locationName": ["臺北市"]
}`
},
{
title: '查詢多個縣市現在天氣',
code: `{
"locationName": ["臺北市", "高雄市", "臺中市"]
}`
}
],
tips: [
'提供各地即時天氣現象觀測',
'包含溫度、濕度、風向風速等資訊',
'適合快速了解當前天氣狀況'
]
},
get_uv_index: {
category: 'observation',
title: '☀️ 紫外線指數',
description: '取得當日各地紫外線指數最大值',
parameters: {
locationName: {
type: 'array[string]',
required: false,
description: '要查詢的地點名稱列表。建議指定1-3個地點'
}
},
examples: [
{
title: '查詢台北紫外線指數',
code: `{
"locationName": ["臺北"]
}`
},
{
title: '查詢全台紫外線指數',
code: `{}`
}
],
tips: [
'提供當日紫外線指數最大值',
'包含曝曬級數和防護建議',
'適合規劃戶外活動參考'
]
},
// 地震海嘯類工具
get_earthquake_report: {
category: 'earthquake_tsunami',
title: '🌍 地震報告',
description: '取得最近的顯著有感地震或小區域有感地震報告',
parameters: {
type: {
type: 'string',
required: true,
description: '地震類型',
options: ['significant(顯著有感地震)', 'local(小區域有感地震)']
},
language: {
type: 'string',
required: false,
description: '報告語言',
options: ['zh(中文)', 'en(英文)'],
default: 'zh'
}
},
examples: [
{
title: '查詢顯著有感地震報告',
code: `{
"type": "significant",
"language": "zh"
}`
},
{
title: '查詢小區域有感地震報告',
code: `{
"type": "local"
}`
}
],
tips: [
'type 參數必須提供',
'顯示最近3筆地震報告',
'包含地震規模、深度、震央位置等資訊'
]
},
get_tsunami_info: {
category: 'earthquake_tsunami',
title: '🌊 海嘯資訊',
description: '取得海嘯資訊資料',
parameters: {
timeFrom: {
type: 'string',
required: false,
description: '開始時間,格式: yyyy-MM-ddThh:mm:ss'
},
timeTo: {
type: 'string',
required: false,
description: '結束時間,格式: yyyy-MM-ddThh:mm:ss'
}
},
examples: [
{
title: '查詢最近海嘯資訊',
code: `{}`
},
{
title: '查詢特定時間範圍海嘯資訊',
code: `{
"timeFrom": "2025-07-01T00:00:00",
"timeTo": "2025-07-03T23:59:59"
}`
}
],
tips: [
'不指定時間範圍時會返回最近的海嘯資訊',
'時間格式為 ISO 8601 標準',
'包含海嘯警報、注意報等資訊'
]
},
// 警特報類工具
get_weather_warning: {
category: 'warning',
title: '⚠️ 天氣警特報',
description: '取得各縣市天氣警特報資訊',
parameters: {
type: {
type: 'string',
required: true,
description: '查詢類型',
options: ['county(各縣市警特報情形)', 'content(警特報內容及影響區域)']
},
locationName: {
type: 'array[string]',
required: false,
description: '要查詢的縣市名稱列表'
},
timeFrom: {
type: 'string',
required: false,
description: '開始時間,格式: yyyy-MM-ddThh:mm:ss'
},
timeTo: {
type: 'string',
required: false,
description: '結束時間,格式: yyyy-MM-ddThh:mm:ss'
}
},
examples: [
{
title: '查詢各縣市警特報情形',
code: `{
"type": "county"
}`
},
{
title: '查詢台北市警特報內容',
code: `{
"type": "content",
"locationName": ["臺北市"]
}`
}
],
tips: [
'type 參數必須提供',
'包含大雨、強風、高溫等各類警特報',
'可查詢特定縣市或全台警特報狀況'
]
},
get_typhoon_info: {
category: 'warning',
title: '🌀 颱風資訊',
description: '取得熱帶氣旋路徑和颱風警報資訊',
parameters: {
timeFrom: {
type: 'string',
required: false,
description: '開始時間,格式: yyyy-MM-ddThh:mm:ss'
},
timeTo: {
type: 'string',
required: false,
description: '結束時間,格式: yyyy-MM-ddThh:mm:ss'
}
},
examples: [
{
title: '查詢當前颱風資訊',
code: `{}`
},
{
title: '查詢特定時間範圍颱風資訊',
code: `{
"timeFrom": "2025-07-01T00:00:00",
"timeTo": "2025-07-31T23:59:59"
}`
}
],
tips: [
'不指定時間範圍時會返回最近的颱風資訊',
'包含颱風路徑、強度、警報範圍等資訊',
'適合颱風季節防災準備參考'
]
},
// 天文類工具
get_sunrise_sunset: {
category: 'astronomy',
title: '🌅 日出日沒時刻',
description: '取得特定縣市當週日出日沒時刻資料',
parameters: {
locationName: {
type: 'array[string]',
required: false,
description: '要查詢的縣市名稱列表。建議指定1個縣市'
}
},
examples: [
{
title: '查詢台北市日出日沒時刻',
code: `{
"locationName": ["臺北市"]
}`
},
{
title: '查詢所有縣市日出日沒時刻',
code: `{}`
}
],
tips: [
'顯示最近7天的日出日沒時刻',
'適合規劃攝影、戶外活動時間',
'包含民用、航海、天文曙光時間'
]
},
get_moonrise_moonset: {
category: 'astronomy',
title: '🌙 月出月沒時刻',
description: '取得特定縣市當週月出月沒時刻資料',
parameters: {
locationName: {
type: 'array[string]',
required: false,
description: '要查詢的縣市名稱列表。建議指定1個縣市'
}
},
examples: [
{
title: '查詢台北市月出月沒時刻',
code: `{
"locationName": ["臺北市"]
}`
},
{
title: '查詢高雄市月出月沒時刻',
code: `{
"locationName": ["高雄市"]
}`
}
],
tips: [
'顯示最近7天的月出月沒時刻',
'包含月相資訊',
'適合天文觀測、攝影規劃'
]
},
// 系統工具
list_cwa_apis: {
category: 'system',
title: '📋 列出可用的CWA API',
description: '列出所有支援的中央氣象署開放資料API端點',
parameters: {
category: {
type: 'string',
required: false,
description: 'API類別篩選',
options: ['all(全部)', 'forecast(預報)', 'observation(觀測)', 'earthquake_tsunami(地震海嘯)', 'climate(氣候)', 'warning(警特報)', 'numerical(數值預報)', 'astronomy(天文)']
}
},
examples: [
{
title: '列出所有API',
code: `{
"category": "all"
}`
},
{
title: '列出預報類API',
code: `{
"category": "forecast"
}`
}
],
tips: [
'提供完整的API端點資訊',
'包含API說明和使用方式',
'適合了解系統功能概況'
]
},
test_cwa_connection: {
category: 'system',
title: '🔧 測試CWA API連線',
description: '測試與中央氣象署開放資料API的連線狀態',
parameters: {},
examples: [
{
title: '測試API連線',
code: `{}`
}
],
tips: [
'無需任何參數',
'檢查API授權碼是否有效',
'適合系統診斷和故障排除'
]
}
};
// 如果指定了特定工具
if (toolName) {
const guide = toolGuides[toolName];
if (!guide) {
return {
content: [
{
type: "text",
text: `❌ 找不到工具 "${toolName}"
🔍 可用的工具名稱:
${Object.keys(toolGuides).map(name => `• ${name}`).join('\n')}
💡 使用 get_tool_usage_guide 不帶參數可查看所有工具的使用指南。`
}
]
};
}
let result = `# ${guide.title}\n\n`;
result += `**描述**: ${guide.description}\n\n`;
// 參數說明
if (Object.keys(guide.parameters).length > 0) {
result += `## 📋 參數說明\n\n`;
Object.entries(guide.parameters).forEach(([param, info]) => {
result += `### ${param}\n`;
result += `- **類型**: ${info.type}\n`;
result += `- **必要**: ${info.required ? '✅ 是' : '❌ 否'}\n`;
result += `- **說明**: ${info.description}\n`;
if (info.default) {
result += `- **預設值**: ${info.default}\n`;
}
if (info.options && info.options.length > 0) {
result += `- **可選值**: ${Array.isArray(info.options) ? info.options.join(', ') : String(info.options)}\n`;
}
result += '\n';
});
}
// 使用範例
if (guide.examples && guide.examples.length > 0) {
result += `## 📝 使用範例\n\n`;
guide.examples.forEach((example, index) => {
result += `### ${index + 1}. ${example.title}\n\n`;
result += '```json\n';
result += example.code;
result += '\n```\n\n';
});
}
// 使用提示
if (guide.tips && guide.tips.length > 0) {
result += `## 💡 使用提示\n\n`;
guide.tips.forEach((tip) => {
result += `• ${tip}\n`;
});
}
return {
content: [
{
type: "text",
text: result
}
]
};
}
// 按類別篩選工具
let filteredTools = Object.entries(toolGuides);
if (category !== 'all') {
filteredTools = filteredTools.filter(([_, guide]) => guide.category === category);
}
// 生成完整指南
let result = `# 🌤️ CWA 天氣 MCP 工具使用指南\n\n`;
result += `本指南提供所有 CWA 天氣 MCP 工具的詳細使用說明。\n\n`;
// 按類別分組
const categoryGroups = {
forecast: '📊 預報類工具',
observation: '🌡️ 觀測類工具',
earthquake_tsunami: '🌍 地震海嘯類工具',
warning: '⚠️ 警特報類工具',
astronomy: '🌙 天文類工具',
system: '🔧 系統工具'
};
Object.entries(categoryGroups).forEach(([cat, title]) => {
if (category === 'all' || category === cat) {
const categoryTools = filteredTools.filter(([_, guide]) => guide.category === cat);
if (categoryTools.length > 0) {
result += `## ${title}\n\n`;
categoryTools.forEach(([toolName, guide]) => {
result += `### ${guide.title}\n`;
result += `**工具名稱**: \`${toolName}\`\n`;
result += `**描述**: ${guide.description}\n\n`;
// 簡化的參數說明
if (Object.keys(guide.parameters).length > 0) {
result += `**主要參數**: `;
const requiredParams = Object.entries(guide.parameters)
.filter(([_, info]) => info.required)
.map(([param]) => `${param}*`);
const optionalParams = Object.entries(guide.parameters)
.filter(([_, info]) => !info.required)
.map(([param]) => param);
result += [...requiredParams, ...optionalParams].join(', ');
result += '\n';
}
// 第一個範例
if (guide.examples && guide.examples.length > 0) {
result += `**範例**: \`${guide.examples[0].code.replace(/\n/g, ' ').replace(/\s+/g, ' ')}\`\n`;
}
result += '\n';
});
}
}
});
result += `## 🔍 詳細使用說明\n\n`;
result += `若要查看特定工具的詳細使用說明,請使用:\n`;
result += `\`\`\`json\n`;
result += `{\n`;
result += ` "toolName": "工具名稱"\n`;
result += `}\n`;
result += `\`\`\`\n\n`;
result += `## 📚 更多資源\n\n`;
result += `• 使用 \`list_cwa_apis\` 查看所有支援的 CWA API\n`;
result += `• 使用 \`test_cwa_connection\` 測試 API 連線狀態\n`;
result += `• 查看 cwa-api-docs 資源取得完整 API 文檔\n`;
return {
content: [
{
type: "text",
text: result
}
]
};
}
catch (error) {
return {
content: [
{
type: "text",
text: `查詢工具使用指南時發生錯誤: ${error instanceof Error ? error.message : '未知錯誤'}`
}
]
};
}
});
/**
* 資源: CWA API 完整文檔
*/
server.registerResource("cwa-api-docs", "cwa://api-docs", {
title: "CWA API 完整文檔",
description: "中央氣象署開放資料API完整使用說明",
mimeType: "text/markdown"
}, async () => {
const docs = `# 中央氣象署開放資料API完整使用說明
## 簡介
中央氣象署開放資料平台提供氣象、氣候、地震、海嘯、天文等完整資料供民眾使用。本MCP伺服器整合了所有主要的API類別。
## 支援的API類別
### 📊 預報類 (F-系列)
- **一般天氣預報**: 今明36小時縣市天氣預報
- **鄉鎮天氣預報**: 各縣市鄉鎮3天/1週詳細預報
- **潮汐預報**: 未來1個月潮汐資料
- **健康氣象預報**: 冷傷害、熱傷害、溫差提醒指數
### 🌡️ 觀測類 (O-系列)
- **自動氣象站**: 全台氣象站即時觀測資料
- **自動雨量站**: 全台雨量站即時觀測資料
- **現在天氣**: 各地現在天氣觀測報告
- **紫外線指數**: 每日紫外線指數資料
- **臭氧總量**: 台北站臭氧觀測資料
- **海象監測**: 浮標站與潮位站海況資料
### 🌍 地震海嘯類 (E-系列, O-B0076)
- **顯著有感地震**: 重大地震報告(中英文)
- **小區域有感地震**: 區域地震報告(中英文)
- **海嘯資訊**: 海嘯警報和資訊
### 🌤️ 氣候類 (C-系列)
- **每日雨量**: 地面測站每日雨量歷史資料
- **月平均資料**: 地面測站月平均氣象資料
- **測站基本資料**: 有人/無人氣象測站資訊
### ⚠️ 警特報類 (W-系列)
- **天氣特報**: 各縣市天氣警特報
- **颱風消息**: 熱帶氣旋路徑和警報
- **健康氣象警示**: 熱傷害指數警示
### 🔢 數值預報類 (M-系列)
- **全球預報系統**: 數值模式溫度預報資料
### 🌙 天文類 (A-系列)
- **日出日沒**: 全台各縣市日出日沒時刻
- **月出月沒**: 全台各縣市月出月沒時刻
## MCP工具對照表
| 工具名稱 | 功能 | API類別 |
|---------|------|---------|
| get_county_weather | 縣市天氣預報 | 預報類 |
| get_township_weather | 鄉鎮天氣預報 | 預報類 |
| get_tidal_forecast | 潮汐預報 | 預報類 |
| get_weather_station_data | 氣象站觀測 | 觀測類 |
| get_rainfall_data | 雨量站觀測 | 觀測類 |
| get_current_weather | 現在天氣 | 觀測類 |
| get_uv_index | 紫外線指數 | 觀測類 |
| get_earthquake_report | 地震報告 | 地震海嘯類 |
| get_tsunami_info | 海嘯資訊 | 地震海嘯類 |
| get_weather_warning | 天氣警特報 | 警特報類 |
| get_typhoon_info | 颱風資訊 | 警特報類 |
| get_sunrise_sunset | 日出日沒 | 天文類 |
| get_moonrise_moonset | 月出月沒 | 天文類 |
## 常用查詢範例
### 即時天氣狀況
- 查詢現在天氣觀測
- 查詢氣象站即時資料
- 查詢雨量站資料
### 天氣預報
- 縣市今明天氣
- 鄉鎮詳細預報
- 潮汐預報
### 災害防護
- 地震報告查詢
- 天氣警特報
- 颱風路徑資訊
### 生活資訊
- 紫外線指數
- 日出日沒時刻
- 月出月沒時刻
## 注意事項
- API有使用頻率限制,請適當使用
- 時間格式使用ISO 8601標準
- 需要有效的CWA API授權碼
- 部分API僅提供最近一段時間的資料
更多資訊請參考:https://opendata.cwa.gov.tw/
`;
return {
contents: [
{
uri: "cwa://api-docs",
text: docs
}
]
};
});
// 啟動伺服器
async function main() {
// 只在錯誤時輸出到 stderr,不要使用 console.log
// 測試 API 連線
const isConnected = await cwaClient.testConnection();
if (!isConnected) {
console.error("❌ 無法連接到 CWA API,請檢查授權碼設定");
process.exit(1);
}
// 成功啟動,不輸出任何訊息避免干擾 MCP 協議
const transport = new StdioServerTransport();
await server.connect(transport);
}
// 錯誤處理
process.on('uncaughtException', (error) => {
console.error('未捕獲的異常:', error);
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('未處理的Promise拒絕:', reason);
process.exit(1);
});
// 啟動伺服器
main().catch((error) => {
console.error('伺服器啟動失敗:', error);
process.exit(1);
});
//# sourceMappingURL=index.js.map