Skip to main content
Glama

MCP Weather Service

by terisuke
HandsOn.md10.3 kB
MCP Weather サーバー ハンズオン資料 ## ゴール - Model Context Protocol (MCP) を用いて、都市名を引数に天気予報を返すサーバーを Node.js (TypeScript) で構築する - ローカルで起動した MCP サーバーを Claude Desktop から呼び出し、ツールとして活用できることを確認する ## 想定所要時間 30 〜 60 分 ## 前提条件 項目 | 推奨バージョン | 備考 ---------------|-------------------------|------------------------------------------ OS | macOS / Windows / Linux | いずれも可 Node.js | 18 以上 | node -v で確認 npm | 9 以上 | npm -v で確認 TypeScript | 5.0 以上 | devDependency として導入 Claude Desktop | v0.7 以上 | "Experimental Features" → MCP toggle がある版 Tip: nvm / nvs など任意の Node バージョンマネージャを使うと複数バージョンを楽に切り替えられます。 --- ## 0. 事前準備 ### プロジェクト用フォルダの作成 ```bash mkdir mcp-weather && cd mcp-weather ``` --- ## 1. Node プロジェクト初期化 ```bash npm init -y npm i -D typescript ts-node nodemon npm i @modelcontextprotocol/sdk axios zod ``` - `typescript` & `ts-node` : TypeScript 実行環境 - `nodemon` : 保存時に自動再起動 - `@modelcontextprotocol/sdk` : MCP サーバー公式 SDK - `axios` : HTTP クライアント - `zod` : スキーマバリデーション ### TypeScript 設定 ```bash npx tsc --init --rootDir src --outDir dist \ --moduleResolution node --esModuleInterop true ``` --- ## 2. ソースコード実装 新規ディレクトリ `src` を作成し、`index.ts` を以下の内容で保存します。 ```typescript // src/index.ts import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import axios from "axios"; import { z } from "zod"; // デバッグメッセージを出力する関数 function debug(...args: any[]) { console.error("[DEBUG]", ...args); } // 天気コードと日本語の天気状態の対応を定義 const weatherCodes: Record<number, string> = { 0: "快晴", 1: "晴れ", 2: "晴れ時々曇り", 3: "曇り", 45: "霧", 48: "霧氷", 51: "小雨", // 他の天気コードも追加可能 }; // 都市の天気情報を取得 async function getWeatherForCity(city: string) { try { const normalizedCity = city.trim(); debug(`Getting weather for city: ${normalizedCity}`); // ジオコーディングAPIを使用して座標を取得 const geocodingResponse = await axios.get( `https://geocoding-api.open-meteo.com/v1/search`, { params: { name: normalizedCity, count: 1, language: "ja" }, timeout: 5000 } ); if (!geocodingResponse.data.results || geocodingResponse.data.results.length === 0) { throw new Error(`都市「${normalizedCity}」が見つかりません`); } 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", hourly: "temperature_2m,weather_code", forecast_days: 1, timezone: "Asia/Tokyo" }, timeout: 5000 } ); const weatherCode = weatherResponse.data.current.weather_code; const weatherDescription = weatherCodes[weatherCode] || "不明"; // 3時間ごとの予報データを抽出 const hourlyData = weatherResponse.data.hourly; const next24h = []; for (let i = 0; i < 24; i += 3) { next24h.push({ time: hourlyData.time[i], temp: hourlyData.temperature_2m[i], weather: weatherCodes[hourlyData.weather_code[i]] || "不明" }); } return { cityName: name, temperature: `${weatherResponse.data.current.temperature_2m}${weatherResponse.data.current_units.temperature_2m}`, condition: weatherDescription, forecast: next24h }; } catch (error) { debug(`Error getting weather for city ${city}:`, error); throw error; } } // MCPサーバーを開始するメイン関数 async function main() { debug("Starting MCP Weather Server"); const server = new McpServer({ name: "Weather MCP", version: "1.0.0", description: "A simple MCP server for weather data", }, { capabilities: { logging: {}, sampling: {}, roots: { listChanged: true } } }); server.tool( "get-weather", "都市の天気情報を取得する", { city: z.string().describe("天気を取得したい都市名") }, async ({ city }) => { debug(`Handling get-weather request for city: ${city}`); try { const weather = await getWeatherForCity(city); // 3時間ごとの予報データを整形 const forecastText = weather.forecast.map(f => `${new Date(f.time).getHours()}時: ${f.temp}°C (${f.weather})` ).join("\n"); return { content: [{ type: "text", text: `${weather.cityName}の天気情報:\n` + `現在の気温: ${weather.temperature}\n` + `現在の天気: ${weather.condition}\n\n` + `24時間予報 (3時間ごと):\n${forecastText}` }] }; } catch (error) { debug(`Error processing weather request:`, error); return { content: [{ type: "text", text: `${city}の天気情報の取得に失敗しました: ${error instanceof Error ? error.message : String(error)}` }] }; } } ); debug("Creating StdioServerTransport"); const transport = new StdioServerTransport(); await server.connect(transport); debug("MCP server ready to receive requests"); } // エラーハンドリング process.on("uncaughtException", (error) => { debug("Uncaught exception:", error); }); process.on("unhandledRejection", (reason, promise) => { debug("Unhandled rejection at:", promise, "reason:", reason); }); // メイン処理を開始 main().catch((error) => { debug("Fatal error in main:", error); process.exit(1); }); ``` ### package.json の修正 `package.json` のスクリプトセクションを以下のように修正してください: ```json "scripts": { "dev": "nodemon --exec ts-node src/index.ts", "build": "tsc", "start": "node dist/index.js", "inspect": "npx @modelcontextprotocol/inspector ." } ``` --- ## 3. サーバー起動 ```bash npm run dev ``` 成功すると以下のようなログが表示されます: ``` [DEBUG] Starting MCP Weather Server [DEBUG] Creating StdioServerTransport [DEBUG] MCP server ready to receive requests ``` ※ ポート変更したい場合は設定を書き換えてください。 --- ## 4. Claude Desktop の MCP 設定 1. Claude Desktop を起動し、メニューバーの「Claude」→「Settings...」を選択 2. 左側のメニューから「Developer」を選択 3. 「Edit Config」ボタンをクリック 4. エクスプローラーが開くので `claude_desktop_config.json` ファイルをテキストエディタで開く 5. 以下のJSONを追加します: ```json { "mcpServers": { "weather": { "command": "node", "args": [ "/absolute/path/to/your/mcp-weather/dist/index.js" ] } } } ``` 注意: `args` のパスは、実際のプロジェクトのパスに置き換えてください。 6. ファイルを保存し、Claude Desktop を再起動します。 7. 🔨アイコンをクリックして「get-weather」が追加されていることを確認します。 --- ## 5. インスペクタの実行(オプション) MCPサーバーの動作を確認するため、インスペクタを使用できます: ```bash npm run inspect ``` これを実行後、ブラウザで `http://127.0.0.1:6274` にアクセスします。 --- ## 6. 動作確認 Claude のチャット欄に以下を入力します。 ``` #assistant_tools: get-weather 東京の天気を教えて ``` Claude が自動で `get-weather` ツールを実行し、現在の天気と24時間分の予報をわかりやすく自然言語で返すはずです。 例: 「東京の天気情報: 現在の気温: 21°C、現在の天気: 晴れ、24時間予報 (3時間ごと): 12時: 22°C (晴れ)...」 --- ## 7. トラブルシューティング 症状 | 原因・対応策 ------------------|------------------------------------------------------------------ 都市「◯◯」が見つかりません | 誤字/マイナー地名。英語表記などで再試行 Claude がツールを選ばない | プロンプトに `#assistant_tools: get-weather` を含めているか、endpoint URL が正しいか タイムアウトエラー | 接続環境を確認。プロキシ設定が必要な場合は対応 インスペクタが起動しない | Node.js のバージョンを確認(18以上が必要) --- ## 8. 応用課題(任意) 項目 | ヒント ------------|------------------------------------- Web UIの作成 | expessを使って簡易WebUIからも天気を検索できるようにする キャッシュ機能 | node-cacheを使って同じ都市のリクエストをキャッシュする 複数言語対応 | 言語パラメータを追加し、多言語での結果を返せるようにする グラフ表示 | SVGやChartJSを使って温度変化をグラフ化する Docker化 | FROM node:18-alpineをベースにDockerfile作成 --- ## 参考リンク - MCP GitHub: https://github.com/modelcontextprotocol - Open-Meteo API Docs: https://open-meteo.com/en/docs - Claude Desktop Release Notes: https://www.anthropic.com/ --- Happy Coding! ✨

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/terisuke/my-weather-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server