UNPKG

voyage-and-consumption-mcp-server

Version:

Voyage and consumption management server handling vessel voyages, fuel consumption, performance monitoring, and operational data with ERP access for data extraction

178 lines 7.34 kB
import { MongoClient } from 'mongodb'; import { config } from './config.js'; import { logger } from './logger.js'; // Global cache for company IMO numbers let companyImoNumbers = []; /** * Fetch company IMO numbers from the common_group_details collection * @param companyName - Name of the company to fetch IMO numbers for * @param companyDbUri - MongoDB connection URI for company database * @param companyDbName - MongoDB database name for company data * @returns Array of IMO numbers as strings */ export async function fetchCompanyImoNumbers(companyName, companyDbUri, companyDbName) { let client = null; try { logger.info(`Connecting to company database for IMO fetching: ${companyDbName}`); client = new MongoClient(companyDbUri); await client.connect(); const db = client.db(companyDbName); const collection = db.collection('common_group_details'); logger.info(`Fetching IMO numbers for company: ${companyName}`); const result = await collection.findOne({ groupName: companyName }, { projection: { imo: 1, imoList: 1, groupImoList: 1, _id: 0 } }); if (!result) { logger.warn(`No group details found for company: ${companyName}`); return []; } // Combine IMO numbers from all three fields const imoNumbers = []; if (result.imo) { imoNumbers.push(result.imo); } if (result.imoList && Array.isArray(result.imoList)) { imoNumbers.push(...result.imoList); } if (result.groupImoList && Array.isArray(result.groupImoList)) { imoNumbers.push(...result.groupImoList); } // Convert to strings and remove duplicates const uniqueImoStrings = [...new Set(imoNumbers.map(imo => String(imo)))]; logger.info(`Successfully fetched ${uniqueImoStrings.length} unique IMO numbers for company: ${companyName}`); logger.debug(`IMO numbers: ${uniqueImoStrings.slice(0, 10).join(', ')}${uniqueImoStrings.length > 10 ? '...' : ''}`); return uniqueImoStrings; } catch (error) { logger.error(`Failed to fetch IMO numbers for company ${companyName}:`, error.message); throw new Error(`Failed to fetch company IMO numbers: ${error.message}`); } finally { if (client) { try { await client.close(); logger.debug(`Closed company database connection`); } catch (closeError) { logger.warn(`Error closing company database connection: ${closeError.message}`); } } } } /** * Set the cached company IMO numbers * @param imoNumbers - Array of IMO numbers to cache */ export function setCompanyImoNumbers(imoNumbers) { companyImoNumbers = [...imoNumbers]; logger.debug(`Cached ${companyImoNumbers.length} IMO numbers for filtering`); } /** * Get the cached company IMO numbers * @returns Array of cached IMO numbers */ export function getCompanyImoNumbers() { return [...companyImoNumbers]; } /** * Check if a specific IMO number is valid for the company * @param imoNumber - IMO number to validate (string or number) * @returns Boolean indicating if IMO is authorized */ export function isValidImoForCompany(imoNumber) { const companyImos = getCompanyImoNumbers(); // If no company IMOs are loaded, allow access (fallback behavior) if (companyImos.length === 0) { logger.debug(`No company IMOs loaded, allowing access to IMO: ${imoNumber}`); return true; } const imoNum = Number(imoNumber); const companyImosNum = companyImos.map(imo => Number(imo)); const isValid = companyImosNum.includes(imoNum); if (!isValid) { logger.debug(`IMO ${imoNumber} not found in company IMO list`); } return isValid; } /** * Validate IMO number and provide detailed error message * @param imoNumber - IMO number to validate * @param companyName - Company name for error message * @returns Validation result with error message if invalid */ export function validateImoNumber(imoNumber, companyName) { // Check if IMO filtering should be bypassed for this company if (shouldBypassImoFiltering(companyName)) { logger.debug(`Bypassing IMO filtering for admin company: ${companyName}`); return { isValid: true }; } // Check if IMO is valid for the company if (isValidImoForCompany(imoNumber)) { return { isValid: true }; } // Generate error message with available IMO numbers const companyImos = getCompanyImoNumbers(); const displayLimit = 20; const displayImos = companyImos.slice(0, displayLimit); const moreCount = companyImos.length > displayLimit ? ` (and ${companyImos.length - displayLimit} more)` : ''; return { isValid: false, errorMessage: `IMO number ${imoNumber} is not associated with ${companyName}. Available IMO numbers: ${displayImos.join(', ')}${moreCount}` }; } /** * Check if IMO filtering should be bypassed for admin companies * @param companyName - Company name to check * @returns Boolean indicating if filtering should be bypassed */ export function shouldBypassImoFiltering(companyName) { const bypassCompanies = ['Synergy', 'Admin', 'SYIA', 'System']; const shouldBypass = bypassCompanies.includes(companyName); if (shouldBypass) { logger.debug(`IMO filtering bypassed for admin company: ${companyName}`); } return shouldBypass; } /** * Initialize company IMO numbers from configuration * Should be called during server startup */ export async function initializeCompanyImoNumbers() { const { companyName, companyDbUri, companyDbName } = config; if (!companyName) { logger.warn("No company name provided, IMO filtering will be disabled"); return; } if (shouldBypassImoFiltering(companyName)) { logger.info(`Admin company detected (${companyName}), IMO filtering will be bypassed`); setCompanyImoNumbers([]); return; } if (!companyDbUri || !companyDbName) { logger.warn("Company database configuration missing, IMO filtering will be limited"); return; } try { const imoNumbers = await fetchCompanyImoNumbers(companyName, companyDbUri, companyDbName); setCompanyImoNumbers(imoNumbers); logger.info(`Successfully initialized IMO filtering for company: ${companyName} with ${imoNumbers.length} IMO numbers`); } catch (error) { logger.error(`Failed to initialize company IMO numbers: ${error.message}`); logger.warn("IMO filtering may be limited. Server will continue with reduced functionality."); setCompanyImoNumbers([]); } } /** * Get current IMO filtering status for monitoring * @returns Object with filtering status information */ export function getImoFilteringStatus() { const { companyName } = config; const companyImos = getCompanyImoNumbers(); return { companyName: companyName || 'Not set', isAdminCompany: companyName ? shouldBypassImoFiltering(companyName) : false, imoCount: companyImos.length, filteringEnabled: !!(companyName && !shouldBypassImoFiltering(companyName) && companyImos.length > 0) }; } //# sourceMappingURL=imoUtils.js.map