UNPKG

purchase-mcp-server

Version:

Purchase and budget management server handling requisitions, purchase orders, expenses, budgets, and vendor management with ERP access for data extraction

153 lines 8.31 kB
// TODO: Replace with syia-mcp-utils import when imoCache is moved there import { getCompanyImosWithFallback, shouldSkipImoValidation } from "../utils/imoCache.js"; import { logger } from "../index.js"; import { config } from "../config/index.js"; import { QAToolHandler } from "./handlers/qaTools.js"; import { UniversalToolHandler } from "./handlers/universalTools.js"; // import { SearchToolHandler } from "./handlers/searchTools.js"; import { ExportToolHandler } from "./handlers/exportTools.js"; import { VendorToolHandler } from "./handlers/vendorTools.js"; /** * Main tool handler that coordinates different categories of tools */ export class ToolHandler { constructor(server) { this.qaToolHandler = new QAToolHandler(); this.universalToolHandler = new UniversalToolHandler(); // this.searchToolHandler = new SearchToolHandler(); this.exportToolHandler = new ExportToolHandler(); this.vendorToolHandler = new VendorToolHandler(); } /** * Get company IMO numbers for validation */ getCompanyImos() { return getCompanyImosWithFallback(); } /** * Validate IMO numbers against company IMO list */ validateImoNumber(imo) { // Skip validation for companies that don't require IMO validation if (shouldSkipImoValidation(config.companyName)) { logger.debug(`Skipping IMO validation for company: "${config.companyName}"`); return null; } const companyImos = this.getCompanyImos(); if (companyImos.length === 0) { logger.warn('No company IMOs available for validation, allowing request to proceed'); return null; } const imoNum = Number(imo); const companyImosNum = companyImos.map(imo => Number(imo)); if (!companyImosNum.includes(imoNum)) { return [{ type: "text", text: `Error: IMO number ${imo} is not associated with the current company. Please provide a valid IMO number. Available IMO numbers: ${companyImos.join(", ")}`, title: "Invalid IMO Number", format: "json" }]; } return null; } /** * Type-safe casting and validation of tool arguments */ processToolArguments(toolName, arguments_) { // Validate IMO numbers if (arguments_.imo) { const error = this.validateImoNumber(arguments_.imo); if (error) return { args: arguments_, error }; } if (arguments_.filters?.imo) { const error = this.validateImoNumber(arguments_.filters.imo); if (error) return { args: arguments_, error }; } // Runtime type casting - the schema validation ensures correctness return { args: arguments_ }; } /** * Handles tool calls by routing them to appropriate specialized handlers * @param name - The name of the tool to call * @param arguments_ - The arguments for the tool * @returns Promise resolving to the tool response */ async handleCallTool(name, arguments_) { try { // 🔒 AUTHORIZATION: Validate company IMO access before any tool execution const authResult = this.processToolArguments(name, arguments_); if (authResult.error) { return authResult.error; } const validatedArgs = authResult.args; switch (name) { case "get_monthly_opex_budget_variance": return await this.qaToolHandler.getMonthlyOpexBudgetVariance(validatedArgs); case "get_current_year_committed_cost": return await this.qaToolHandler.getCurrentYearCommittedCost(validatedArgs); case "get_budget_status_summary_ytd": return await this.qaToolHandler.getBudgetStatusSummaryYtd(validatedArgs); case "get_purchase_orders_with_forwarders": return await this.qaToolHandler.getPurchaseOrdersWithForwarders(validatedArgs); case "purchase_orders_open_more_than_180_days": return await this.qaToolHandler.purchaseOrdersOpenMoreThan180Days(validatedArgs); // case "get_vessel_budget_data": // return await this.searchToolHandler.getVesselBudgetData(validatedArgs as any); case "universal_purchase_search": return await this.universalToolHandler.universalPurchaseSearchHandler(validatedArgs); case "universal_budget_search": return await this.universalToolHandler.universalBudgetSearchHandler(validatedArgs); case "universal_expense_search": return await this.universalToolHandler.universalExpenseSearchHandler(validatedArgs); // case "get_purchase_requisition_details": // return await this.searchToolHandler.getPurchaseRequisitionDetails(validatedArgs as any); // case "get_purchase_order_details": // return await this.searchToolHandler.getPurchaseOrderDetails(validatedArgs as any); // case "list_requisitions_by_status": // return await this.searchToolHandler.listRequisitionsByStatus(validatedArgs as any); // case "list_overdue_open_requisitions": // return await this.searchToolHandler.listOverdueOpenRequisitions(validatedArgs as any); // case "list_purchase_orders_by_status": // return await this.searchToolHandler.listPurchaseOrdersByStatus(validatedArgs as any); // case "list_requisitions_by_type_and_stage": // return await this.searchToolHandler.listRequisitionsByTypeAndStage(validatedArgs as any); // case "list_recent_requisitions_by_order_priority": // return await this.searchToolHandler.listRecentRequisitionsByOrderPriority(validatedArgs as any); // case "list_top_expenses_by_category": // return await this.searchToolHandler.listTopExpensesByCategory(validatedArgs as any); // case "list_committed_cost_expenses": // return await this.searchToolHandler.listCommittedCostExpenses(validatedArgs as any); // case "get_vessel_purchase_log_table": // return await this.searchToolHandler.getVesselPurchaseLogTable(validatedArgs as any); // case "list_recent_urgent_requisitions": // return await this.searchToolHandler.listRecentUrgentRequisitions(validatedArgs as any); case "find_relevant_vendors": return await this.vendorToolHandler.findRelevantVendors(validatedArgs); case "get_vendor_contact_details": return await this.vendorToolHandler.getVendorContactInfo(validatedArgs); // Fleet tools case "get_fleet_purchase_log_table": return await this.qaToolHandler.getFleetPurchaseLogTable(validatedArgs); case "get_fleet_purchase_activities": return await this.qaToolHandler.getFleetPurchaseActivities(validatedArgs); case "get_fleet_budget_overviews": return await this.qaToolHandler.getFleetBudgetOverviews(validatedArgs); case "get_complete_vessel_purchase_requisition_data": return await this.exportToolHandler.getCompleteVesselPurchaseRequisitionData(validatedArgs); case "get_complete_vessel_expense_data": return await this.exportToolHandler.getCompleteVesselExpenseData(validatedArgs); case "get_complete_vessel_budget_data": return await this.exportToolHandler.getCompleteVesselBudgetData(validatedArgs); default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { logger.error(`Error calling tool ${name}:`, error); throw error; } } } //# sourceMappingURL=index.js.map