pms-analysis-reports-mcp-server
Version:
PMS analysis reports server handling maintenance reports, equipment analysis, compliance tracking, and performance metrics with ERP access for data extraction
148 lines • 6.38 kB
JavaScript
/**
* PMS Analysis Reports 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, handleGetPrompt } from "./prompts/index.js";
import { initializeCompanyDatabase, fetchCompanyImoNumbers, setCompanyImoNumbers, shouldBypassImoFiltering, closeCompanyDatabase } from "./utils/imoUtils.js";
async function main() {
logger.info("Starting PMS Analysis Reports MCP server... version 1.0.19");
// ✅ Step 1: Validate company name configuration
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);
}
logger.info(`Starting server for company: ${config.companyName}`);
// ✅ Step 2: Initialize company database and fetch IMO numbers
try {
// Initialize company database connection
await initializeCompanyDatabase();
// Skip IMO fetching for admin companies
if (shouldBypassImoFiltering(config.companyName)) {
logger.info(`Admin company detected: ${config.companyName}. Skipping IMO filtering.`);
setCompanyImoNumbers([]);
}
else {
logger.info(`Fetching IMO numbers for company: ${config.companyName}`);
const imoNumbers = await fetchCompanyImoNumbers(config.companyName);
setCompanyImoNumbers(imoNumbers);
logger.info(`Successfully fetched and cached ${imoNumbers.length} IMO numbers for company: ${config.companyName}`);
}
}
catch (error) {
logger.error("Failed to initialize IMO filtering system:", error);
logger.warn("IMO filtering may be limited. Server will continue with reduced functionality.");
// Continue server startup even if IMO fetching fails
setCompanyImoNumbers([]);
}
const server = new Server({
name: "pms-analysis-reports-mcp-server",
version: "1.0.19"
}, {
capabilities: {
resources: {
read: true,
list: true,
templates: true
},
tools: {
list: true,
call: true
},
prompts: {
list: true,
get: true
}
}
});
const toolHandler = new ToolHandler(server);
// Empty resource list
server.setRequestHandler(ListResourcesRequestSchema, async () => {
return { resources: [] };
});
// Empty resource read
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
throw new Error("Resource reading not implemented");
});
// 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 || {});
// Ensure content is always an array as expected by MCP protocol
const content = Array.isArray(result) ? result : [result];
return { content };
});
// Prompts list
server.setRequestHandler(ListPromptsRequestSchema, async () => {
logger.info("Handling ListPromptsRequest");
return { prompts: promptList };
});
// Prompt get
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
logger.info("Handling GetPromptRequest", { request });
const params = request.params || {};
const name = params.name;
const args = params.arguments || {};
const result = handleGetPrompt(name, args);
return result;
});
// ✅ Step 3: Setup graceful shutdown handling
const gracefulShutdown = async () => {
logger.info("Shutting down server gracefully...");
try {
await closeCompanyDatabase();
logger.info("Company database connection closed successfully");
}
catch (error) {
logger.error("Error during graceful shutdown:", error);
}
process.exit(0);
};
process.on('SIGINT', gracefulShutdown);
process.on('SIGTERM', gracefulShutdown);
// Connect to transport and start server
const transport = new StdioServerTransport();
await server.connect(transport);
logger.info("Server started successfully with IMO filtering enabled");
}
main().catch((error) => {
logger.error("Fatal error:", error);
process.exit(1);
});
//# sourceMappingURL=index.js.map