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

151 lines 5.8 kB
/** * MCP Server - Standardized Implementation * Multi-tenant server with YAML-based configuration */ 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 { readFileSync } from 'fs'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import { ToolHandler } from "./tools/index.js"; import { config } from "./config/index.js"; import { logger, initializeConnection as initializeTypesenseConnection, closeConnection as closeTypesenseConnection, setConfig } from "syia-mcp-utils"; import { toolDefinitions } from "./tools/schema.js"; import { promptList, getPrompt } from "./prompts/index.js"; import { resourceList, readResource } from "./resources/index.js"; // TODO: Replace with syia-mcp-utils import when imoCache is moved there import { initializeImoCache } from "./utils/imoCache.js"; // Get version dynamically from package.json const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8')); export { logger }; // Global server instance and transport for access during shutdown let server = null; let transport = null; // Shared error handler for requests function handleRequestError(operation, error, context) { logger.error(`Error in ${operation}`, { error, context }); throw error; } // Graceful shutdown handler async function handleShutdown(signal) { logger.info(`Received ${signal}. Shutting down server...`); try { // Close all database connections await closeTypesenseConnection(); // Close transport if it exists if (transport) { try { await transport.close(); logger.info("Transport closed successfully"); } catch (error) { logger.error("Error closing transport:", error); } } logger.info("Server shutdown complete"); process.exit(0); } catch (error) { logger.error("Error during shutdown:", error); process.exit(1); } } // Setup graceful shutdown handlers process.on('SIGINT', () => handleShutdown('SIGINT')); process.on('SIGTERM', () => handleShutdown('SIGTERM')); process.on('uncaughtException', (error) => { logger.error("Uncaught exception:", error); handleShutdown('uncaughtException'); }); process.on('unhandledRejection', (reason) => { logger.error("Unhandled rejection:", reason); handleShutdown('unhandledRejection'); }); async function initializeServices() { setConfig(config); initializeTypesenseConnection(); // Initialize IMO cache (fetch and save to file) await initializeImoCache(config.companyName); } async function main() { logger.info(`Starting MCP server v${packageJson.version} in ${config.environment} environment`); try { await initializeServices(); } catch (error) { logger.error("Failed to initialize services:", error); process.exit(1); } // Create server instance server = new Server({ name: packageJson.name, version: packageJson.version }, { capabilities: { resources: { read: true, list: true, templates: true }, tools: { list: true, call: true }, prompts: { list: true, get: true } } }); const toolHandler = new ToolHandler(server); // Resource handlers server.setRequestHandler(ListResourcesRequestSchema, async () => { return { resources: resourceList }; }); server.setRequestHandler(ReadResourceRequestSchema, async (request) => { try { const content = await readResource(request.params.uri); return { contents: [{ uri: request.params.uri, mimeType: "application/json", text: content }] }; } catch (error) { handleRequestError("ReadResource", error, request.params.uri); } }); server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => { return { templates: [] }; }); // Tools handler server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: toolDefinitions }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const result = await toolHandler.handleCallTool(request.params.name, request.params.arguments || {}); return { content: result }; } catch (error) { handleRequestError("CallTool", error, request.params.name); } }); // Prompt handlers server.setRequestHandler(ListPromptsRequestSchema, async () => { return { prompts: promptList }; }); server.setRequestHandler(GetPromptRequestSchema, async (request) => { try { const result = getPrompt(request.params.name, request.params.arguments); return result; } catch (error) { handleRequestError("GetPrompt", error, request.params.name); } }); // Connect transport and start server transport = new StdioServerTransport(); await server.connect(transport); logger.info("Server started successfully"); } main().catch((error) => { logger.error("Fatal error during server startup:", error); process.exit(1); }); //# sourceMappingURL=index.js.map