MCP_Res / mcp /pubmed.py
mgbam's picture
Update mcp/pubmed.py
ca336b6 verified
# mcp/pubmed.py
import httpx
import xmltodict
import os
PUBMED_ESEARCH = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi"
PUBMED_EFETCH = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi"
PUB_KEY = os.environ.get("PUB_KEY")
async def fetch_pubmed(query: str, max_results: int = 5):
"""Fetch latest PubMed articles for the query."""
async with httpx.AsyncClient() as client:
params = {
"db": "pubmed",
"term": query,
"retmax": max_results,
"retmode": "json",
"api_key": PUB_KEY
}
resp = await client.get(PUBMED_ESEARCH, params=params)
ids = resp.json()["esearchresult"]["idlist"]
if not ids:
return []
efetch_params = {
"db": "pubmed",
"id": ",".join(ids),
"retmode": "xml",
"api_key": PUB_KEY
}
efetch_resp = await client.get(PUBMED_EFETCH, params=efetch_params)
articles = xmltodict.parse(efetch_resp.text)["PubmedArticleSet"].get("PubmedArticle", [])
if not isinstance(articles, list): # Single article edge case
articles = [articles]
results = []
for a in articles:
art = a["MedlineCitation"]["Article"]
# Robustly extract publication year or date
published = ""
article_date = art.get("ArticleDate")
if isinstance(article_date, list) and article_date:
published = article_date[0].get("Year", "")
elif isinstance(article_date, dict):
published = article_date.get("Year", "")
else:
# Fallback to PubDate in Journal > JournalIssue > PubDate
pubdate = art.get("Journal", {}).get("JournalIssue", {}).get("PubDate", {})
published = pubdate.get("Year", "") or pubdate.get("MedlineDate", "")
# Robustly extract authors
authors_raw = art.get("AuthorList", {}).get("Author", [])
if isinstance(authors_raw, dict):
authors_raw = [authors_raw]
authors = ", ".join([
f"{a.get('LastName', '')} {a.get('ForeName', '')}".strip()
for a in authors_raw if a.get("LastName") and a.get("ForeName")
]) if authors_raw else "Unknown"
# Robustly extract summary/abstract
abstract = art.get("Abstract", {}).get("AbstractText", "")
if isinstance(abstract, list):
# List of dicts or strings
summary = " ".join(
a.get("#text", str(a)) if isinstance(a, dict) else str(a)
for a in abstract
)
elif isinstance(abstract, dict):
summary = abstract.get("#text", "")
else:
summary = abstract or ""
pmid = a["MedlineCitation"]["PMID"]
if isinstance(pmid, dict):
pmid = pmid.get("#text", "")
results.append({
"title": art["ArticleTitle"],
"authors": authors,
"summary": summary,
"link": f"https://pubmed.ncbi.nlm.nih.gov/{pmid}/",
"published": published,
"source": "PubMed"
})
return results