Skip to main content
Glama

TypeScript MCP Server Template

by dhinojosac
weatherPlugin.ts6 kB
import { FastifyPluginAsync } from 'fastify'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { WeatherForecastSchema, WeatherAlertsSchema, validateToolArgs, type WeatherForecastArgs, type WeatherAlertsArgs, } from '../schemas/toolSchemas.js'; /** * Weather plugin demonstrating Zod validation for larger MCP projects * Shows how to organize tools by domain/plugin */ export function registerWeatherTools(server: McpServer) { // Weather forecast tool with Zod validation server.registerTool( 'getWeatherForecast', { title: 'Get Weather Forecast', description: 'Get weather forecast for a specific location using coordinates', }, async (args: { [x: string]: any }) => { const { latitude, longitude }: WeatherForecastArgs = validateToolArgs( WeatherForecastSchema, args ); // Simulate weather API call (replace with actual API) const forecast = await simulateWeatherAPI(latitude, longitude); return { content: [ { type: 'text', text: `Weather forecast for coordinates (${latitude}, ${longitude}):\n${forecast}`, }, ], }; } ); // Weather alerts tool with Zod validation server.registerTool( 'getWeatherAlerts', { title: 'Get Weather Alerts', description: 'Get active weather alerts for a US state', }, async (args: { [x: string]: any }) => { const { state }: WeatherAlertsArgs = validateToolArgs( WeatherAlertsSchema, args ); // Simulate alerts API call (replace with actual API) const alerts = await simulateAlertsAPI(); return { content: [ { type: 'text', text: `Weather alerts for ${state}:\n${alerts}`, }, ], }; } ); } /** * Simulate weather API call * In a real implementation, this would call an actual weather service */ async function simulateWeatherAPI( latitude: number, longitude: number ): Promise<string> { // Simulate API delay await new Promise(resolve => setTimeout(resolve, 100)); // Generate mock forecast based on coordinates const temperature = Math.round( 20 + latitude * 0.5 + (Math.random() * 10 - 5) ); const conditions = ['Sunny', 'Cloudy', 'Rainy', 'Partly Cloudy']; const condition = conditions[Math.floor(Math.random() * conditions.length)]; return ` 🌤️ Current Conditions: ${condition} 🌡️ Temperature: ${temperature}°C Location: ${latitude.toFixed(4)}, ${longitude.toFixed(4)} ⏰ Updated: ${new Date().toLocaleString()} `.trim(); } /** * Simulate weather alerts API call * In a real implementation, this would call an actual alerts service */ async function simulateAlertsAPI(): Promise<string> { // Simulate API delay await new Promise(resolve => setTimeout(resolve, 100)); // Generate mock alerts based on state const alerts = [ 'Severe Thunderstorm Warning', 'Flash Flood Watch', 'Heat Advisory', 'Winter Weather Advisory', ]; const hasAlerts = Math.random() > 0.5; if (!hasAlerts) { return '✅ No active weather alerts for this state.'; } const activeAlerts = alerts.filter(() => Math.random() > 0.7).slice(0, 2); if (activeAlerts.length === 0) { return '✅ No active weather alerts for this state.'; } return activeAlerts.map(alert => `⚠️ ${alert}`).join('\n'); } /** * Fastify plugin for weather-related REST endpoints * Demonstrates how to expose weather data via traditional REST API */ const weatherPlugin: FastifyPluginAsync = async fastify => { // GET /weather/forecast?lat=40.7128&lng=-74.0060 fastify.get( '/weather/forecast', { schema: { querystring: { type: 'object', properties: { lat: { type: 'number', minimum: -90, maximum: 90 }, lng: { type: 'number', minimum: -180, maximum: 180 }, }, required: ['lat', 'lng'], }, }, }, async (request, reply) => { const { lat, lng } = request.query as { lat: number; lng: number }; try { // Use the same validation as the MCP tool const args = { latitude: lat, longitude: lng }; const { latitude, longitude }: WeatherForecastArgs = validateToolArgs( WeatherForecastSchema, args ); const forecast = await simulateWeatherAPI(latitude, longitude); return { forecast, coordinates: { latitude, longitude }, timestamp: new Date().toISOString(), }; } catch (error) { return reply.status(400).send({ error: 'Invalid coordinates', message: error instanceof Error ? error.message : 'Unknown error', }); } } ); // GET /weather/alerts/:state fastify.get<{ Params: { state: string } }>( '/weather/alerts/:state', { schema: { params: { type: 'object', properties: { state: { type: 'string', pattern: '^[A-Z]{2}$', description: 'Two-letter US state code', }, }, required: ['state'], }, }, }, async (request, reply) => { const { state } = request.params; try { // Use the same validation as the MCP tool const args = { state }; const { state: validatedState }: WeatherAlertsArgs = validateToolArgs( WeatherAlertsSchema, args ); const alerts = await simulateAlertsAPI(); return { alerts, state: validatedState, timestamp: new Date().toISOString(), }; } catch (error) { return reply.status(400).send({ error: 'Invalid state code', message: error instanceof Error ? error.message : 'Unknown error', }); } } ); }; export default weatherPlugin;

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/dhinojosac/calendar-mcp'

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