From 6baa02e22c67f600dd8800d1d9a4f5aad00acd76 Mon Sep 17 00:00:00 2001 From: MatMoul Date: Sun, 6 Jul 2025 19:37:21 +0200 Subject: [PATCH] With build --- .gitignore | 2 +- build/index.js | 165 ++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 3 + 3 files changed, 169 insertions(+), 1 deletion(-) create mode 100755 build/index.js diff --git a/.gitignore b/.gitignore index dd87e2d..6c54766 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ node_modules -build +#build diff --git a/build/index.js b/build/index.js new file mode 100755 index 0000000..682f32e --- /dev/null +++ b/build/index.js @@ -0,0 +1,165 @@ +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; +import { z } from "zod"; +const NWS_API_BASE = "https://api.weather.gov"; +const USER_AGENT = "weather-app/1.0"; +// Create server instance +const server = new McpServer({ + name: "weather", + version: "1.0.0", + capabilities: { + resources: {}, + tools: {}, + }, +}); +// Helper function for making NWS API requests +async function makeNWSRequest(url) { + const headers = { + "User-Agent": USER_AGENT, + Accept: "application/geo+json", + }; + try { + const response = await fetch(url, { headers }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return (await response.json()); + } + catch (error) { + console.error("Error making NWS request:", error); + return null; + } +} +// Format alert data +function formatAlert(feature) { + const props = feature.properties; + return [ + `Event: ${props.event || "Unknown"}`, + `Area: ${props.areaDesc || "Unknown"}`, + `Severity: ${props.severity || "Unknown"}`, + `Status: ${props.status || "Unknown"}`, + `Headline: ${props.headline || "No headline"}`, + "---", + ].join("\n"); +} +// Register weather tools +server.tool("get-alerts", "Get weather alerts for a state", { + state: z.string().length(2).describe("Two-letter state code (e.g. CA, NY)"), +}, async ({ state }) => { + const stateCode = state.toUpperCase(); + const alertsUrl = `${NWS_API_BASE}/alerts?area=${stateCode}`; + const alertsData = await makeNWSRequest(alertsUrl); + if (!alertsData) { + return { + content: [ + { + type: "text", + text: "Failed to retrieve alerts data", + }, + ], + }; + } + const features = alertsData.features || []; + if (features.length === 0) { + return { + content: [ + { + type: "text", + text: `No active alerts for ${stateCode}`, + }, + ], + }; + } + const formattedAlerts = features.map(formatAlert); + const alertsText = `Active alerts for ${stateCode}:\n\n${formattedAlerts.join("\n")}`; + return { + content: [ + { + type: "text", + text: alertsText, + }, + ], + }; +}); +server.tool("get-forecast", "Get weather forecast for a location", { + latitude: z.number().min(-90).max(90).describe("Latitude of the location"), + longitude: z + .number() + .min(-180) + .max(180) + .describe("Longitude of the location"), +}, async ({ latitude, longitude }) => { + // Get grid point data + const pointsUrl = `${NWS_API_BASE}/points/${latitude.toFixed(4)},${longitude.toFixed(4)}`; + const pointsData = await makeNWSRequest(pointsUrl); + if (!pointsData) { + return { + content: [ + { + type: "text", + text: `Failed to retrieve grid point data for coordinates: ${latitude}, ${longitude}. This location may not be supported by the NWS API (only US locations are supported).`, + }, + ], + }; + } + const forecastUrl = pointsData.properties?.forecast; + if (!forecastUrl) { + return { + content: [ + { + type: "text", + text: "Failed to get forecast URL from grid point data", + }, + ], + }; + } + // Get forecast data + const forecastData = await makeNWSRequest(forecastUrl); + if (!forecastData) { + return { + content: [ + { + type: "text", + text: "Failed to retrieve forecast data", + }, + ], + }; + } + const periods = forecastData.properties?.periods || []; + if (periods.length === 0) { + return { + content: [ + { + type: "text", + text: "No forecast periods available", + }, + ], + }; + } + // Format forecast periods + const formattedForecast = periods.map((period) => [ + `${period.name || "Unknown"}:`, + `Temperature: ${period.temperature || "Unknown"}°${period.temperatureUnit || "F"}`, + `Wind: ${period.windSpeed || "Unknown"} ${period.windDirection || ""}`, + `${period.shortForecast || "No forecast available"}`, + "---", + ].join("\n")); + const forecastText = `Forecast for ${latitude}, ${longitude}:\n\n${formattedForecast.join("\n")}`; + return { + content: [ + { + type: "text", + text: forecastText, + }, + ], + }; +}); +async function main() { + const transport = new StdioServerTransport(); + await server.connect(transport); + console.error("Weather MCP Server running on stdio"); +} +main().catch((error) => { + console.error("Fatal error in main():", error); + process.exit(1); +}); diff --git a/package-lock.json b/package-lock.json index 8887a7e..1b21eb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,9 @@ "@modelcontextprotocol/sdk": "^1.13.0", "zod": "^3.25.67" }, + "bin": { + "mcp": "build/index.js" + }, "devDependencies": { "@types/node": "^24.0.3", "typescript": "^5.8.3"