{"version":3,"sources":["jsdelivr-header.js","/npm/flightaware-mcp@0.2.0/lib/mcp-server.js"],"names":[],"mappings":"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","file":"/npm/flightaware-mcp@0.2.0/lib/mcp-server.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/flightaware-mcp@0.2.0/lib/mcp-server.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","const net = require('net');\nconst WebSocket = require('ws');\nconst AeroApi = require('./aeroapi');\nconst logger = require('./logger');\n\n// Import handlers\nconst getFlightByIdent = require('./handlers/getFlightByIdent');\nconst getFlightsForAirport = require('./handlers/getFlightsForAirport');\nconst getAircraftByTail = require('./handlers/getAircraftByTail');\nconst getAirportsByRegion = require('./handlers/getAirportsByRegion');\nconst getFlightDetails = require('./handlers/getFlightDetails');\n\nclass McpServer {\n  constructor(options) {\n    this.port = options.port || 8080;\n    this.mode = (options.mode || 'tcp').toLowerCase();\n    this.server = null;\n    this.clients = new Set();\n    this.requestTimeout = options.requestTimeout || 30000; // 30 second default timeout\n    this.debug = options.debug || process.env.DEBUG === 'true';\n    \n    // Set logger level based on debug flag\n    if (this.debug) {\n      process.env.LOG_LEVEL = 'debug';\n    }\n    \n    logger.info(`MCP Server initializing (mode: ${this.mode}, timeout: ${this.requestTimeout}ms)`);\n    \n    // Initialize AeroAPI client with the same timeout\n    this.aeroApi = new AeroApi(options.aeroapiKey, {\n      timeout: this.requestTimeout\n    });\n    \n    // Method handlers mapping\n    this.handlers = {\n      getFlightByIdent: getFlightByIdent,\n      getFlightsForAirport: getFlightsForAirport,\n      getAircraftByTail: getAircraftByTail,\n      getAirportsByRegion: getAirportsByRegion,\n      getFlightDetails: getFlightDetails\n    };\n  }\n\n  async start() {\n    if (this.mode === 'tcp') {\n      return this._startTcpServer();\n    } else if (this.mode === 'ws') {\n      return this._startWebSocketServer();\n    } else {\n      throw new Error(`Unsupported server mode: ${this.mode}`);\n    }\n  }\n\n  async stop() {\n    if (!this.server) {\n      return;\n    }\n\n    // Close all client connections\n    for (const client of this.clients) {\n      if (this.mode === 'tcp') {\n        client.end();\n      } else if (this.mode === 'ws') {\n        client.close();\n      }\n    }\n\n    // Close the server\n    return new Promise((resolve, reject) => {\n      this.server.close(err => {\n        if (err) {\n          reject(err);\n        } else {\n          this.server = null;\n          resolve();\n        }\n      });\n    });\n  }\n\n  _startTcpServer() {\n    return new Promise((resolve, reject) => {\n      this.server = net.createServer(socket => {\n        const clientId = `tcp:${socket.remoteAddress}:${socket.remotePort}`;\n        this.clients.add(socket);\n        socket._mcp_client_id = clientId; // Attach client ID to socket\n        \n        // Set socket timeout\n        socket.setTimeout(this.requestTimeout);\n        \n        logger.debug(`TCP client connected: ${clientId}`);\n        \n        let buffer = '';\n        \n        socket.on('data', data => {\n          buffer += data.toString();\n          \n          // Try to parse complete JSON messages\n          try {\n            // Simple approach: one JSON message per line\n            const messages = buffer.split('\\n');\n            buffer = messages.pop(); // Keep the last incomplete message in buffer\n            \n            for (const message of messages) {\n              if (message.trim()) {\n                this._handleMessage(JSON.parse(message), (response) => {\n                  socket.write(JSON.stringify(response) + '\\n');\n                });\n              }\n            }\n          } catch (err) {\n            // Incomplete or invalid JSON, continue buffering\n          }\n        });\n\n        socket.on('close', () => {\n          logger.debug(`TCP client disconnected: ${socket._mcp_client_id}`);\n          this.clients.delete(socket);\n        });\n\n        socket.on('error', err => {\n          logger.error(`Socket error for ${socket._mcp_client_id}`, err);\n          this.clients.delete(socket);\n        });\n        \n        socket.on('timeout', () => {\n          logger.warn(`Socket timeout for ${socket._mcp_client_id}`);\n          \n          // Don't end the connection, just reset the timeout and send an error\n          socket.setTimeout(0); // Disable timeout temporarily\n          \n          // Send timeout error response if there's a pending request\n          const timeoutResponse = {\n            id: null, // We don't know the request ID\n            error: {\n              code: -32001,\n              message: 'Request timed out'\n            }\n          };\n          \n          try {\n            socket.write(JSON.stringify(timeoutResponse) + '\\n');\n            // Reset the timeout\n            socket.setTimeout(this.requestTimeout);\n          } catch (err) {\n            logger.error(`Failed to send timeout response to ${socket._mcp_client_id}`, err);\n            this.clients.delete(socket);\n            socket.destroy();\n          }\n        });\n      });\n\n      this.server.on('error', err => {\n        reject(err);\n      });\n\n      this.server.listen(this.port, () => {\n        resolve();\n      });\n    });\n  }\n\n  _startWebSocketServer() {\n    return new Promise((resolve, reject) => {\n      try {\n        this.server = new WebSocket.Server({ \n          port: this.port,\n          // Set WebSocket options\n          clientTracking: true,\n          perMessageDeflate: false,\n          maxPayload: 100 * 1024 * 1024, // 100MB\n          // Set ping interval and timeout\n          pingInterval: Math.floor(this.requestTimeout / 3),\n          pingTimeout: Math.floor(this.requestTimeout / 2)\n        });\n        \n        this.server.on('connection', (ws, req) => {\n          const clientId = `ws:${req.socket.remoteAddress}:${req.socket.remotePort}`;\n          this.clients.add(ws);\n          ws._mcp_client_id = clientId;\n          \n          logger.debug(`WebSocket client connected: ${clientId}`);\n          \n          // Keep track of last ping time\n          ws._lastPingTime = Date.now();\n          \n          ws.on('message', message => {\n            try {\n              const request = JSON.parse(message.toString());\n              logger.debug(`Processing WebSocket request: ${JSON.stringify(request)}`);\n              \n              this._handleMessage(request, (response) => {\n                if (ws.readyState === WebSocket.OPEN) {\n                  ws.send(JSON.stringify(response));\n                  logger.debug(`Sent WebSocket response for request ${request.id}`);\n                } else {\n                  logger.warn(`Cannot send response to ${ws._mcp_client_id}, socket not open`);\n                }\n              });\n            } catch (err) {\n              logger.error('Error processing WebSocket message:', err);\n              if (ws.readyState === WebSocket.OPEN) {\n                ws.send(JSON.stringify({\n                  id: null,\n                  error: {\n                    code: -32700,\n                    message: 'Parse error'\n                  }\n                }));\n              }\n            }\n          });\n\n          ws.on('close', (code, reason) => {\n            logger.debug(`WebSocket client disconnected: ${ws._mcp_client_id}, code: ${code}, reason: ${reason || 'No reason provided'}`);\n            this.clients.delete(ws);\n          });\n\n          ws.on('error', err => {\n            logger.error(`WebSocket error for ${ws._mcp_client_id}:`, err);\n            this.clients.delete(ws);\n          });\n          \n          // Add ping/pong for WebSocket timeout detection\n          const pingInterval = setInterval(() => {\n            if (ws.readyState === WebSocket.OPEN) {\n              const now = Date.now();\n              // Check if client hasn't responded to ping for too long\n              if (ws._lastPingTime && now - ws._lastPingTime > this.requestTimeout) {\n                logger.warn(`WebSocket client ${ws._mcp_client_id} ping timeout`);\n                \n                // Send timeout error response\n                if (ws.readyState === WebSocket.OPEN) {\n                  ws.send(JSON.stringify({\n                    id: null,\n                    error: {\n                      code: -32001,\n                      message: 'Request timed out'\n                    }\n                  }));\n                }\n                \n                // Terminate connection if it's been too long\n                if (now - ws._lastPingTime > 2 * this.requestTimeout) {\n                  logger.error(`Terminating unresponsive WebSocket client ${ws._mcp_client_id}`);\n                  ws.terminate();\n                  clearInterval(pingInterval);\n                  return;\n                }\n              }\n              \n              // Send ping\n              logger.debug(`Sending ping to ${ws._mcp_client_id}`);\n              ws.ping(() => {\n                // Ping callback\n                ws._lastPingTime = Date.now();\n              });\n            }\n          }, Math.floor(this.requestTimeout / 3));\n          \n          ws.on('pong', () => {\n            // Reset timeout on pong response\n            logger.debug(`Received pong from ${ws._mcp_client_id}`);\n            ws._lastPingTime = Date.now();\n          });\n          \n          ws.on('close', () => {\n            logger.debug(`Clearing ping interval for ${ws._mcp_client_id}`);\n            clearInterval(pingInterval);\n          });\n        });\n\n        this.server.on('error', err => {\n          reject(err);\n        });\n\n        this.server.on('listening', () => {\n          resolve();\n        });\n      } catch (err) {\n        reject(err);\n      }\n    });\n  }\n\n  async _handleMessage(request, sendResponse) {\n    const requestId = request.id || 'unknown';\n    const startTime = Date.now();\n    \n    // Log request\n    logger.debug(`Processing request ${requestId}: ${request.method}`, request.params);\n    \n    // Validate request format\n    if (!request.id || !request.method) {\n      logger.warn(`Invalid request: ${JSON.stringify(request)}`);\n      return sendResponse({\n        id: request.id || null,\n        error: {\n          code: -32600,\n          message: 'Invalid request'\n        }\n      });\n    }\n\n    // Find handler for the requested method\n    const handler = this.handlers[request.method];\n    if (!handler) {\n      logger.warn(`Method '${request.method}' not found`);\n      return sendResponse({\n        id: request.id,\n        error: {\n          code: -32601,\n          message: `Method '${request.method}' not found`\n        }\n      });\n    }\n\n    try {\n      // Create a timeout promise\n      const timeoutPromise = new Promise((_, reject) => {\n        const timeoutId = setTimeout(() => {\n          const timeoutMsg = `Request ${requestId} timed out after ${this.requestTimeout}ms`;\n          logger.warn(timeoutMsg);\n          const timeoutError = new Error('Request timed out');\n          timeoutError.code = -32001;\n          reject(timeoutError);\n        }, this.requestTimeout);\n        \n        // Ensure the timeout is cleared if the promise is fulfilled\n        timeoutPromise.cleanup = () => clearTimeout(timeoutId);\n      });\n\n      // Race the handler against the timeout\n      try {\n        const result = await Promise.race([\n          handler(this.aeroApi, request.params || {}),\n          timeoutPromise\n        ]);\n        \n        // Clean up the timeout\n        if (timeoutPromise.cleanup) {\n          timeoutPromise.cleanup();\n        }\n        \n        // Calculate execution time\n        const executionTime = Date.now() - startTime;\n        logger.debug(`Request ${requestId} completed in ${executionTime}ms`);\n        \n        // Send response\n        sendResponse({\n          id: request.id,\n          result\n        });\n      } catch (err) {\n        // Clean up the timeout\n        if (timeoutPromise.cleanup) {\n          timeoutPromise.cleanup();\n        }\n        \n        throw err; // Re-throw to be caught by the outer catch\n      }\n    } catch (err) {\n      const executionTime = Date.now() - startTime;\n      logger.error(`Error handling '${request.method}' (${executionTime}ms):`, err);\n      \n      // Format error response\n      sendResponse({\n        id: request.id,\n        error: {\n          code: err.code || 500,\n          message: err.message || 'Internal error'\n        }\n      });\n    }\n  }\n}\n\nmodule.exports = McpServer;"]}