@cyanheads/pubmed-mcp-server
Version:
A Model Context Protocol (MCP) server enabling AI agents to intelligently search, retrieve, and analyze biomedical literature from PubMed via NCBI E-utilities. Built on the mcp-ts-template for robust, production-ready performance.
65 lines (64 loc) • 2.8 kB
JavaScript
/**
* @fileoverview Service for interacting with NCBI E-utilities.
* This module centralizes all communication with NCBI's E-utility APIs,
* handling request construction, API key management, rate limiting,
* retries, and parsing of XML/JSON responses. It aims to provide a robust
* and compliant interface for other parts of the pubmed-mcp-server to
* access PubMed data.
* @module src/services/NCBI/ncbiService
*/
import { logger, requestContextService, } from "../../utils/index.js";
import { NcbiCoreApiClient } from "./ncbiCoreApiClient.js";
import { NcbiRequestQueueManager } from "./ncbiRequestQueueManager.js";
import { NcbiResponseHandler } from "./ncbiResponseHandler.js";
export class NcbiService {
constructor() {
this.queueManager = new NcbiRequestQueueManager();
this.apiClient = new NcbiCoreApiClient();
this.responseHandler = new NcbiResponseHandler();
}
async performNcbiRequest(endpoint, params, context, options = {}) {
const task = async () => {
const rawResponse = await this.apiClient.makeRequest(endpoint, params, context, options);
return this.responseHandler.parseAndHandleResponse(rawResponse, endpoint, context, options);
};
return this.queueManager.enqueueRequest(task, context, endpoint, params);
}
async eSearch(params, context) {
return this.performNcbiRequest("esearch", params, context, {
retmode: "xml",
});
}
async eSummary(params, context) {
// Determine retmode based on params, default to xml
const retmode = params.version === "2.0" && params.retmode === "json" ? "json" : "xml";
return this.performNcbiRequest("esummary", params, context, { retmode });
}
async eFetch(params, context, options = { retmode: "xml" }) {
// Determine if POST should be used based on number of IDs
const usePost = typeof params.id === "string" && params.id.split(",").length > 200;
const fetchOptions = { ...options, usePost };
return this.performNcbiRequest("efetch", params, context, fetchOptions);
}
async eLink(params, context) {
return this.performNcbiRequest("elink", params, context, {
retmode: "xml",
});
}
async eInfo(params, context) {
return this.performNcbiRequest("einfo", params, context, {
retmode: "xml",
});
}
}
let ncbiServiceInstance;
export function getNcbiService() {
if (!ncbiServiceInstance) {
ncbiServiceInstance = new NcbiService();
logger.debug("NcbiService lazily initialized.", requestContextService.createRequestContext({
service: "NcbiService",
operation: "getNcbiServiceInstance",
}));
}
return ncbiServiceInstance;
}