UNPKG

@bashcat/cwa-mcp-weather

Version:

MCP 伺服器整合中央氣象署 (CWA) 開放資料 API - 完整支援所有15個天氣工具

1,586 lines (1,552 loc) 56.2 kB
#!/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(表示2025628日) • 建議查詢未來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