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
137 lines • 5.74 kB
JavaScript
/**
* Voyage & Consumption MCP Server
* A low-level server implementation using Model Context Protocol
*/
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { ListResourcesRequestSchema, ReadResourceRequestSchema, ListToolsRequestSchema, CallToolRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListResourceTemplatesRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import { ToolHandler } from "./tools/index.js";
import { config } from "./utils/config.js";
import { logger } from "./utils/logger.js";
import { toolDefinitions } from "./tools/schema.js";
import { promptList, getPrompt } from './prompts/index.js';
import { registerResources } from './resources/index.js';
import { ConnectionManager } from './database/connection-manager.js';
import { DatabaseService } from './database/database-service.js';
import { initializeCompanyImoNumbers } from './utils/imoUtils.js';
async function main() {
logger.info("Starting Voyage & Consumption MCP server...");
// Validate critical configuration
if (!config.siyaApiKey) {
logger.error("SIYA_API_KEY is required but not provided. Please set the --siya-api-key argument or SIYA_API_KEY environment variable.");
process.exit(1);
}
// Validate company configuration for IMO filtering
if (!config.companyName) {
logger.error("Company name is required for IMO filtering. Please provide it via --company-name option or COMPANY_NAME environment variable.");
process.exit(1);
}
// Initialize connection pooling
logger.info("Initializing database connection pooling...");
const connectionManager = new ConnectionManager({
uri: config.mongoUri,
dbName: config.dbName
}, {
uri: config.secondaryMongoUri,
dbName: config.secondaryDbName
});
await connectionManager.initializeConnections();
const databaseService = new DatabaseService(connectionManager);
// Initialize company IMO numbers for filtering
logger.info("Initializing company IMO numbers for filtering...");
await initializeCompanyImoNumbers();
const server = new Server({
name: "voyage-and-consumption-mcp-server",
version: "1.1.4"
}, {
capabilities: {
resources: {
read: true,
list: true,
templates: true
},
tools: {
list: true,
call: true
},
prompts: {
list: true,
get: true
}
}
});
const toolHandler = new ToolHandler(server, databaseService);
// Register resources
const { handleListResources, handleReadResource } = await registerResources();
// Register handlers
server.setRequestHandler(ListResourcesRequestSchema, async (request) => {
return handleListResources(request);
});
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
return handleReadResource(request);
});
// Empty resource templates
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
return { templates: [] };
});
// Tools list
server.setRequestHandler(ListToolsRequestSchema, async (request) => {
logger.info("Handling ListToolsRequest", { request });
let tools = [...toolDefinitions];
const params = request.params || {};
const category = params.category;
const search = params.search;
const includeDeprecated = params.include_deprecated;
// Apply category filter if provided
if (category) {
tools = tools.filter(tool => {
const toolName = tool.name.toLowerCase();
return toolName.includes(category.toLowerCase());
});
}
// Apply search filter if provided
if (search) {
const searchTerm = search.toLowerCase();
tools = tools.filter(tool => tool.name.toLowerCase().includes(searchTerm) ||
(tool.description?.toLowerCase() || '').includes(searchTerm));
}
// Filter out deprecated tools unless explicitly requested
if (!includeDeprecated) {
tools = tools.filter(tool => !tool.name.includes('deprecated'));
}
return { tools };
});
// Tool call
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const result = await toolHandler.handleCallTool(request.params.name, request.params.arguments || {});
return { content: result };
});
// List prompts
server.setRequestHandler(ListPromptsRequestSchema, async () => {
return { prompts: promptList };
});
// Get prompt
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
return getPrompt(request.params.name, request.params.arguments);
});
// Set up graceful shutdown
process.on('SIGINT', async () => {
logger.info('Received SIGINT, shutting down gracefully...');
await databaseService.close();
process.exit(0);
});
process.on('SIGTERM', async () => {
logger.info('Received SIGTERM, shutting down gracefully...');
await databaseService.close();
process.exit(0);
});
// Connect to transport and start server
const transport = new StdioServerTransport();
await server.connect(transport);
logger.info("MCP server connected and running with connection pooling");
}
main().catch((error) => {
logger.error("Fatal error:", error);
process.exit(1);
});
//# sourceMappingURL=index.js.map