project_files_mcp-weather-server.txt•4.83 kB
📄 Details:
Project Description: This is a project description
Main Technologies: node.js
📝 Exclusion Note: The directories and files listed in excluded are existing files that have been excluded because their content is not relevant.
📁 Structure:
📂 Path: main.ts
📂 Excluded Directories:
.vscode/
node_modules/
project_scanners/
🗂️ Files Content:
Path: main.ts
Content: // main.ts (Servidor MCP de Clima y Historial - Versión Final) import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { z } from "zod"; import { writeFile, readFile } from 'fs/promises'; // Importamos para manejo de archivos // --- CONFIGURACIÓN DEL SERVIDOR --- const server = new McpServer({ name: "Weather Server", version: "1.0.0" }); // --- HERRAMIENTA 1: OBTENER CLIMA (Con Historial) --- server.tool( 'get-weather', 'Tool to get the current weather, temperature, and humidity for a specified city.', { city: z.string().describe("The name of the city to get the weather for") }, async({ city }) => { try { // Paso 1: Obtener coordenadas de la ciudad (Geocoding API) const geoResponse = await fetch( `https://geocoding-api.open-meteo.com/v1/search?name=${city}&count=1&language=en&format=json` ); const geoData = await geoResponse.json(); // Manejar ciudad no encontrada if (!geoData.results || geoData.results.length === 0) { return { content: [{ type: "text", text: `Sorry, I couldn't find a city named "${city}". Please check the spelling and try again.` }] }; } // Paso 2: Obtener datos del clima usando coordenadas const { latitude, longitude } = geoData.results[0]; const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,relative_humidity_2m,apparent_temperature,precipitation,weather_code&hourly=temperature_2m,precipitation&forecast_days=1`; const weatherResponse = await fetch(weatherUrl); const weatherData = await weatherResponse.json(); // Paso 3: Guardar en el historial const logEntry = { city, latitude, longitude, timestamp: new Date().toISOString(), temp: weatherData.current.temperature_2m }; await writeFile('history.json', JSON.stringify(logEntry) + '\n', { flag: 'a' }); // Paso 4: Simplificar y devolver los datos clave const simplifiedData = { city_searched: city, current_temperature_c: weatherData.current.temperature_2m, relative_humidity_percent: weatherData.current.relative_humidity_2m, weather_code: weatherData.current.weather_code, }; return { content: [{ type: "text", text: JSON.stringify(simplifiedData, null, 2) }] }; } catch (error) { let errorMessage = "An unknown error occurred."; if (error instanceof Error) { errorMessage = error.message; } else if (typeof error === 'string') { errorMessage = error; } return { content: [{ type: "text", text: `Error fetching weather data: ${errorMessage}` }] }; } } ); // --- HERRAMIENTA 2: OBTENER HISTORIAL --- server.tool( 'get-history', 'Tool to retrieve the last 5 cities queried for weather information, useful for context.', {}, async() => { try { // Leer el contenido del archivo history.json const data = await readFile('history.json', 'utf-8'); // Procesar y obtener las últimas 5 entradas const lines = data.trim().split('\n').filter(line => line.length > 0); const recentHistory = lines.slice(-5); const historyString = recentHistory.join('\n'); return { content: [{ type: "text", text: `Recent weather query history:\n${historyString}` }] }; } catch (error) { // Manejar si el archivo aún no existe (ENOENT) if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') { return { content: [{ type: "text", text: "No previous weather query history found yet. Ask for the weather in a city first to populate the history." }] }; } let errorMessage = "An error occurred reading the history file."; if (error instanceof Error) { errorMessage = error.message; } return { content: [{ type: "text", text: `Error reading history: ${errorMessage}` }] }; } } ); // --- RECURSO: CÓDIGOS DE CLIMA (Corrección final) --- server.resource( 'weather-codes', // 1. name: string async () => { // 2. readCallback: Función que lee y devuelve el contenido try { // Leemos el contenido del archivo weather-codes.json const content = await readFile('weather-codes.json', 'utf-8'); return { description: 'WMO weather codes mapping for text descriptions.', content: [{ type: 'text', text: content // Devolvemos el contenido leído }] }; } catch (error) { // Devolvemos error si no se encuentra el archivo return { description: 'Error loading WMO codes.', content: [{ type: 'text', text: `Error: weather-codes.json could not be loaded.` }] }; } } ); // --- CONFIGURACIÓN DE COMUNICACIÓN --- const transport = new StdioServerTransport(); server.connect(transport);