get_full_text
Retrieve open-access full text articles from PubMed Central using PubMed IDs. Returns complete article content when available or provides alternative access information.
Instructions
Retrieve the full text of an article from PubMed Central (PMC) if available.
Only open-access articles archived in PMC have a full text. Subscription-only articles will return a link to PubMed instead.
Args: pmid: The PubMed ID of the article.
Returns: The full text (title, abstract, and body sections) when the article is open-access in PMC, or a helpful message with links otherwise.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| pmid | Yes |
Implementation Reference
- main.py:444-539 (handler)The `get_full_text` function is decorated with `@mcp.tool()` and implements the logic to fetch full-text content from PubMed Central (PMC) based on a provided PubMed ID (PMID). It first retrieves the PMC ID from the PubMed record and then fetches the full text from PMC if it's available.
@mcp.tool() async def get_full_text(pmid: str) -> str: """Retrieve the full text of an article from PubMed Central (PMC) if available. Only open-access articles archived in PMC have a full text. Subscription-only articles will return a link to PubMed instead. Args: pmid: The PubMed ID of the article. Returns: The full text (title, abstract, and body sections) when the article is open-access in PMC, or a helpful message with links otherwise. """ pmid = pmid.strip() if not pmid.isdigit(): return _err(f"Invalid PMID: {pmid!r}. A PMID must be a numeric string.") try: # 1) Retrieve the PubMed record to find the PMC ID fetch_resp = await _get( "efetch.fcgi", {"db": "pubmed", "id": pmid, "retmode": "xml", "rettype": "abstract"}, ) root = _require_xml(fetch_resp, f"efetch PMID {pmid}") article_xml = root.find(".//PubmedArticle") if article_xml is None: return _err(f"No article found for PMID {pmid}.") pmc_id: Optional[str] = None for id_el in article_xml.findall(".//ArticleId"): if id_el.get("IdType") == "pmc" and id_el.text: pmc_id = id_el.text.strip() break if not pmc_id: title_el = article_xml.find(".//ArticleTitle") title = "".join(title_el.itertext()).strip() if title_el is not None else "" msg = [f"Full text not available in PubMed Central for PMID {pmid}."] if title: msg.append(f"Title: {title}") msg.append( "The article may be subscription-only or not yet indexed in PMC.\n" f"PubMed page: https://pubmed.ncbi.nlm.nih.gov/{pmid}/" ) return "\n".join(msg) # 2) Fetch full-text XML from PMC numeric_id = pmc_id.replace("PMC", "") pmc_resp = await _get( "efetch.fcgi", {"db": "pmc", "id": numeric_id, "retmode": "xml", "rettype": "full"}, ) try: pmc_root = ET.fromstring(pmc_resp.text) except ET.ParseError as exc: return ( f"Full text is available in PMC but could not be parsed.\n" f"Reason: {exc}\n" f"PMC URL: https://www.ncbi.nlm.nih.gov/pmc/articles/{pmc_id}/" ) sections: list[str] = [] title_el = pmc_root.find(".//article-title") if title_el is not None: sections.append(f"TITLE\n{''.join(title_el.itertext()).strip()}\n") abstract_el = pmc_root.find(".//abstract") if abstract_el is not None: sections.append("ABSTRACT\n" + "".join(abstract_el.itertext()).strip() + "\n") body = pmc_root.find(".//body") if body is not None: for sec in body.findall(".//sec"): title_el = sec.find("title") if title_el is not None: sections.append(f"\n{''.join(title_el.itertext()).upper()}") for p in sec.findall("p"): para = "".join(p.itertext()).strip() if para: sections.append(para) if not sections: return ( f"Full text is available in PMC but the content could not be extracted.\n" f"PMC URL: https://www.ncbi.nlm.nih.gov/pmc/articles/{pmc_id}/" ) header = f"=== Full Text — PMID {pmid} | {pmc_id} ===\n" return header + "\n".join(sections) except PubMedError as exc: return _err(str(exc))