@cyanheads/pubmed-mcp-server
Version:
Production-ready PubMed Model Context Protocol (MCP) server that empowers AI agents and research tools with comprehensive access to PubMed's article database. Enables advanced, automated LLM workflows for searching, retrieving, analyzing, and visualizing
120 lines • 5.18 kB
JavaScript
/**
* @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.
*
* @module src/mcp-server/server
*/
import { config, environment } from "../config/index.js";
import { ErrorHandler, logger, requestContextService } from "../utils/index.js";
import { ManagedMcpServer } from "./core/managedMcpServer.js";
import { registerPubMedArticleConnectionsTool } from "./tools/pubmedArticleConnections/index.js";
import { registerPubMedFetchContentsTool } from "./tools/pubmedFetchContents/index.js";
import { registerPubMedGenerateChartTool } from "./tools/pubmedGenerateChart/index.js";
import { registerPubMedResearchAgentTool } from "./tools/pubmedResearchAgent/index.js";
import { registerPubMedSearchArticlesTool } from "./tools/pubmedSearchArticles/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 `ManagedMcpServer` 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 ManagedMcpServer({ name: config.mcpServerName, version: config.mcpServerVersion }, {
capabilities: {
logging: {},
resources: { listChanged: true },
tools: { listChanged: true },
},
});
try {
logger.debug("Registering resources and tools...", context);
// IMPORTANT: Keep tool registrations in alphabetical order.
await registerPubMedArticleConnectionsTool(server);
await registerPubMedFetchContentsTool(server);
await registerPubMedGenerateChartTool(server);
await registerPubMedResearchAgentTool(server);
await registerPubMedSearchArticlesTool(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.fatal(`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.fatal("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);
}
}
//# sourceMappingURL=server.js.map