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
JavaScript
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