Skip to main content
Glama
x8yuv
by x8yuv
index.http.js7.64 kB
import express from 'express'; import cors from 'cors'; import { z } from 'zod'; import { getAlerts, getForecast, alertsSchema, forecastSchema } from './weather.js'; const app = express(); // CORS configuration for thesys.dev app.use(cors({ origin: '*', methods: ['GET', 'POST', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'], credentials: false })); app.use(express.json()); // Health check endpoint app.get('/health', (_req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString(), service: 'weather-mcp-server' }); }); // MCP protocol endpoints app.get('/mcp/info', (_req, res) => { res.json({ name: 'weather', version: '1.0.0', description: 'Weather MCP Server providing NWS weather data', capabilities: { tools: true, resources: false } }); }); app.get('/mcp/tools', (_req, res) => { res.json({ tools: [ { name: 'get_alerts', description: 'Get weather alerts for a state', inputSchema: { type: 'object', properties: { state: { type: 'string', minLength: 2, maxLength: 2, description: 'Two-letter state code (e.g. CA, NY)' } }, required: ['state'] } }, { name: 'get_forecast', description: 'Get weather forecast for a location', inputSchema: { type: 'object', properties: { latitude: { type: 'number', minimum: -90, maximum: 90, description: 'Latitude of the location' }, longitude: { type: 'number', minimum: -180, maximum: 180, description: 'Longitude of the location' } }, required: ['latitude', 'longitude'] } } ] }); }); // SSE endpoint for thesys.dev app.get('/sse', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'Cache-Control' }); // Send server info res.write(`data: ${JSON.stringify({ type: 'server_info', name: 'weather', version: '1.0.0', tools: ['get_alerts', 'get_forecast'] })}\n\n`); // Keep connection alive const keepAlive = setInterval(() => { res.write(`data: ${JSON.stringify({ type: 'ping', timestamp: Date.now() })}\n\n`); }, 30000); req.on('close', () => { clearInterval(keepAlive); }); }); app.post('/mcp/call', async (req, res) => { try { const { tool, params = {} } = req.body || {}; if (!tool) { return res.status(400).json({ error: 'Missing tool name', code: 'MISSING_TOOL' }); } console.log(`MCP call: ${tool}`, params); switch (tool) { case 'get_alerts': { try { const validatedParams = alertsSchema.parse(params); const result = await getAlerts(validatedParams.state); return res.json(result); } catch (error) { if (error instanceof z.ZodError) { return res.status(400).json({ error: 'Invalid parameters for get_alerts', details: error.errors, code: 'VALIDATION_ERROR' }); } throw error; } } case 'get_forecast': { try { const validatedParams = forecastSchema.parse(params); const result = await getForecast(validatedParams.latitude, validatedParams.longitude); return res.json(result); } catch (error) { if (error instanceof z.ZodError) { return res.status(400).json({ error: 'Invalid parameters for get_forecast', details: error.errors, code: 'VALIDATION_ERROR' }); } throw error; } } default: return res.status(400).json({ error: `Unknown tool: ${tool}`, code: 'UNKNOWN_TOOL', availableTools: ['get_alerts', 'get_forecast'] }); } } catch (error) { console.error('Error in MCP call:', error); return res.status(500).json({ error: 'Internal server error', code: 'INTERNAL_ERROR', message: error instanceof Error ? error.message : 'Unknown error' }); } }); // Root endpoint with MCP server info app.get('/', (_req, res) => { res.json({ name: 'Weather MCP Server', version: '1.0.0', description: 'MCP server for weather data using National Weather Service API', protocol: 'MCP JSON-RPC 2.0', endpoints: { health: '/health', mcp: '/mcp', sse: '/mcp/sse', // Legacy REST endpoints info: '/mcp/info', tools: '/mcp/tools', call: '/mcp/call' }, usage: { mcp_jsonrpc: { method: 'POST', url: '/mcp', body: { jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: 'get_forecast', arguments: { latitude: 40.7128, longitude: -74.0060 } } } }, legacy_rest: { method: 'POST', url: '/mcp/call', body: { tool: 'get_forecast', params: { latitude: 40.7128, longitude: -74.0060 } } } } }); }); // Error handling middleware app.use((error, _req, res, _next) => { console.error('Unhandled error:', error); res.status(500).json({ error: 'Internal server error', code: 'INTERNAL_ERROR' }); }); // 404 handler app.use((_req, res) => { res.status(404).json({ error: 'Endpoint not found', code: 'NOT_FOUND' }); }); const PORT = process.env.PORT || 3001; app.listen(Number(PORT), '0.0.0.0', () => { console.log(`Weather MCP HTTP Server running on port ${PORT}`); console.log(`Environment: ${process.env.NODE_ENV || 'development'}`); console.log(`Health check: /health`); console.log(`Tools list: /mcp/tools`); }); export default app;

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/x8yuv/MCPServer'

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