@albertmcp/mcp 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +225 -0
  2. package/package.json +43 -0
package/dist/index.js ADDED
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env node
2
+ // Ref: https://modelcontextprotocol.io/quickstart
3
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
6
+ import { z } from "zod";
7
+ const NWS_API_BASE = "https://api.weather.gov";
8
+ const USER_AGENT = "weather-app/1.0";
9
+ // Define Zod schemas for validation
10
+ const AlertsArgumentsSchema = z.object({
11
+ state: z.string().length(2),
12
+ });
13
+ const ForecastArgumentsSchema = z.object({
14
+ latitude: z.number().min(-90).max(90),
15
+ longitude: z.number().min(-180).max(180),
16
+ });
17
+ // Create server instance
18
+ const server = new Server({
19
+ name: "weather",
20
+ version: "1.0.0",
21
+ }, {
22
+ capabilities: {
23
+ tools: {},
24
+ },
25
+ });
26
+ // List available tools
27
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
28
+ return {
29
+ tools: [
30
+ {
31
+ name: "get-alerts",
32
+ description: "Get weather alerts for a US state",
33
+ inputSchema: {
34
+ type: "object",
35
+ properties: {
36
+ state: {
37
+ type: "string",
38
+ description: "Two-letter US state code (e.g. CA, NY)",
39
+ },
40
+ },
41
+ required: ["state"],
42
+ },
43
+ },
44
+ {
45
+ name: "get-forecast",
46
+ description: "Get weather forecast for a location in the US",
47
+ inputSchema: {
48
+ type: "object",
49
+ properties: {
50
+ latitude: {
51
+ type: "number",
52
+ description: "Latitude of the location",
53
+ },
54
+ longitude: {
55
+ type: "number",
56
+ description: "Longitude of the location",
57
+ },
58
+ },
59
+ required: ["latitude", "longitude"],
60
+ },
61
+ },
62
+ ],
63
+ };
64
+ });
65
+ // Helper function for making NWS API requests
66
+ async function makeNWSRequest(url) {
67
+ const headers = {
68
+ "User-Agent": USER_AGENT,
69
+ Accept: "application/geo+json",
70
+ };
71
+ try {
72
+ const response = await fetch(url, { headers });
73
+ if (!response.ok) {
74
+ throw new Error(`HTTP error! status: ${response.status}`);
75
+ }
76
+ return (await response.json());
77
+ }
78
+ catch (error) {
79
+ console.error("Error making NWS request:", error);
80
+ return null;
81
+ }
82
+ }
83
+ // Format alert data
84
+ function formatAlert(feature) {
85
+ const props = feature.properties;
86
+ return [
87
+ `Event: ${props.event || "Unknown"}`,
88
+ `Area: ${props.areaDesc || "Unknown"}`,
89
+ `Severity: ${props.severity || "Unknown"}`,
90
+ `Status: ${props.status || "Unknown"}`,
91
+ `Headline: ${props.headline || "No headline"}`,
92
+ "---",
93
+ ].join("\n");
94
+ }
95
+ // Handle tool execution
96
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
97
+ const { name, arguments: args } = request.params;
98
+ try {
99
+ if (name === "get-alerts") {
100
+ const { state } = AlertsArgumentsSchema.parse(args);
101
+ const stateCode = state.toUpperCase();
102
+ const alertsUrl = `${NWS_API_BASE}/alerts?area=${stateCode}`;
103
+ const alertsData = await makeNWSRequest(alertsUrl);
104
+ if (!alertsData) {
105
+ return {
106
+ content: [
107
+ {
108
+ type: "text",
109
+ text: "Failed to retrieve alerts data",
110
+ },
111
+ ],
112
+ };
113
+ }
114
+ const features = alertsData.features || [];
115
+ if (features.length === 0) {
116
+ return {
117
+ content: [
118
+ {
119
+ type: "text",
120
+ text: `No active alerts for ${stateCode}`,
121
+ },
122
+ ],
123
+ };
124
+ }
125
+ const formattedAlerts = features.map(formatAlert).slice(0, 20); // only take the first 20 alerts;
126
+ const alertsText = `Active alerts for ${stateCode}:\n\n${formattedAlerts.join("\n")}`;
127
+ return {
128
+ content: [
129
+ {
130
+ type: "text",
131
+ text: alertsText,
132
+ },
133
+ ],
134
+ };
135
+ }
136
+ else if (name === "get-forecast") {
137
+ const { latitude, longitude } = ForecastArgumentsSchema.parse(args);
138
+ // Get grid point data
139
+ const pointsUrl = `${NWS_API_BASE}/points/${latitude.toFixed(4)},${longitude.toFixed(4)}`;
140
+ const pointsData = await makeNWSRequest(pointsUrl);
141
+ if (!pointsData) {
142
+ return {
143
+ content: [
144
+ {
145
+ type: "text",
146
+ 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).`,
147
+ },
148
+ ],
149
+ };
150
+ }
151
+ const forecastUrl = pointsData.properties?.forecast;
152
+ if (!forecastUrl) {
153
+ return {
154
+ content: [
155
+ {
156
+ type: "text",
157
+ text: "Failed to get forecast URL from grid point data",
158
+ },
159
+ ],
160
+ };
161
+ }
162
+ // Get forecast data
163
+ const forecastData = await makeNWSRequest(forecastUrl);
164
+ if (!forecastData) {
165
+ return {
166
+ content: [
167
+ {
168
+ type: "text",
169
+ text: "Failed to retrieve forecast data",
170
+ },
171
+ ],
172
+ };
173
+ }
174
+ const periods = forecastData.properties?.periods || [];
175
+ if (periods.length === 0) {
176
+ return {
177
+ content: [
178
+ {
179
+ type: "text",
180
+ text: "No forecast periods available",
181
+ },
182
+ ],
183
+ };
184
+ }
185
+ // Format forecast periods
186
+ const formattedForecast = periods.map((period) => [
187
+ `${period.name || "Unknown"}:`,
188
+ `Temperature: ${period.temperature || "Unknown"}°${period.temperatureUnit || "F"}`,
189
+ `Wind: ${period.windSpeed || "Unknown"} ${period.windDirection || ""}`,
190
+ `${period.shortForecast || "No forecast available"}`,
191
+ "---",
192
+ ].join("\n"));
193
+ const forecastText = `Forecast for ${latitude}, ${longitude}:\n\n${formattedForecast.join("\n")}`;
194
+ return {
195
+ content: [
196
+ {
197
+ type: "text",
198
+ text: forecastText,
199
+ },
200
+ ],
201
+ };
202
+ }
203
+ else {
204
+ throw new Error(`Unknown tool: ${name}`);
205
+ }
206
+ }
207
+ catch (error) {
208
+ if (error instanceof z.ZodError) {
209
+ throw new Error(`Invalid arguments: ${error.errors
210
+ .map((e) => `${e.path.join(".")}: ${e.message}`)
211
+ .join(", ")}`);
212
+ }
213
+ throw error;
214
+ }
215
+ });
216
+ // Start the server
217
+ async function main() {
218
+ const transport = new StdioServerTransport();
219
+ await server.connect(transport);
220
+ console.error("Weather MCP Server running on stdio");
221
+ }
222
+ main().catch((error) => {
223
+ console.error("Fatal error in main():", error);
224
+ process.exit(1);
225
+ });
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@albertmcp/mcp",
3
+ "version": "0.1.3",
4
+ "description": "MCP server for weather forecast and severe weather alerts in the US",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "modelcontextprotocol",
8
+ "mcp",
9
+ "mcp-server",
10
+ "weather"
11
+ ],
12
+ "author": "",
13
+ "type": "module",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/albertmcp/mcp.git"
17
+ },
18
+ "engines": {
19
+ "node": ">=18"
20
+ },
21
+ "bin": {
22
+ "mcp-server-weather": "dist/index.js"
23
+ },
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "scripts": {
28
+ "build": "tsc && shx chmod +x dist/*.js",
29
+ "watch": "tsc --watch",
30
+ "clean": "git clean -fdxn -e .env && read -p 'OK?' && git clean -fdx -e .env",
31
+ "do-publish": "npm run clean && npm install && npm publish --access=public",
32
+ "publish-dry-run": "npm run clean && npm install && npm publish --access=public --dry-run"
33
+ },
34
+ "dependencies": {
35
+ "@modelcontextprotocol/sdk": "^1.25.2",
36
+ "zod": "^3.24.1"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^22.19.7",
40
+ "shx": "^0.3.4",
41
+ "typescript": "^5.7.2"
42
+ }
43
+ }