UNPKG

docwriter-mcp-server

Version:

A Model Context Protocol (MCP) server for programmatic creation, modification, and compilation of structured LaTeX documents. Enables AI agents and automated workflows to generate reports, articles, and papers from templates, with secure, structured conte

115 lines (114 loc) 5.14 kB
/** * @fileoverview Main entry point for the MCP (Model Context Protocol) server. * This file orchestrates the server's lifecycle: * 1. Initializes the core `McpServer` instance (from `@modelcontextprotocol/sdk`) with its identity and capabilities. * 2. Registers available resources and tools, making them discoverable and usable by clients. * 3. Selects and starts the appropriate communication transport (stdio or Streamable HTTP) * based on configuration. * 4. Handles top-level error management during startup. * * MCP Specification References: * - Lifecycle: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/basic/lifecycle.mdx * - Overview (Capabilities): https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/basic/index.mdx * - Transports: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/basic/transports.mdx * @module src/mcp-server/server */ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { config, environment } from "../config/index.js"; import { BaseErrorCode } from "../types-global/errors.js"; import { ErrorHandler, logger, requestContextService } from "../utils/index.js"; import { registerCreateLatexDocumentTool } from "./tools/createLatexDocument/index.js"; import { registerUpdateDocumentBlockTool } from "./tools/updateDocumentBlock/index.js"; import { registerSearchAndReplaceTool } from "./tools/searchAndReplace/index.js"; import { registerCompileLatexToPdfTool } from "./tools/compileLatexToPdf/index.js"; import { registerListLatexDocumentsTool } from "./tools/listLatexDocuments/index.js"; import { startHttpTransport } from "./transports/httpTransport.js"; import { connectStdioTransport } from "./transports/stdioTransport.js"; /** * Creates and configures a new instance of the `McpServer`. * * @returns A promise resolving with the configured `McpServer` instance. * @throws {McpError} If any resource or tool registration fails. * @private */ async function createMcpServerInstance() { const context = requestContextService.createRequestContext({ operation: "createMcpServerInstance", }); logger.info("Initializing MCP server instance", context); requestContextService.configure({ appName: config.mcpServerName, appVersion: config.mcpServerVersion, environment, }); const server = new McpServer({ name: config.mcpServerName, version: config.mcpServerVersion }, { capabilities: { logging: {}, resources: { listChanged: true }, tools: { listChanged: true }, }, }); await ErrorHandler.tryCatch(async () => { logger.debug("Registering resources and tools...", context); await registerCreateLatexDocumentTool(server); await registerUpdateDocumentBlockTool(server); await registerSearchAndReplaceTool(server); await registerCompileLatexToPdfTool(server); await registerListLatexDocumentsTool(server); logger.info("Resources and tools registered successfully", context); }, { operation: "registerAllCapabilities", context, errorCode: BaseErrorCode.INITIALIZATION_FAILED, critical: true, }); return server; } /** * Selects, sets up, and starts the appropriate MCP transport layer based on configuration. * * @returns Resolves with `McpServer` for 'stdio', `http.Server` for 'http', or `void`. * @throws {Error} If transport type is unsupported or setup fails. * @private */ async function startTransport() { const transportType = config.mcpTransportType; const context = requestContextService.createRequestContext({ operation: "startTransport", transport: transportType, }); logger.info(`Starting transport: ${transportType}`, context); if (transportType === "http") { return startHttpTransport(createMcpServerInstance, context); } if (transportType === "stdio") { const server = await createMcpServerInstance(); await connectStdioTransport(server, context); return server; } throw new Error(`Unsupported transport type: ${transportType}. Must be 'stdio' or 'http'.`); } /** * Main application entry point. Initializes and starts the MCP server. */ export async function initializeAndStartServer() { const context = requestContextService.createRequestContext({ operation: "initializeAndStartServer", }); logger.info("MCP Server initialization sequence started.", context); try { const result = await startTransport(); logger.info("MCP Server initialization sequence completed successfully.", context); return result; } catch (err) { ErrorHandler.handleError(err, { operation: "initializeAndStartServer", context: context, critical: true, rethrow: false, }); logger.info("Exiting process due to critical initialization error.", context); process.exit(1); } }