File size: 3,343 Bytes
de2e45e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3a900e3
de2e45e
 
 
 
3a900e3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ca336b6
 
 
 
 
3a900e3
 
 
 
 
 
 
 
 
de2e45e
 
3a900e3
 
 
 
de2e45e
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 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