Skip to main content
Glama
WeatherXM

WeatherXM Pro MCP Server

Official
by WeatherXM
index.ts10.6 kB
#!/usr/bin/env node import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import axios from 'axios'; import dotenv from 'dotenv'; import { z } from 'zod'; dotenv.config(); const API_KEY = process.env.WEATHERXMPRO_API_KEY; if (!API_KEY) { throw new Error('WEATHERXMPRO_API_KEY environment variable is required'); } const baseUrl = "https://pro.weatherxm.com/api/v1"; // Create an MCP server const server = new McpServer({ name: "weatherxm-pro-mcp-server", version: "0.5.0" }); // Create axios instance with API key const axiosInstance = axios.create({ baseURL: baseUrl, headers: { 'X-API-KEY': API_KEY } }); // Add MCP tool for getStationsNear server.tool( "get_stations_near", { lat: z.number().describe("Latitude of the center of the area"), lon: z.number().describe("Longitude of the center of the area"), radius: z.number().describe("Radius in meters for which stations are queried"), }, async ({ lat, lon, radius }) => { try { const response = await axiosInstance.get('/stations/near', { params: { lat, lon, radius }, }); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { if (axios.isAxiosError(error)) { return { content: [{ type: "text", text: `WeatherXM API error: ${error.response?.data.message ?? error.message}` }], isError: true, }; } throw error; } } ); // Add MCP tool for getStationsBounds server.tool( "get_stations_bounds", { min_lat: z.number().describe("Minimum latitude of the bounding box"), min_lon: z.number().describe("Minimum longitude of the bounding box"), max_lat: z.number().describe("Maximum latitude of the bounding box"), max_lon: z.number().describe("Maximum longitude of the bounding box"), }, async ({ min_lat, min_lon, max_lat, max_lon }) => { try { const response = await axiosInstance.get('/stations/bounds', { params: { min_lat, min_lon, max_lat, max_lon }, }); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { if (axios.isAxiosError(error)) { return { content: [{ type: "text", text: `WeatherXM API error: ${error.response?.data.message ?? error.message}` }], isError: true, }; } throw error; } } ); // Add MCP tool for getAllStations server.tool( "get_all_stations", {}, async () => { try { const response = await axiosInstance.get('/stations'); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { if (axios.isAxiosError(error)) { return { content: [{ type: "text", text: `WeatherXM API error: ${error.response?.data.message ?? error.message}` }], isError: true, }; } throw error; } } ); // Add MCP tool for getLatestObservation server.tool( "get_latest_observation", { station_id: z.string().describe("The unique identifier of the station"), }, async ({ station_id }) => { try { const response = await axiosInstance.get(`/stations/${station_id}/latest`); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { if (axios.isAxiosError(error)) { return { content: [{ type: "text", text: `WeatherXM API error: ${error.response?.data.message ?? error.message}` }], isError: true, }; } throw error; } } ); // Add MCP tool for getHistoricalObservations server.tool( "get_historical_observations", { station_id: z.string().describe("The unique identifier of the station"), date: z.string().describe("Date (YYYY-MM-DD) for historical observations"), }, async ({ station_id, date }) => { try { const response = await axiosInstance.get(`/stations/${station_id}/history`, { params: { date }, }); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { if (axios.isAxiosError(error)) { return { content: [{ type: "text", text: `WeatherXM API error: ${error.response?.data.message ?? error.message}` }], isError: true, }; } throw error; } } ); // Add MCP tool for searchCellsInRegion server.tool( "search_cells_in_region", { region_query: z.string().describe("The name of the region to search for cells"), }, async ({ region_query }) => { try { const response = await axiosInstance.get('/cells/search', { params: { query: region_query }, }); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { if (axios.isAxiosError(error)) { return { content: [{ type: "text", text: `WeatherXM API error: ${error.response?.data.message ?? error.message}` }], isError: true, }; } throw error; } } ); // Add MCP tool for getStationsInCell server.tool( "get_stations_in_cell", { cell_index: z.string().describe("The H3 index of the cell to return stations for"), }, async ({ cell_index }) => { try { const response = await axiosInstance.get(`/cells/${cell_index}/stations`); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { if (axios.isAxiosError(error)) { return { content: [{ type: "text", text: `WeatherXM API error: ${error.response?.data.message ?? error.message}` }], isError: true, }; } throw error; } } ); // Add MCP tool for getForecastForCell server.tool( "get_forecast_for_cell", { forecast_cell_index: z.string().describe("The H3 index of the cell to get forecast for"), forecast_from: z.string().describe("The first day for which to get forecast data (YYYY-MM-DD)"), forecast_to: z.string().describe("The last day for which to get forecast data (YYYY-MM-DD)"), forecast_include: z.enum(['daily', 'hourly']).describe('Types of forecast to include'), }, async ({ forecast_cell_index, forecast_from, forecast_to, forecast_include }) => { try { const response = await axiosInstance.get(`/cells/${forecast_cell_index}/forecast`, { params: { from: forecast_from, to: forecast_to, include: forecast_include, }, }); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { if (axios.isAxiosError(error)) { return { content: [{ type: "text", text: `WeatherXM API error: ${error.response?.data.message ?? error.message}` }], isError: true, }; } throw error; } } ); // Add MCP tool for getHyperlocalForecast server.tool( "get_hyperlocal_forecast", { station_id: z.string().describe("The station to get the forecast for."), variable: z.string().describe("The weather variable to get the forecast for."), timezone: z.string().optional().describe("The timezone to get forecast for. Defaults to station location timezone."), }, async ({ station_id, variable, timezone }) => { const allowedVariables = ["temperature", "humidity", "precipitation", "windSpeed", "windDirection"]; if (!allowedVariables.includes(variable)) { return { content: [{ type: "text", text: `Invalid variable provided: ${variable}. Allowed variables are: ${allowedVariables.join(", ")}` }], isError: true, }; } try { const response = await axiosInstance.get(`/stations/${station_id}/hyperlocal`, { params: { variable, timezone }, }); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { if (axios.isAxiosError(error)) { return { content: [{ type: "text", text: `WeatherXM API error: ${error.response?.data.message ?? error.message}` }], isError: true, }; } throw error; } } ); // Add MCP tool for getFactPerformance server.tool( "get_fact_performance", { station_id: z.string().describe("The station to get the forecast performance for."), variable: z.string().describe("The weather variable to get the forecast for."), }, async ({ station_id, variable }) => { const allowedVariables = ["temperature", "humidity", "precipitation", "windSpeed", "windDirection"]; if (!allowedVariables.includes(variable)) { return { content: [{ type: "text", text: `Invalid variable provided: ${variable}. Allowed variables are: ${allowedVariables.join(", ")}` }], isError: true, }; } try { const response = await axiosInstance.get(`/stations/${station_id}/fact/performance`, { params: { variable }, }); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { if (axios.isAxiosError(error)) { return { content: [{ type: "text", text: `WeatherXM API error: ${error.response?.data.message ?? error.message}` }], isError: true, }; } throw error; } } ); // Add MCP tool for getFactRanking server.tool( "get_fact_ranking", { station_id: z.string().describe("The station to get the forecast ranking for."), }, async ({ station_id }) => { try { const response = await axiosInstance.get(`/stations/${station_id}/fact/ranking`); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { if (axios.isAxiosError(error)) { return { content: [{ type: "text", text: `WeatherXM API error: ${error.response?.data.message ?? error.message}` }], isError: true, }; } throw error; } } ); // Start the server async function run() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('WeatherXM PRO MCP server running on stdio'); } run().catch(error => { console.error('Error running MCP server:', error); process.exit(1); });

Implementation Reference

Latest Blog Posts

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/WeatherXM/weatherxm-pro-mcp'

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