get-weather
Retrieve current weather data for any city by providing the city name as input. This tool fetches weather information from the MCP Weather Service.
Instructions
Get weather information for a city
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| city | Yes | City name to get weather for |
Implementation Reference
- src/index.ts:178-238 (registration)Registers the 'get-weather' tool using server.tool() with name, description, input schema using Zod, and inline handler function.server.tool( 'get-weather', 'Get weather information for a city', { city: z.string().describe('City name to get weather for') }, async ({ city }) => { debug(`Handling get-weather request for city: ${city}`); try { let attempts = 0; const maxAttempts = 3; let lastError: Error | null = null; while (attempts < maxAttempts) { try { attempts++; debug(`Attempt ${attempts}/${maxAttempts} for city: ${city}`); // 最後の試行では、可能であればモックデータを使用 const useMockData = attempts === maxAttempts; const weather = await getWeatherForCity(city, useMockData); const conditionJapanese = weather.condition; return { content: [{ type: 'text', text: `${weather.cityName}の天気:\n気温: ${weather.temperature}\n状態: ${conditionJapanese}` }] }; } catch (error) { lastError = error instanceof Error ? error : new Error(String(error)); debug(`Attempt ${attempts} failed:`, lastError.message); if (attempts < maxAttempts) { const waitTime = 1000 * attempts; debug(`Waiting ${waitTime}ms before next retry`); await new Promise(resolve => setTimeout(resolve, waitTime)); } } } return { content: [{ type: 'text', text: `${city}の天気情報の取得に失敗しました: ${lastError?.message || '不明なエラー'}` }] }; } catch (error) { debug(`Error processing weather request:`, error); return { content: [{ type: 'text', text: `${city}の天気情報の取得に失敗しました: ${error instanceof Error ? error.message : String(error)}` }] }; } } );
- src/index.ts:184-237 (handler)Handler function implementing the 'get-weather' tool logic: retries API calls via getWeatherForCity, handles errors, formats response as MCP text content.async ({ city }) => { debug(`Handling get-weather request for city: ${city}`); try { let attempts = 0; const maxAttempts = 3; let lastError: Error | null = null; while (attempts < maxAttempts) { try { attempts++; debug(`Attempt ${attempts}/${maxAttempts} for city: ${city}`); // 最後の試行では、可能であればモックデータを使用 const useMockData = attempts === maxAttempts; const weather = await getWeatherForCity(city, useMockData); const conditionJapanese = weather.condition; return { content: [{ type: 'text', text: `${weather.cityName}の天気:\n気温: ${weather.temperature}\n状態: ${conditionJapanese}` }] }; } catch (error) { lastError = error instanceof Error ? error : new Error(String(error)); debug(`Attempt ${attempts} failed:`, lastError.message); if (attempts < maxAttempts) { const waitTime = 1000 * attempts; debug(`Waiting ${waitTime}ms before next retry`); await new Promise(resolve => setTimeout(resolve, waitTime)); } } } return { content: [{ type: 'text', text: `${city}の天気情報の取得に失敗しました: ${lastError?.message || '不明なエラー'}` }] }; } catch (error) { debug(`Error processing weather request:`, error); return { content: [{ type: 'text', text: `${city}の天気情報の取得に失敗しました: ${error instanceof Error ? error.message : String(error)}` }] }; } }
- src/index.ts:181-183 (schema)Zod input schema defining the 'city' parameter as a required string.{ city: z.string().describe('City name to get weather for') },
- src/index.ts:94-156 (helper)Helper function to fetch real weather data from Open-Meteo APIs (geocoding + forecast) or use mock data, translates weather codes to Japanese.async function getWeatherForCity(city: string, useMockData: boolean = false) { try { const normalizedCity = city.trim(); debug(`Getting weather for city: ${normalizedCity}`); if (useMockData && MOCK_WEATHER_DATA[normalizedCity]) { debug(`Using mock data for ${normalizedCity}`); return MOCK_WEATHER_DATA[normalizedCity]; } // ジオコーディングAPIを使用して座標を取得 const geocodingResponse = await axios.get( `https://geocoding-api.open-meteo.com/v1/search`, { params: { name: normalizedCity, count: 1, language: 'en' }, timeout: 5000 } ); if (!geocodingResponse.data.results || geocodingResponse.data.results.length === 0) { throw new Error(`City "${normalizedCity}" not found`); } const { latitude, longitude, name } = geocodingResponse.data.results[0]; debug(`Found coordinates for ${name}: ${latitude}, ${longitude}`); // 天気APIを使用して天気情報を取得 const weatherResponse = await axios.get( `https://api.open-meteo.com/v1/forecast`, { params: { latitude, longitude, current: 'temperature_2m,weather_code', timezone: 'Asia/Tokyo' }, timeout: 5000 } ); const weatherCode = weatherResponse.data.current.weather_code; const weatherDescription = weatherCodes[weatherCode] || "不明"; return { cityName: name, temperature: `${weatherResponse.data.current.temperature_2m}${weatherResponse.data.current_units.temperature_2m}`, condition: weatherDescription }; } catch (error) { debug(`Error getting weather for city ${city}:`, error); if (MOCK_WEATHER_DATA[city]) { debug(`Falling back to mock data for ${city}`); return MOCK_WEATHER_DATA[city]; } throw error; } }