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