PyEuropePMC

Registre officiel Recherche et web

Europe PMC search, search analytics, full text, enrichment, PICO, MeSH, data links, export, auth

Que pouvez-vous faire avec PyEuropePMC ?

  • Europe PMC search with plain queries or a fluent QueryBuilder, pagination, and results as JSON, XML or Dublin Core. [Search guide](https://github.com/JonasHeinickeB...
  • Ten more sources in one search, with duplicates merged: PubMed, arXiv, ClinicalTrials.gov, OpenAlex, Semantic Scholar, CORE, DBLP, DOAJ, HAL and Zenodo. Semantic Scholar needs the semanticscholar extra and CORE an API key. [Multi-source search](https:...
  • Full text: XML (Europe PMC first, then other open sources), PDF and HTML, plus bulk PDF downloads from the Europe PMC FTP site. Full-text retrieval
  • JATS XML parsing: metadata, authors, tables, figures and references; plain text and Markdown; typed sections for retrieval-augmented generation (RAG); JATS normalization and BioC export. [XML parsing](https://github.com/JonasHeinickeBio/pyEuropePMC/blob...
  • Text-mining annotations for genes, diseases, chemicals and their relationships. Examples
  • Citations and metadata: walk citation graphs, and enrich records from Crossref, Unpaywall, OpenAlex, Semantic Scholar, DataCite, ORCID, ROR and iCite. [Citation walking](https://github.com/JonasHeinickeBio/pyEuropePMC/blob/main/docs/features/citation-wa...
  • Analysis: pandas DataFrames, citation statistics, duplicate detection, plots, and PRISMA-style search logs for systematic reviews. Analytics, [Review tracki...
  • RDF knowledge graphs from parsed articles, mapped by the rdf_map.yml that ships with the package; pass RDFMapper(config_path=...) or `PipelineConfig(rdf_co...

Installation

Ajoutez ceci à la configuration MCP de votre client (Claude Desktop : claude_desktop_config.json ; Cursor : .cursor/mcp.json ; VS Code et les autres utilisent la même forme « mcpServers »).

PYPI package pyeuropepmc
Claude Code
claude mcp add pyeuropepmc -e 'PYEUROPEPMC_MCP_LOG_LEVEL=INFO' -e 'SEMANTIC_SCHOLAR_API_KEY=<your semantic_scholar_api_key>' -e 'OPENAI_API_KEY=<your openai_api_key>' -e 'OPENAI_BASE_URL=<OPENAI_BASE_URL>' -e 'OPENAI_MODEL=gpt-4o-mini' -e 'UNPAYWALL_EMAIL=<UNPAYWALL_EMAIL>' -- uvx pyeuropepmc==4.5.0 mcp
Configuration JSON (Claude Desktop, Cursor, VS Code)
{
    "mcpServers": {
        "pyeuropepmc": {
            "command": "uvx",
            "args": [
                "pyeuropepmc==4.5.0",
                "mcp"
            ],
            "env": {
                "PYEUROPEPMC_MCP_LOG_LEVEL": "INFO",
                "SEMANTIC_SCHOLAR_API_KEY": "<your semantic_scholar_api_key>",
                "OPENAI_API_KEY": "<your openai_api_key>",
                "OPENAI_BASE_URL": "<OPENAI_BASE_URL>",
                "OPENAI_MODEL": "gpt-4o-mini",
                "UNPAYWALL_EMAIL": "<UNPAYWALL_EMAIL>"
            }
        }
    }
}

Variables d'environnement

  • PYEUROPEPMC_MCP_LOG_LEVEL Log level, written to stderr: DEBUG, INFO, WARNING or ERROR.
  • SEMANTIC_SCHOLAR_API_KEY secret Optional. Raises the Semantic Scholar rate limit used by citation_snowball and the semantic_scholar source of unified_search; without it requests are throttled and may get HTTP 429.
  • OPENAI_API_KEY secret Optional. Enables the LLM-powered tools (analyze_citations, literature_review, paper_screening, ...) with any OpenAI-compatible API. Needs the agentic extra.
  • OPENAI_BASE_URL Optional. Base URL of an OpenAI-compatible API for the LLM tools.
  • OPENAI_MODEL Optional. Model for the LLM tools.
  • UNPAYWALL_EMAIL Optional. Your contact e-mail address, sent with each Unpaywall request (their terms ask for one). Needed by the find_open_access tool only; there is no default.

Documentation

Tirée du README du projet sur GitHub, actualisée chaque semaine. Les liens ouvrent GitHub.

Sommaire
  1. PyEuropePMC
  2. ✨ Features
  3. 📦 Installation
  4. 🚀 Quick start
  5. 🔒 Safe XML parsing
  6. 💻 Command line
  7. 🤖 MCP server
  8. ⚙️ Configuration
  9. 📚 Documentation
  10. 📊 Performance
  11. 🚀 pyEuropePMC Benchmark Suite
  12. 📊 Summary
  13. ArticleClient_NoCache
  14. ArticleClient_Cached
  15. SearchClient_NoCache
  16. SearchClient_Cached
  17. FullTextClient_NoCache
  18. FullTextClient_Cached
  19. 🔁 Cache vs No-Cache Comparison
  20. ⚙️ How to reproduce
  21. 🤝 Contributing
  22. 📝 Citation
  23. 📄 License

PyEuropePMC

PyEuropePMC is a Python client for Europe PMC. It searches the literature, downloads open-access full text, and parses JATS XML into metadata, plain text and structured sections. It also ships a command-line tool and an MCP server for AI agents.

✨ Features

  • Europe PMC search with plain queries or a fluent QueryBuilder, pagination, and results as JSON, XML or Dublin Core. Search guide
  • Ten more sources in one search, with duplicates merged: PubMed, arXiv, ClinicalTrials.gov, OpenAlex, Semantic Scholar, CORE, DBLP, DOAJ, HAL and Zenodo. Semantic Scholar needs the semanticscholar extra and CORE an API key. Multi-source search
  • Full text: XML (Europe PMC first, then other open sources), PDF and HTML, plus bulk PDF downloads from the Europe PMC FTP site. Full-text retrieval
  • JATS XML parsing: metadata, authors, tables, figures and references; plain text and Markdown; typed sections for retrieval-augmented generation (RAG); JATS normalization and BioC export. XML parsing, JATS normalization
  • Text-mining annotations for genes, diseases, chemicals and their relationships. Examples
  • Citations and metadata: walk citation graphs, and enrich records from Crossref, Unpaywall, OpenAlex, Semantic Scholar, DataCite, ORCID, ROR and iCite. Citation walking, Enrichment
  • Analysis: pandas DataFrames, citation statistics, duplicate detection, plots, and PRISMA-style search logs for systematic reviews. Analytics, Review tracking
  • RDF knowledge graphs from parsed articles, mapped by the rdf_map.yml that ships with the package; pass RDFMapper(config_path=...) or PipelineConfig(rdf_config_path=...) to use your own. Data models and RDF
  • A command line and an MCP server, described below.

📦 Installation

pip install pyeuropepmc                              # core
pip install "pyeuropepmc[analytics,visualization]"   # add extras (quote the brackets)
pip install "pyeuropepmc[all]"                       # every optional feature

PyEuropePMC supports Python 3.10 to 3.13. The core install covers search, full-text download, XML parsing, RDF, the command line and the MCP server. The extras add:

ExtraInstallsAdds
analyticspandas, numpyto_dataframe, citation_statistics, quality_metrics, remove_duplicates and CSV export
visualizationmatplotlib, seaborn, pandas, numpyThe plot_* functions and create_summary_dashboard
exportpandas, tabulate, xlsxwriterExcel and Markdown-table export (pyeuropepmc.utils.export)
semanticscholarsemanticscholarSemanticScholarClient and the semantic_scholar search source
enrichmentsemanticscholarSemantic Scholar data in PaperEnricher
bibliographybibtexparserBibTeX parsing, validation and RIS/CSL conversion, including the bib_* MCP tools
zoteropyzoteroThe Zotero client
agenticopenai, langchain, langchain-openai, langgraph, jinja2LLM analysis, the LLM MCP tools and pyeuropepmc claim
uiflask, tornadoThe web UI (pyeuropepmc claim serve)
signingcryptographySigned search logs for systematic reviews
benchmarkhuggingface-hubDownloading the published benchmark datasets (pyeuropepmc benchmark download)
rdfnothingKept so existing installs keep working; the core rdflib writes JSON-LD itself
standardjupyterlab, notebook, ipykernel, ipython, ipywidgets, matplotlib, seaborn, pandas, numpy, tabulate, xlsxwriter, requests-cache, richJupyter plus the analytics, plotting and export packages
allall of the aboveEvery optional feature

Upgrading from 1.x? The migration guide lists what moved into extras.

🚀 Quick start

from pyeuropepmc import FullTextClient, FullTextXMLParser, QueryBuilder, SearchClient

# 1. Search Europe PMC for open-access articles ("CRISPR AND OPEN_ACCESS:y")
query = QueryBuilder().keyword("CRISPR").and_().field("open_access", True).build()
with SearchClient() as search:
    hits = search.search_and_parse(query, pageSize=10)
pmcid = next(hit["pmcid"] for hit in hits if hit.get("pmcid"))

# 2. Download the article's JATS XML (raises an error if no source has it)
with FullTextClient() as fulltext:
    xml_path = fulltext.download_xml_by_pmcid(pmcid, output_path=f"articles/{pmcid}.xml")

# 3. Parse it
parser = FullTextXMLParser(xml_path.read_text(encoding="utf-8"))
metadata = parser.extract_metadata()
print(metadata["title"])
print(", ".join(metadata["authors"][:3]))
text = parser.to_plaintext()  # or parser.to_markdown()

# 4. Collect text blocks with their section path, ready to chunk and embed for RAG
chunks = []
for section in parser.get_full_text_sections_structured():
    if section["section_type"] not in ("front", "body"):  # skip back matter and appendices
        continue
    for block in section["content"]:
        if block.get("text"):
            path = section.get("section_path", section["title"])
            chunks.append({"section": path, "type": block["type"], "text": block["text"]})
print(f"{len(chunks)} text blocks")

section_type is front for the title and abstract, then body, back or appendix. Each block has a type such as paragraph, list, table or figure. Tables and figures carry label and caption, and tables also carry rows. The XML parsing guide covers the other extractors.

🔒 Safe XML parsing

PyEuropePMC parses every XML document it reads with defusedxml: full-text articles, Europe PMC search results, arXiv and PubMed responses, and local files. A DOCTYPE declaration is accepted, but a document that declares entities, internal or external, is refused rather than expanded; FullTextXMLParser raises ParsingError. lxml is not used and does not need to be installed.

💻 Command line

CommandWhat it does
pyeuropepmc unified_searchsearch several sources with deduplication, or compare-sources to see each source's results
pyeuropepmc normalizeTurn JATS XML into clean text (text), sections (sections) or BioC JSON (bioc); classify a heading; batch a directory
pyeuropepmc benchmarkScore and profile the XML parser on a local folder or a published dataset
pyeuropepmc claimCheck the claims in a text against Europe PMC literature with LLM agents (needs the agentic extra and an API key)
pyeuropepmc unified_search search "CRISPR base editing" --limit 10 --output results.json
pyeuropepmc benchmark list-datasets

unified_search search queries Europe PMC, PubMed and arXiv unless you pass --source. Add --help to any command for its options.

🤖 MCP server

pyeuropepmc-mcp serves 47 tools over the Model Context Protocol, so an AI agent can search the literature, read papers and export references. The server is part of the core install.

JobWhat the tools do
SearchEurope PMC and ten more sources with duplicates merged, hit counts, author search, ClinicalTrials.gov
Summarise a searchPapers per year, citation thresholds and open-access share counted by Europe PMC over the whole result set, plus journals, authors, publication types, countries, funders and citation statistics from the first records, each labelled exact or sample, without returning the records
Check a queryA linter for the mistakes Europe PMC silently accepts (it answers a different query instead of an error), a query builder, a PubMed translator, and a recall check against papers you already know
Plan a searchA research question split into PICO, PICOS, PICOT or SPIDER elements (verbatim, missing ones reported, never invented) with a checked query, and MeSH headings, tree numbers and entry terms for search terms, offline from a bundled snapshot or from NLM on request
Look up papersMetadata for up to 100 papers by PMID, PMCID or DOI in one call; enrich one paper with citation impact, funders, institutions, open-access status and retractions from Europe PMC, Crossref, OpenAlex, Semantic Scholar and iCite
ReadOpen-access full text as Markdown or typed sections, with a section filter and a size cap, or its sentences tagged as background, method, result, limitation and so on whatever the headings are called; figures, tables and supplementary files; free copies of other papers through Unpaywall
Entities and dataGenes, chemicals and diseases text-mined from a paper, papers that mention an entity, and the data a paper links to (accession numbers, BioStudies, model-organism databases)
CitationsCiting papers, references and citation-graph walking
ExportBibTeX, RIS, CSL-JSON, CSV, JSON or Markdown for a search or a list of papers
Resources and promptsepmc://paper/{pmcid} (full text), /references and /outline as attachable resources, and ready workflows for a literature review, a critical appraisal and a citation trace
DiagnoseA service-status probe and cache controls
Local and LLM toolsA local full-text index, bibliography conversion, and LLM-powered analysis

pip install "pyeuropepmc[all]" enables every tool; otherwise the bib_* tools need bibliography, and the LLM tools need agentic plus an OpenAI-compatible API key (see Configuration below).

pyeuropepmc-mcp                                # stdio, for Claude Desktop and similar clients
pyeuropepmc mcp                                # the same server, through the CLI
pyeuropepmc-mcp --transport streamable-http    # HTTP at http://127.0.0.1:8000/mcp

For Claude Desktop and other clients that start the server themselves:

{
  "mcpServers": {
    "pyeuropepmc": {
      "command": "pyeuropepmc-mcp"
    }
  }
}

Without an install, "command": "uvx" with "args": ["pyeuropepmc", "mcp"] does the same; this is what the MCP Registry entry tells clients to run. For Claude Code, one command adds it:

claude mcp add pyeuropepmc -- uvx pyeuropepmc mcp

Cursor (.cursor/mcp.json) and VS Code (.vscode/mcp.json, under "servers" instead of "mcpServers") take the same command and args.

The server has no authentication of its own, so keep the HTTP transport on 127.0.0.1 or put an authenticating proxy in front of it; behind a proxy that forwards its public host name, add --allowed-host mcp.example.org. The MCP server guide walks through the common workflows, and the tool reference lists every tool. The server is listed in the MCP Registry as io.github.JonasHeinickeBio/pyeuropepmc.

⚙️ Configuration

Europe PMC needs no API key. Other services read these environment variables. A value passed in code, such as FullTextClient(email=...) or EnrichmentConfig(unpaywall_email=...), takes precedence.

VariableUsed for
UNPAYWALL_EMAIL, CROSSREF_EMAILContact e-mail for Unpaywall and Crossref. FullTextClient needs one of them for its Unpaywall fallback, and so does the MCP tool find_open_access.
OPENALEX_EMAIL, DATACITE_EMAIL, ROR_EMAIL, ROR_CLIENT_IDThe other enrichment sources
SEMANTIC_SCHOLAR_API_KEYSemantic Scholar, with higher rate limits
CORE_API_KEYThe core search source
OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MODELLLM features, with any OpenAI-compatible API; the model defaults to gpt-4o-mini
ZOTERO_API_KEY, ZOTERO_LIBRARY_ID, ZOTERO_LOCALThe Zotero client
PYEUROPEPMC_MCP_TRANSPORT, PYEUROPEPMC_MCP_HOST, PYEUROPEPMC_MCP_PORT, PYEUROPEPMC_MCP_LOG_LEVELDefaults for the pyeuropepmc-mcp options

The pyeuropepmc command also loads the first .env file it finds in the current directory, one of its parents, or ~/.config/pyeuropepmc/. Variables that are already set keep their values.

📚 Documentation

The guides are in docs/. Start with installation and the quick start, or go straight to the API reference, caching, the example scripts and the changelog.

Parser benchmark. On the 55 JATS articles in benchmark_xmls/xml, the parser's mean composite quality score is 0.998 (measured on 2026-09-15). The benchmarking guide explains the metrics. To reproduce the score from a source checkout, or to score a published dataset:

pyeuropepmc benchmark run local --local-path benchmark_xmls/xml --limit 55
pyeuropepmc benchmark download PLOS_1000   # 1,000 articles, 1.3 GB
pyeuropepmc benchmark run PLOS_1000

The weekly benchmark workflow times the API clients and opens a pull request that refreshes the section below.

📊 Performance

Last updated: 2026-09-14

MetricValue
Benchmarked methods10
Total requests224
Mean call time0.871s
Success rate100.0%

📈 View full benchmark report

🚀 pyEuropePMC Benchmark Suite

Generated: 2026-09-14 07:45:39

📊 Summary

  • Total Benchmarks: 6
  • Total Methods: 10
  • Successful Runs: 10
  • Failed Runs: 0
  • Cache Enabled: 5

ArticleClient_NoCache

MethodMean TimeStd DevMean MemoryCacheRequestsErrors
get_article_details1.707s0.212s0.0MB❌310

p50: 1.620s · p95: 2.235s · ops: 0.59/s · runs: 30 | get_citations | 1.789s | 0.318s | 0.0MB | ❌ | 31 | 0 | p50: 1.666s · p95: 2.851s · ops: 0.56/s · runs: 30

ArticleClient_Cached

MethodMean TimeStd DevMean MemoryCacheRequestsErrors
get_article_details<1ms<1ms0.0MB✅10

p50: 17µs · p95: 29µs · ops: 53390.19/s · runs: 30 | get_citations | <1ms | <1ms | 0.0MB | ✅ | 1 | 0 | p50: 19µs · p95: 30µs · ops: 48437.33/s · runs: 30

SearchClient_NoCache

MethodMean TimeStd DevMean MemoryCacheRequestsErrors
search2.074s0.262s0.1MB❌310

p50: 1.964s · p95: 2.673s · ops: 0.48/s · runs: 30 | get_hit_count | 2.085s | 0.562s | 0.0MB | ❌ | 31 | 0 | p50: 1.933s · p95: 3.668s · ops: 0.48/s · runs: 30

SearchClient_Cached

MethodMean TimeStd DevMean MemoryCacheRequestsErrors
search<1ms<1ms0.0MB✅10

p50: 109µs · p95: 134µs · ops: 8795.90/s · runs: 30 | get_hit_count | <1ms | <1ms | 0.0MB | ✅ | 1 | 0 | p50: 111µs · p95: 137µs · ops: 8603.62/s · runs: 30

FullTextClient_NoCache

MethodMean TimeStd DevMean MemoryCacheRequestsErrors
check_fulltext_availability1.050s0.148s0.1MB❌930

p50: 0.998s · p95: 1.388s · ops: 0.95/s · runs: 30

FullTextClient_Cached

MethodMean TimeStd DevMean MemoryCacheRequestsErrors
check_fulltext_availability<1ms<1ms0.0MB✅30

p50: 20µs · p95: 21µs · ops: 48496.45/s · runs: 30

🔁 Cache vs No-Cache Comparison

ArticleClient — cached vs no-cache
MethodNo-Cache MeanCached MeanSpeedup (no/cache)
get_article_details1.707s<1ms>17074.4x
get_citations1.789s<1ms>17888.5x
FullTextClient — cached vs no-cache
MethodNo-Cache MeanCached MeanSpeedup (no/cache)
check_fulltext_availability1.050s<1ms>10504.7x
SearchClient — cached vs no-cache
MethodNo-Cache MeanCached MeanSpeedup (no/cache)
get_hit_count2.085s<1ms17941.89x
search2.074s<1ms18245.92x
  • Average speedup for SearchClient (no-cache / cached): 18093.91x

Notes: Means are computed over measured iterations; '-' indicates missing data. Values like '<1ms' indicate very fast cached responses. Speedups shown as lower-bounds when cached times are too small to measure precisely.

⚙️ How to reproduce

Run the modular benchmark locally and regenerate these artifacts:

pytest tests/benchmark_article_client.py::test_modular_benchmark_system -m benchmark --force-enable-socket --timeout=3600
  • Detailed JSON results: MODULAR_BENCHMARK_RESULTS.json

🤝 Contributing

Contributions are welcome. The development guide covers setup, testing, code quality and the release process. Report bugs and suggest features in the issue tracker.

📝 Citation

If PyEuropePMC supports your research, please cite it and give the version you used (pip show pyeuropepmc prints it):

@software{pyeuropepmc,
  author = {Heinicke, Jonas},
  title  = {{PyEuropePMC}: a Python toolkit for Europe PMC},
  url    = {https://github.com/JonasHeinickeBio/pyEuropePMC}
}

The literature itself comes from Europe PMC; please acknowledge it as your data source.

📄 License

PyEuropePMC is released under the MIT License. Articles you retrieve keep their own licences, which FullTextXMLParser.extract_license() reads from the XML.

Questions fréquentes

Qu'est-ce que PyEuropePMC ?

Europe PMC search, search analytics, full text, enrichment, PICO, MeSH, data links, export, auth

Comment installer PyEuropePMC ?

Il s'exécute sur votre machine. Dans Claude Code : claude mcp add pyeuropepmc -e 'PYEUROPEPMC_MCP_LOG_LEVEL=INFO' -e 'SEMANTIC_SCHOLAR_API_KEY=<your semantic_scholar_api_key>' -e 'OPENAI_API_KEY=<your openai_api_key>' -e 'OPENAI_BASE_URL=<OPENAI_BASE_URL>' -e 'OPENAI_MODEL=gpt-4o-mini' -e 'UNPAYWALL_EMAIL=<UNPAYWALL_EMAIL>' -- uvx pyeuropepmc==4.5.0 mcp. Pour les autres clients, collez la configuration JSON de cette page dans leurs réglages MCP.

Faut-il une clé API pour PyEuropePMC ?

Oui. Il attend SEMANTIC_SCHOLAR_API_KEY, OPENAI_API_KEY, à renseigner dans sa configuration.

PyEuropePMC est-il open source ?

Oui. Son code est sur GitHub sous licence MIT.

Qui maintient PyEuropePMC ?

Il est publié par JonasHeinickeBio. AI.tn le référence sans le maintenir ni le recommander.

Issu du registre MCP officiel. Être listé n'est pas une recommandation : vérifiez le code et les permissions d'un serveur avant de lui donner accès à vos données.