Skip to main content
Glama
index.ts8.01 kB
import fetch from "node-fetch"; // Types matching SDK 1.0.1 interface Tool { name: string; description: string; inputSchema: any; } // Enable debug logging const DEBUG = process.env.DEBUG === 'true'; function debugLog(...args: any[]) { if (DEBUG) { console.error('[DEBUG]', ...args); } } // Export TOOLS array for use by the main server export const TOOLS: Tool[] = [ { name: "get_notams", description: "Retrieves NOTAMs based on specified filters", inputSchema: { type: "object", properties: { responseFormat: { type: "string", enum: ["aixm", "geoJson", "aidap"], default: "geoJson", description: "Response format for NOTAM data" }, icaoLocation: { type: "string", description: "The ICAO location criteria (e.g., 'KIAD' for Dulles International Airport)" }, domesticLocation: { type: "string", description: "The domestic location criteria (e.g., 'IAD' for Dulles International Airport)" }, notamType: { type: "string", enum: ["N", "R", "C"], description: "The NOTAM type: 'N' for New, 'R' for Replaced, 'C' for Canceled" }, classification: { type: "string", enum: ["INTL", "MIL", "DOM", "LMIL", "FDC"], description: "The NOTAM classification" }, notamNumber: { type: "string", description: "The NOTAM number (e.g., 'CK0000/01')" }, effectiveStartDate: { type: "string", description: "The effective start date" }, effectiveEndDate: { type: "string", description: "The effective end date" }, featureType: { type: "string", enum: [ "RWY", "TWY", "APRON", "AD", "OBST", "NAV", "COM", "SVC", "AIRSPACE", "ODP", "SID", "STAR", "CHART", "DATA", "DVA", "IAP", "VFP", "ROUTE", "SPECIAL", "SECURITY", "MILITARY", "INTERNATIONAL" ], description: "The feature type filter" }, locationLongitude: { type: "number", description: "The location longitude (e.g., -151.24)" }, locationLatitude: { type: "number", description: "The location latitude (e.g., 60.57)" }, locationRadius: { type: "number", description: "The location radius in nautical miles (max: 100)" }, lastUpdatedDate: { type: "number", description: "The last update date" }, sortBy: { type: "string", enum: [ "icaoLocation", "domesticLocation", "notamType", "notamNumber", "effectiveStartDate", "effectiveEndDate", "featureType" ], description: "The field to sort results by" }, sortOrder: { type: "string", enum: ["Asc", "Desc"], description: "The sort order" }, pageSize: { type: "number", default: 50, description: "The page size (max: 1000)" }, pageNum: { type: "number", default: 1, description: "The page number" }, }, } } ]; /** * Handles NOTAM requests */ async function handleNotams( responseFormat?: string, icaoLocation?: string, domesticLocation?: string, notamType?: string, classification?: string, notamNumber?: string, effectiveStartDate?: string, effectiveEndDate?: string, featureType?: string, locationLongitude?: number, locationLatitude?: number, locationRadius?: number, lastUpdatedDate?: number, sortBy?: string, sortOrder?: string, pageSize?: number, pageNum?: number, ) { // Set default format if not provided responseFormat = responseFormat || 'geoJson'; // Construct the URL with query parameters const baseUrl = 'https://external-api.faa.gov/notamapi/v1/notams'; const urlParams = new URLSearchParams(); // Add parameters to URL if they exist if (responseFormat) urlParams.append('responseFormat', responseFormat); if (icaoLocation) urlParams.append('icaoLocation', icaoLocation); if (domesticLocation) urlParams.append('domesticLocation', domesticLocation); if (notamType) urlParams.append('notamType', notamType); if (classification) urlParams.append('classification', classification); if (notamNumber) urlParams.append('notamNumber', notamNumber); if (effectiveStartDate) urlParams.append('effectiveStartDate', effectiveStartDate); if (effectiveEndDate) urlParams.append('effectiveEndDate', effectiveEndDate); if (featureType) urlParams.append('featureType', featureType); if (locationLongitude !== undefined) urlParams.append('locationLongitude', locationLongitude.toString()); if (locationLatitude !== undefined) urlParams.append('locationLatitude', locationLatitude.toString()); if (locationRadius !== undefined) urlParams.append('locationRadius', locationRadius.toString()); if (lastUpdatedDate !== undefined) urlParams.append('lastUpdatedDate', lastUpdatedDate.toString()); if (sortBy) urlParams.append('sortBy', sortBy); if (sortOrder) urlParams.append('sortOrder', sortOrder); if (pageSize !== undefined) urlParams.append('pageSize', pageSize.toString()); if (pageNum !== undefined) urlParams.append('pageNum', pageNum.toString()); const url = `${baseUrl}?${urlParams.toString()}`; // Check if required auth credentials are provided if (!process.env.FAA_CLIENT_ID || !process.env.FAA_CLIENT_SECRET) { throw new Error('Client ID and Client Secret are required for NOTAM API authentication'); } // Make the request with authentication headers const response = await fetch(url, { method: 'GET', headers: { 'Accept': 'application/json', 'client_id': process.env.FAA_CLIENT_ID, 'client_secret': process.env.FAA_CLIENT_SECRET } }); if (!response.ok) { const errorText = await response.text(); return { content: [ { type: "text", text: `NOTAM API Error (${response.status}): ${errorText}` } ], isError: true } } const data = await response.text(); return { content: [ { type: "text", text: data } ], isError: false }; } export async function handleToolCall(toolName: string, args: any) { debugLog('Received CallTool request:', { name: toolName, args }); try { switch (toolName) { case "get_notams": { const { responseFormat, icaoLocation, domesticLocation, notamType, classification, notamNumber, effectiveStartDate, effectiveEndDate, featureType, locationLongitude, locationLatitude, locationRadius, lastUpdatedDate, sortBy, sortOrder, pageSize, pageNum, } = args; return await handleNotams( responseFormat, icaoLocation, domesticLocation, notamType, classification, notamNumber, effectiveStartDate, effectiveEndDate, featureType, locationLongitude, locationLatitude, locationRadius, lastUpdatedDate, sortBy, sortOrder, pageSize, pageNum, ); } default: debugLog('Unknown tool:', toolName); return { content: [{ type: "text", text: `Unknown tool: ${toolName}` }], isError: true }; } } catch (error) { debugLog('Error handling tool call:', error); return { content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } }

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/blevinstein/aviation-mcp'

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