UNPKG

syia-mcp-vessel-accounts

Version:

MCP server for vessel account management including EyeShare API integration, vessel expenses, and purchase orders

792 lines (703 loc) 29.4 kB
import { logger } from "../utils/logger.js"; import * as fs from 'fs'; import * as path from 'path'; import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); export class ResourceHandler { constructor(server) { this.server = server; } // List of available resources getResourceList() { return [ // Scripts { uri: "committed-cost://vessel-analyzer", name: "Vessel Committed Cost Analyzer", description: "Complete vessel committed cost analyzer with sequential workflow, API integration, and Excel report generation", mimeType: "text/x-python" }, // Database Schemas { uri: "vessel-data://database/schemas", name: "Database Schemas Documentation", description: "Complete MongoDB collection schemas for vessel expenses, purchase orders, and categories", mimeType: "application/json" }, // API Documentation { uri: "vessel-data://api/eyeshare-endpoints", name: "EyeShare API Endpoints", description: "Comprehensive documentation of EyeShare API endpoints, parameters, and response formats", mimeType: "text/markdown" }, // Data Flow Documentation { uri: "vessel-data://architecture/data-flow", name: "Data Flow Architecture", description: "Visual representation and explanation of data flow between MongoDB, EyeShare API, and committed cost calculations", mimeType: "text/markdown" }, // Tool Usage Guide { uri: "vessel-data://guides/tool-usage", name: "MCP Tools Usage Guide", description: "Comprehensive guide on how to use each MCP tool effectively with examples and best practices", mimeType: "text/markdown" }, // Business Process Documentation { uri: "vessel-data://processes/committed-cost-workflow", name: "Committed Cost Analysis Workflow", description: "Step-by-step business process documentation for committed cost analysis including data sources and calculations", mimeType: "text/markdown" }, // Configuration Templates { uri: "vessel-data://config/environment-template", name: "Environment Configuration Template", description: "Template and documentation for setting up environment variables and configuration", mimeType: "text/plain" }, // Sample Data { uri: "vessel-data://samples/test-data", name: "Sample Test Data", description: "Sample vessel data for testing and development purposes with realistic maritime financial data", mimeType: "application/json" } ]; } async handleReadResource(uri) { try { logger.info("Reading resource", { uri }); const parsedUri = new URL(uri); const resourceType = parsedUri.hostname; const identifier = parsedUri.pathname.substring(1); // remove leading '/' switch (parsedUri.protocol) { case "committed-cost:": return await this.handleCommittedCostResource(resourceType, uri); case "vessel-data:": return await this.handleVesselDataResource(resourceType, identifier, uri); default: throw new Error(`Unsupported resource protocol: ${parsedUri.protocol}`); } } catch (error) { logger.error(`Error reading resource ${uri}:`, error); throw error; } } async handleCommittedCostResource(resourceType, uri) { const scriptFiles = { "vessel-analyzer": "vessel_committed_cost_analyzer.py" }; const scriptFile = scriptFiles[resourceType]; if (!scriptFile) { throw new Error(`Unknown committed cost resource type: ${resourceType}`); } const scriptPath = path.join(__dirname, 'scripts', scriptFile); try { const scriptContent = fs.readFileSync(scriptPath, 'utf-8'); return { contents: [ { uri: uri, text: scriptContent, mimeType: "text/x-python" } ] }; } catch (error) { logger.error(`Error reading script file ${scriptPath}:`, error); throw new Error(`Failed to read script file: ${scriptFile}`); } } async handleVesselDataResource(resourceType, identifier, uri) { try { let content; let mimeType; switch (resourceType) { case "database": content = this.generateDatabaseSchemas(identifier); mimeType = "application/json"; break; case "api": content = this.generateApiDocumentation(identifier); mimeType = "text/markdown"; break; case "architecture": content = this.generateArchitectureDocumentation(identifier); mimeType = "text/markdown"; break; case "guides": content = this.generateGuideDocumentation(identifier); mimeType = "text/markdown"; break; case "processes": content = this.generateProcessDocumentation(identifier); mimeType = "text/markdown"; break; case "config": content = this.generateConfigurationTemplates(identifier); mimeType = "text/plain"; break; case "samples": content = this.generateSampleData(identifier); mimeType = "application/json"; break; default: throw new Error(`Unknown vessel data resource type: ${resourceType}`); } return { contents: [ { uri: uri, text: content, mimeType: mimeType } ] }; } catch (error) { logger.error(`Error generating vessel data resource ${resourceType}/${identifier}:`, error); throw error; } } generateDatabaseSchemas(identifier) { const schemas = { budget_expenses_raw_data: { description: "Current year vessel expenses from ShipNet system", fields: { _id: "ObjectId - MongoDB document ID", vesselCode: "String - 4-letter vessel code (e.g., BASC, BWET)", amount: "Number - Expense amount in original currency", currency: "String - Currency code (USD, EUR, etc.)", date: "Date - Transaction date", accountNo: "String - Account number for category lookup", account_name: "String - Account description", description: "String - Expense description", supplier: "String - Supplier name", "EyeShare ID": "String - Reference ID for EyeShare system integration" } }, budget_expenses_previous_year_raw_data: { description: "Previous year vessel expenses for historical analysis", fields: { _id: "ObjectId - MongoDB document ID", vesselCode: "String - 4-letter vessel code", amount: "Number - Expense amount in original currency", currency: "String - Currency code", date: "Date - Transaction date", accountNo: "String - Account number for category lookup", account_name: "String - Account description", description: "String - Expense description" } }, budget_category_raw_data: { description: "Category mapping for expense classification", fields: { _id: "ObjectId - MongoDB document ID", accountCode: "String - Account code matching expense accountNo", category: "String - Category name for grouping", subcategory: "String - Subcategory for detailed classification" } }, purchase_order: { description: "Purchase order data from ShipPalm V2/V3 systems", fields: { _id: "ObjectId - MongoDB document ID", "Purchase Order No": "String - PO number", "Item Line No": "Number - Line item number", vesselCode: "String - 4-letter vessel code", "Int Account Code": "String - Internal account code", Quantity: "Number - Ordered quantity", "Unit Price": "Number - Price per unit", "Purchase Order Value": "Number - Total PO value", "Purchase Order Status": "String - PO status (OPEN, CLOSED, etc.)", "Exchange Rate": "Number - Currency exchange rate to USD", supplier_name: "String - Supplier name", total_amount: "Number - Total amount in original currency" } } }; return JSON.stringify(schemas, null, 2); } generateApiDocumentation(identifier) { return `# EyeShare API Endpoints Documentation ## Authentication - **Endpoint**: \`/auth/connect/token\` - **Method**: POST - **Purpose**: Get OAuth2 access token - **Parameters**: - \`client_id\`: EyeShare client ID - \`client_secret\`: EyeShare client secret - \`grant_type\`: "client_credentials" ## Vessel Data - **Endpoint**: \`/api/system/config/allclientcompany\` - **Method**: GET - **Purpose**: Get all vessels from company hierarchy - **Headers**: \`Authorization: Bearer {access_token}\` - **Response**: Array of company/vessel objects with codes and names ## Invoice Search - **Endpoint**: \`/api/search\` - **Method**: POST - **Purpose**: Search invoices with filters - **Headers**: \`Authorization: Bearer {access_token}\` - **Parameters**: - \`CompanyCode\`: Vessel code filter - \`FromDate\`: Start date (ISO format) - \`ToDate\`: End date (ISO format) - \`DateField\`: Date field to filter on - \`MinAmount\`: Minimum invoice amount - \`MaxAmount\`: Maximum invoice amount - \`Status\`: Invoice status - \`Limit\`: Maximum results - \`Skip\`: Pagination offset ## Purchase Order Data - **Endpoint**: \`/api/purchaseorder/{invoiceId}\` - **Method**: GET - **Purpose**: Get purchase order data for specific invoice - **Headers**: \`Authorization: Bearer {access_token}\` - **Parameters**: - \`vesselCode\`: Vessel code - \`module\`: "purchaseorder" ## Attachment Download - **Endpoint**: \`/api/attachments/{attachmentId}/{documentId}/{version}\` - **Method**: GET - **Purpose**: Download invoice attachments - **Headers**: \`Authorization: Bearer {access_token}\` - **Response**: Binary file data (base64 encoded) ## Rate Limits - Standard rate limits apply - Use connection pooling for multiple requests - Implement retry logic with exponential backoff ## Error Handling - 401: Authentication required/expired - 404: Resource not found - 429: Rate limit exceeded - 500: Server error `; } generateArchitectureDocumentation(identifier) { return `# Vessel Accounts Data Flow Architecture ## System Overview The MCP Vessel Accounts server integrates multiple maritime data sources to provide comprehensive financial analysis. ## Data Sources ### 1. MongoDB Collections (ShipNet & ShipPalm) - **Location**: MongoDB database - **Collections**: - \`budget_expenses_raw_data\` (current year expenses) - \`budget_expenses_previous_year_raw_data\` (historical expenses) - \`budget_category_raw_data\` (expense categorization) - \`purchase_order\` (ShipPalm V2/V3 purchase orders) ### 2. EyeShare API - **Location**: External REST API - **Data Types**: - Vessel master data - Invoice search and details - Purchase order line items - Document attachments ## Data Flow Diagram \`\`\` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ MongoDB │ │ EyeShare API │ │ MCP Tools │ │ │ │ │ │ │ │ • Expenses │◄───┤ • Invoices │◄───┤ • Data Retrieval│ │ • Categories │ │ • PO Lines │ │ • Analysis │ │ • Purchase Orders│ │ • Vessels │ │ • Reporting │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ └───────────────────────┼───────────────────────┘ ▼ ┌─────────────────────────┐ │ Committed Cost │ │ Analysis Engine │ │ │ │ • Data Integration │ │ • Complex Calculations │ │ • Excel Report Gen │ └─────────────────────────┘ \`\`\` ## Committed Cost Calculation Flow 1. **Data Collection** - Fetch purchase orders from MongoDB - Fetch vessel expenses (current + previous year) - Extract EyeShare IDs from expenses 2. **API Integration** - Parallel API calls to EyeShare for PO lines - Invoice data retrieval for reconciliation - Category mapping from MongoDB 3. **Complex Calculations** - Quantity Diff = PO Quantity - (Invoiced + Written Off) - TCD (Total Cost Distribution) adjustments - Exchange rate conversions to USD - Status filtering (exclude SHORT-CLOSED) 4. **Report Generation** - 5 comprehensive Excel reports - Executive summaries via AI analysis - Data quality validation ## Security Considerations - OAuth2 authentication for EyeShare API - MongoDB connection security - Environment variable protection - Rate limiting and timeout handling ## Performance Optimizations - Connection pooling for MongoDB - Parallel API processing with ThreadPoolExecutor - Configurable batch sizes and timeouts - Efficient data aggregation pipelines `; } generateGuideDocumentation(identifier) { return `# MCP Vessel Accounts Tools Usage Guide ## Quick Start ### 1. Basic Vessel Information \`\`\`javascript // Get all available vessels mcp(operation='callTool', toolName='get_vessels', toolArgs={}, serverId='mcp-vessel-accounts') \`\`\` ### 2. Financial Data Retrieval \`\`\`javascript // Get vessel expenses mcp(operation='callTool', toolName='vessel_expenses', toolArgs={'vesselCode': 'BASC', 'limit': 1000}, serverId='mcp-vessel-accounts') // Get purchase orders mcp(operation='callTool', toolName='purchase_orders', toolArgs={'vesselCode': 'BASC', 'limit': 500}, serverId='mcp-vessel-accounts') // Search invoices mcp(operation='callTool', toolName='search_invoices', toolArgs={'vesselCode': 'BASC', 'fromDate': '2024-01-01T00:00:00.000Z'}, serverId='mcp-vessel-accounts') \`\`\` ### 3. AI-Powered Analysis \`\`\`javascript // Analyze vessel expenses with AI insights mcp(operation='callTool', toolName='analyze_vessel_expenses', toolArgs={'vesselCode': 'BASC'}, serverId='mcp-vessel-accounts') // Detect data anomalies mcp(operation='callTool', toolName='detect_data_anomalies', toolArgs={'vesselCode': 'BASC', 'dataType': 'all'}, serverId='mcp-vessel-accounts') \`\`\` ### 4. Comprehensive Reporting \`\`\`javascript // Step 1: Generate committed cost reports mcp(operation='callTool', toolName='generate_committed_cost_report', toolArgs={'vesselCode': 'BASC', 'endDate': '2025-07-31'}, serverId='mcp-vessel-accounts') // Step 2: Check completion status mcp(operation='callTool', toolName='check_report_status', toolArgs={'vesselCode': 'BASC'}, serverId='mcp-vessel-accounts') // Step 3: Get AI summary mcp(operation='callTool', toolName='summarize_committed_cost_report', toolArgs={'vesselCode': 'BASC'}, serverId='mcp-vessel-accounts') \`\`\` ## Tool Categories ### Data Retrieval Tools (9 tools) - **Purpose**: Get raw data from various sources - **Use Case**: When you need specific data for analysis - **Response**: Structured data in JSON format ### AI Analysis Tools (4 tools) - **Purpose**: Intelligent insights and pattern recognition - **Use Case**: Quick business insights and operational decisions - **Response**: Professional formatted analysis reports ### Reporting Tools (2 tools) - **Purpose**: Comprehensive Excel reports and summaries - **Use Case**: Executive reporting and detailed financial analysis - **Response**: Excel files + executive summaries ## Best Practices ### 1. Data Quality - Always check data completeness before analysis - Use anomaly detection tools to identify issues - Validate vessel codes (4 uppercase letters) ### 2. Performance - Use appropriate limits for large datasets - Consider timeouts for complex queries - Batch operations when possible ### 3. Business Workflow - Start with basic data retrieval - Use AI analysis for quick insights - Generate comprehensive reports for detailed analysis - Always verify report completion before summarizing ## Common Use Cases ### Monthly Financial Review 1. \`analyze_vessel_expenses\` - Get expense overview 2. \`analyze_vessel_invoices\` - Review supplier performance 3. \`detect_data_anomalies\` - Check data quality ### Quarterly Committed Cost Analysis 1. \`generate_committed_cost_report\` - Full analysis 2. \`check_report_status\` - Verify completion 3. \`summarize_committed_cost_report\` - Executive summary ### Operational Troubleshooting 1. \`vessel_expenses\` - Get raw expense data 2. \`search_invoices\` - Find specific transactions 3. \`get_purchase_order_by_invoice\` - Trace PO relationships ## Error Handling - Check vessel code format (must be 4 uppercase letters) - Verify date formats (ISO 8601 for date-time fields) - Monitor API rate limits and connection timeouts - Validate data availability before complex operations `; } generateProcessDocumentation(identifier) { return `# Committed Cost Analysis Workflow ## Business Purpose Committed cost analysis identifies outstanding financial commitments that will impact future cash flow. This is critical for: - **Budget Planning**: Understanding future expenditures - **Cash Flow Management**: Planning for upcoming payments - **Risk Assessment**: Identifying overcommitted positions - **Supplier Management**: Tracking outstanding orders ## Data Sources Integration ### Primary Sources 1. **Purchase Orders** (ShipPalm V2/V3 → MongoDB) - Order quantities and values - Supplier information - Status tracking 2. **Vessel Expenses** (ShipNet → MongoDB) - Current and previous year transactions - EyeShare ID references - Category classifications 3. **Invoice Data** (EyeShare API) - Invoiced quantities per PO line - Written-off quantities - TCD (Total Cost Distribution) data ## Calculation Methodology ### Step 1: Data Collection \`\`\` MongoDB Collections: ├── purchase_order (PO master data) ├── budget_expenses_raw_data (current expenses) ├── budget_expenses_previous_year_raw_data (historical) └── budget_category_raw_data (categorization) EyeShare API: ├── PO Lines data (quantities and costs) ├── Invoice reconciliation └── TCD adjustments \`\`\` ### Step 2: Quantity Analysis \`\`\` Outstanding Quantity = PO Quantity - (Invoiced Quantity + Written Off Quantity) Where: - PO Quantity: Original order quantity - Invoiced Quantity: Already invoiced/received - Written Off Quantity: Cancelled/adjusted quantities \`\`\` ### Step 3: Financial Calculation \`\`\` Committed Cost = Outstanding Quantity × Adjusted Unit Price Adjusted Unit Price considers: - Base unit price from PO - TCD (Total Cost Distribution) allocations - Exchange rate conversions to USD - Proportional cost adjustments \`\`\` ### Step 4: Status Filtering - Exclude SHORT-CLOSED orders (if closed before analysis date) - Include only orders with positive outstanding quantities - Filter by vessel code and date ranges ## Workflow Steps ### 1. Preparation Phase - Validate vessel code format - Set analysis end date - Configure output directory - Initialize logging ### 2. Data Extraction Phase - **Purchase Orders**: Fetch from MongoDB with vessel filter - **Vessel Expenses**: Get current + previous year data - **EyeShare IDs**: Extract unique IDs from expenses - **Categories**: Load account code mappings ### 3. API Integration Phase - **Parallel Processing**: Use ThreadPoolExecutor for efficiency - **PO Lines**: Fetch detailed line data from EyeShare - **Rate Limiting**: Respect API limits with proper delays - **Error Handling**: Retry logic for failed requests ### 4. Calculation Phase - **Data Joining**: Merge PO, expense, and API data - **Quantity Diff**: Calculate outstanding quantities - **Cost Calculation**: Apply complex pricing formulas - **Currency Conversion**: Convert all amounts to USD ### 5. Report Generation Phase - **Excel Reports**: Generate 5 comprehensive reports 1. Purchase Orders Report 2. Vessel Expenses Report 3. PO Lines Report 4. Committed Cost Report 5. Complete Analysis Report - **Data Validation**: Verify calculation accuracy - **Summary Statistics**: Generate key metrics ### 6. Analysis Phase (Optional) - **AI Summary**: Generate executive summary - **Insights**: Identify patterns and recommendations - **Risk Assessment**: Evaluate financial exposure ## Quality Assurance ### Data Validation - ✅ All EyeShare IDs processed - ✅ PO lines count matches expense ID count - ✅ Currency conversions applied correctly - ✅ Outstanding quantities are positive - ✅ Status filtering applied properly ### Calculation Verification - Cross-check totals across reports - Validate exchange rate applications - Verify TCD allocations - Confirm category mappings ### Output Validation - All 5 Excel files generated - Summary statistics calculated - No missing critical data - Proper file naming conventions ## Performance Considerations - **Parallel Processing**: Up to 100 concurrent API calls - **Memory Management**: Process large datasets efficiently - **Timeout Handling**: 5-minute maximum per operation - **Connection Pooling**: Optimize database connections ## Business Impact Metrics - **Total Committed Amount**: Outstanding financial exposure - **Record Count**: Number of commitment line items - **Average Commitment**: Per-line financial impact - **Risk Level**: Based on total exposure thresholds This workflow ensures accurate, comprehensive committed cost analysis that supports strategic financial decision-making for vessel operations. `; } generateConfigurationTemplates(identifier) { return `# Environment Configuration Template ## Required Environment Variables ### MongoDB Configuration MONGODB_URI=mongodb://username:password@host:port/database MONGODB_DATABASE=syia-etl-dev ### EyeShare API Configuration EYESHARE_BASE_URL=https://api.eyeshare.com EYESHARE_CLIENT_ID=your_client_id EYESHARE_CLIENT_SECRET=your_client_secret EYESHARE_COMPANY_CODE=your_company_code EYESHARE_MODULE=purchaseorder ### Logging Configuration LOG_LEVEL=info NODE_ENV=production ## Optional Configuration ### Performance Tuning MONGODB_POOL_SIZE=10 API_TIMEOUT_MS=30000 MAX_CONCURRENT_REQUESTS=100 ### Development Settings DEBUG_MODE=false CACHE_TTL_SECONDS=3600 ## Configuration Validation Before running the MCP server, ensure: 1. All required variables are set 2. MongoDB connection is accessible 3. EyeShare API credentials are valid 4. Network connectivity to all services ## Security Notes - Store sensitive credentials in secure environment - Use connection encryption for MongoDB - Implement proper access controls - Regular credential rotation recommended ## Docker Environment File Example # Create .env file in project root cp .env.example .env # Edit with your actual values nano .env ## Kubernetes ConfigMap Example apiVersion: v1 kind: ConfigMap metadata: name: vessel-accounts-config data: MONGODB_URI: "mongodb://mongo-service:27017/syia-etl-dev" EYESHARE_BASE_URL: "https://api.eyeshare.com" LOG_LEVEL: "info" ## Testing Configuration # Test MongoDB connection node -e "const { MongoClient } = require('mongodb'); MongoClient.connect(process.env.MONGODB_URI).then(() => console.log('MongoDB OK')).catch(console.error);" # Test EyeShare API curl -X POST "$EYESHARE_BASE_URL/auth/connect/token" -d "client_id=$EYESHARE_CLIENT_ID&client_secret=$EYESHARE_CLIENT_SECRET&grant_type=client_credentials" `; } generateSampleData(identifier) { return JSON.stringify({ vessel_expenses_sample: [ { _id: "507f1f77bcf86cd799439011", vesselCode: "BASC", amount: 15750.00, currency: "USD", date: "2024-01-15T00:00:00.000Z", accountNo: "5100", account_name: "Fuel and Lubricants", description: "Marine Gas Oil - Port Supply", supplier: "Marine Fuel Supply Co.", "EyeShare ID": "inv-2024-001234" }, { _id: "507f1f77bcf86cd799439012", vesselCode: "BASC", amount: 8500.00, currency: "EUR", date: "2024-01-20T00:00:00.000Z", accountNo: "5200", account_name: "Maintenance and Repairs", description: "Engine Parts Replacement", supplier: "Maritime Engineering Ltd.", "EyeShare ID": "inv-2024-001235" } ], purchase_orders_sample: [ { _id: "507f1f77bcf86cd799439013", "Purchase Order No": "PO-2024-0156", "Item Line No": 1, vesselCode: "BASC", "Int Account Code": "5100", Quantity: 500.0, "Unit Price": 31.50, "Purchase Order Value": 15750.00, "Purchase Order Status": "OPEN", "Exchange Rate": 1.0, supplier_name: "Marine Fuel Supply Co.", total_amount: 15750.00 } ], budget_categories_sample: [ { _id: "507f1f77bcf86cd799439014", accountCode: "5100", category: "Fuel & Lubricants", subcategory: "Marine Gas Oil" }, { _id: "507f1f77bcf86cd799439015", accountCode: "5200", category: "Maintenance & Repairs", subcategory: "Engine Components" } ], eyeshare_invoice_sample: [ { id: "inv-2024-001234", vesselCode: "BASC", supplierName: "Marine Fuel Supply Co.", amount: 15750.00, currency: "USD", status: "Approved", invoiceDate: "2024-01-15T00:00:00.000Z", dueDate: "2024-02-14T00:00:00.000Z" } ], vessel_codes_sample: [ { code: "BASC", name: "Baltic Sunrise", type: "Bulk Carrier" }, { code: "BWET", name: "Blue Water Express", type: "Container" }, { code: "GEVI", name: "Green Victory", type: "Tanker" }, { code: "ACET", name: "Atlantic Crest", type: "General Cargo" } ] }, null, 2); } } //# sourceMappingURL=index.js.map