Skip to main content
Glama

get-article-details

Retrieve comprehensive medical article information using PubMed ID to access detailed research data from authoritative medical databases.

Instructions

Get detailed information about a specific medical article by PMID

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pmidYesPubMed ID (PMID) of the article

Implementation Reference

  • src/index.ts:141-155 (registration)
    MCP tool registration for 'get-article-details', including input schema, description, and thin handler delegating to utility functions.
    server.tool(
      "get-article-details",
      "Get detailed information about a specific medical article by PMID",
      {
        pmid: z.string().describe("PubMed ID (PMID) of the article"),
      },
      async ({ pmid }) => {
        try {
          const article = await getPubMedArticleByPMID(pmid);
          return formatArticleDetails(article, pmid);
        } catch (error: any) {
          return createErrorResponse("fetching article details", error);
        }
      },
    );
  • Core handler function that fetches PubMed article details by PMID via EUtils API, parses XML response, and retrieves full text if available via PMC.
    export async function getPubMedArticleByPMID(
      pmid: string,
    ): Promise<PubMedArticle | null> {
      try {
        const fetchRes = await superagent
          .get(`${PUBMED_API_BASE}/efetch.fcgi`)
          .query({
            db: "pubmed",
            id: pmid,
            retmode: "xml",
          })
          .set("User-Agent", USER_AGENT);
    
        const articles = parsePubMedXML(fetchRes.text);
        const article = articles[0] || null;
    
        if (article && article.pmc_id) {
          // Always try to fetch full text for individual article requests
          try {
            const fullText = await fetchFullTextFromPMC(article.pmc_id);
            if (fullText) {
              article.full_text = fullText;
            }
          } catch (error) {
            console.error(`Error fetching full text for PMID ${pmid}:`, error);
          }
        }
    
        return article;
      } catch (error) {
        console.error("Error fetching article by PMID:", error);
        return null;
      }
    }
  • TypeScript type definition for PubMedArticle, defining the structure of article data returned by the tool.
    export type PubMedArticle = {
      pmid: string;
      title: string;
      abstract: string;
      authors: string[];
      journal: string;
      publication_date: string;
      doi?: string;
      pmc_id?: string;
      full_text?: string;
    };
  • Helper function to format the retrieved PubMed article data into a formatted MCP text response.
    export function formatArticleDetails(article: any, pmid: string) {
      if (!article) {
        return createMCPResponse(`No article found with PMID: ${pmid}`);
      }
    
      let result = `**Article Details for PMID: ${pmid}**\n\n`;
      result += `**Title:** ${article.title}\n\n`;
    
      if (article.authors && article.authors.length > 0) {
        result += `**Authors:** ${article.authors.join(", ")}\n\n`;
      }
    
      result += `**Journal:** ${article.journal}\n`;
      result += `**Publication Date:** ${article.publication_date}\n`;
    
      if (article.doi) {
        result += `**DOI:** ${article.doi}\n`;
      }
    
      if (article.pmc_id) {
        result += `**PMC ID:** ${article.pmc_id}\n`;
        result += `**Full Text Available:** Yes\n`;
        result += `**Full Text URL:** https://www.ncbi.nlm.nih.gov/pmc/articles/PMC${article.pmc_id}/\n\n`;
      }
    
      result += `\n**Abstract:**\n${article.abstract}\n\n`;
    
      if (article.full_text) {
        result += `**Full Text:**\n${article.full_text}\n\n`;
      } else if (article.pmc_id) {
        result += `**Note:** Full text is available but could not be automatically retrieved. `;
        result += `Please visit the PMC URL above to access the complete article.\n\n`;
      } else {
        result += `**Note:** Full text is not available in PubMed Central. `;
        result += `You may need institutional access or subscription to view the complete article.\n\n`;
      }
    
      return createMCPResponse(result);
    }
  • Helper function to parse PubMed EFetch XML response into structured PubMedArticle objects, extracting PMID, title, abstract, authors, journal, date, DOI, and PMC ID.
    export function parsePubMedXML(xmlText: string): PubMedArticle[] {
      const articles: PubMedArticle[] = [];
    
      // Split by article boundaries
      const articleMatches = xmlText.match(
        /<PubmedArticle>[\s\S]*?<\/PubmedArticle>/g,
      );
    
      if (!articleMatches) return articles;
    
      for (const articleXml of articleMatches) {
        try {
          // Extract PMID
          const pmidMatch = articleXml.match(/<PMID[^>]*>(\d+)<\/PMID>/);
          const pmid = pmidMatch?.[1];
          if (!pmid) continue;
    
          // Extract title
          const titleMatch = articleXml.match(
            /<ArticleTitle[^>]*>([^<]+)<\/ArticleTitle>/,
          );
          const title = titleMatch?.[1]?.trim() || "No title available";
    
          // Extract abstract
          let abstract = "No abstract available";
          const abstractMatch = articleXml.match(
            /<AbstractText[^>]*>([\s\S]*?)<\/AbstractText>/,
          );
          if (abstractMatch) {
            abstract = abstractMatch[1]
              .replace(/<[^>]*>/g, "") // Remove HTML tags
              .replace(/\s+/g, " ") // Normalize whitespace
              .trim();
          }
    
          // Extract authors
          const authors: string[] = [];
          const authorMatches = articleXml.match(/<Author[\s\S]*?<\/Author>/g);
          if (authorMatches) {
            for (const authorXml of authorMatches) {
              const lastNameMatch = authorXml.match(
                /<LastName>([^<]+)<\/LastName>/,
              );
              const firstNameMatch = authorXml.match(
                /<ForeName>([^<]+)<\/ForeName>/,
              );
              const collectiveNameMatch = authorXml.match(
                /<CollectiveName>([^<]+)<\/CollectiveName>/,
              );
    
              if (collectiveNameMatch) {
                authors.push(collectiveNameMatch[1].trim());
              } else if (lastNameMatch && firstNameMatch) {
                authors.push(
                  `${firstNameMatch[1].trim()} ${lastNameMatch[1].trim()}`,
                );
              } else if (lastNameMatch) {
                authors.push(lastNameMatch[1].trim());
              }
            }
          }
    
          // Extract journal information
          let journal = "Journal information not available";
          const journalMatch = articleXml.match(/<Title>([^<]+)<\/Title>/);
          if (journalMatch) {
            journal = journalMatch[1].trim();
          }
    
          // Extract publication date
          let publicationDate = "Date not available";
          const yearMatch = articleXml.match(/<Year>(\d{4})<\/Year>/);
          const monthMatch = articleXml.match(/<Month>(\d{1,2})<\/Month>/);
          const dayMatch = articleXml.match(/<Day>(\d{1,2})<\/Day>/);
    
          if (yearMatch) {
            const year = yearMatch[1];
            const month = monthMatch?.[1]?.padStart(2, "0") || "01";
            const day = dayMatch?.[1]?.padStart(2, "0") || "01";
            publicationDate = `${year}-${month}-${day}`;
          }
    
          // Extract DOI
          let doi: string | undefined;
          const doiMatch = articleXml.match(
            /<ELocationID[^>]*EIdType="doi"[^>]*>([^<]+)<\/ELocationID>/,
          );
          if (doiMatch) {
            doi = doiMatch[1].trim();
          }
    
          // Extract PMC ID
          let pmc_id: string | undefined;
          const pmcIdPatterns = [
            /<ArticleId[^>]*IdType="pmc"[^>]*>PMC(\d+)<\/ArticleId>/i,
            /<ArticleId[^>]*IdType="pmc"[^>]*>(\d+)<\/ArticleId>/i,
          ];
          for (const pattern of pmcIdPatterns) {
            const pmcMatch = articleXml.match(pattern);
            if (pmcMatch) {
              pmc_id = pmcMatch[1].trim();
              break;
            }
          }
    
          articles.push({
            pmid,
            title,
            abstract,
            authors,
            journal,
            publication_date: publicationDate,
            doi,
            pmc_id,
          });
        } catch (error) {
          console.error("Error parsing individual article:", error);
        }
      }
    
      return articles;
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JamesANZ/medical-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server