UNPKG

clinicaltrialsgov-mcp-server

Version:

ClinicalTrials.gov Model Context Protocol (MCP) Server that provides a suite of tools for interacting with the official ClinicalTrials.gov v2 API. Enables AI agents and LLMs to programmatically search, retrieve, and analyze clinical trial data.

119 lines (118 loc) 5.15 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 { ErrorHandler, logger, requestContextService } from "../utils/index.js"; import { registerGetStudyTool } from "./tools/getStudy/index.js"; import { registerSearchStudiesTool } from "./tools/searchStudies/index.js"; import { registerAnalyzeTrendsTool } from "./tools/analyzeTrends/index.js"; import { startHttpTransport } from "./transports/http/index.js"; import { startStdioTransport } from "./transports/stdio/index.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 }, }, }); try { logger.debug("Registering resources and tools...", context); await registerGetStudyTool(server); await registerSearchStudiesTool(server); await registerAnalyzeTrendsTool(server); logger.info("Resources and tools registered successfully", context); } catch (err) { logger.error("Failed to register resources/tools", { ...context, error: err instanceof Error ? err.message : String(err), stack: err instanceof Error ? err.stack : undefined, }); throw err; } return server; } /** * Selects, sets up, and starts the appropriate MCP transport layer based on configuration. * * @returns Resolves with `McpServer` for 'stdio' or `http.Server` for 'http'. * @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") { const { server } = await startHttpTransport(createMcpServerInstance, context); return server; } if (transportType === "stdio") { const server = await createMcpServerInstance(); await startStdioTransport(server, context); return server; } logger.crit(`Unsupported transport type configured: ${transportType}`, context); 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) { logger.crit("Critical error during MCP server initialization.", { ...context, error: err instanceof Error ? err.message : String(err), stack: err instanceof Error ? err.stack : undefined, }); ErrorHandler.handleError(err, { ...context, operation: "initializeAndStartServer_Catch", critical: true, }); logger.info("Exiting process due to critical initialization error.", context); process.exit(1); } }