pubmed-clinical-mcp
# PubMed Clinical MCP
`pubmed-clinical-mcp` is a lightweight Model Context Protocol (MCP) server for clinical biomedical literature retrieval. It gives MCP-compatible clients reusable tools for PubMed/MEDLINE search, article metadata retrieval, PubMed Central full text, full-text availability checks, related articles, clinical query building, PICO extraction, article ranking, and evidence summarization.
This project is designed for clinical evidence support and research workflows. It is **not** a diagnosis system, treatment recommendation system, paywall bypasser, or institutional-library automation tool.
## Why This Exists
Many medical agents need reliable access to public biomedical literature, but PubMed handling often gets mixed into one-off application code. This package separates that capability into a standalone MCP server so tools like Codex, Claude Desktop, Cursor, or other MCP clients can call PubMed-focused tools directly.
## Features
- PubMed/MEDLINE search through NCBI E-utilities.
- PubMed article fetching with title, abstract, authors, journal, year, DOI, PMCID, MeSH terms, publication types, and URL.
- PubMed Central open-access full-text section retrieval when legally available.
- Related PubMed article lookup through NCBI `elink`.
- Unpaywall DOI availability checks for legal open-access links.
- Clinical query builder for natural-language medical questions.
- Article ranking against a clinical question with relevance reasons.
- Rough PICO extraction from abstracts or article passages.
- Citation-backed evidence table and limitations summary.
- Retry/backoff on `429` and transient server failures.
- Optional local JSON cache.
- Tests use local fixtures, so CI does not need live API access.
## Tool List
| Tool | Purpose |
| --- | --- |
| `build_clinical_query` | Convert a natural-language clinical question into a PubMed-ready query. |
| `search_pubmed` | Search PubMed and return PMIDs plus lightweight metadata. |
| `fetch_pubmed_articles` | Fetch detailed PubMed article metadata for PMIDs. |
| `search_and_fetch_pubmed` | Build a query, search, fetch, rank, and return citations in one call. |
| `fetch_pmc_full_text` | Fetch PMC full-text sections when a PMCID is legally available. |
| `check_full_text_availability` | Check PMC and Unpaywall for legal full-text access. |
| `find_related_articles` | Find related PubMed articles using NCBI `elink`. |
| `rank_articles` | Rank article objects against a clinical question. |
| `extract_pico` | Extract rough population/intervention/comparator/outcome fields. |
| `summarize_evidence` | Produce an evidence table, citation-backed findings, and limitations. |
## Install
```bash
git clone https://github.com/jxia622/pubmed-clinical-mcp.git
cd pubmed-clinical-mcp
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
```
## Optional Environment Variables
No paid keys are required. For low-volume demos, the server can run without API keys.
```bash
export NCBI_EMAIL="you@example.com"
export NCBI_API_KEY="optional_free_ncbi_key"
export UNPAYWALL_EMAIL="you@example.com"
export PUBMED_MCP_CACHE_PATH=".cache/pubmed_clinical_mcp.json"
```
Notes:
- `NCBI_EMAIL` is recommended for NCBI E-utilities usage.
- `NCBI_API_KEY` is optional and raises NCBI rate limits.
- `UNPAYWALL_EMAIL` is required for Unpaywall checks.
- `PUBMED_MCP_CACHE_PATH` enables a simple local JSON cache.
## Run The MCP Server
```bash
pubmed-clinical-mcp
```
or:
```bash
python -m pubmed_clinical_mcp.server
```
## Example MCP Client Config
```json
{
"mcpServers": {
"pubmed-clinical": {
"command": "python",
"args": ["-m", "pubmed_clinical_mcp.server"],
"env": {
"NCBI_EMAIL": "you@example.com",
"PUBMED_MCP_CACHE_PATH": ".cache/pubmed_clinical_mcp.json"
}
}
}
}
```
## Example Tool Calls
### Build a PubMed query
```json
{
"natural_language_question": "Why might a diabetic foot ulcer be Wagner grade 2 instead of grade 1?",
"filters": {
"english_only": true,
"year_from": 2020
}
}
```
Example output:
```json
{
"query": "(\"diabetic foot\"[Title/Abstract] OR \"diabetic foot ulcer\"[Title/Abstract]) AND (Wagner[Title/Abstract] OR classification[Title/Abstract] OR staging[Title/Abstract]) AND english[Language] AND (\"2020\"[Date - Publication] : \"3000\"[Date - Publication])",
"explanation": [
"Mapped diabetic foot ulcer + Wagner wording to title/abstract terms for classification and staging."
],
"filters": {
"english_only": true,
"year_from": 2020
}
}
```
### Search and fetch ranked PubMed articles
```json
{
"clinical_question": "What evidence supports using wound depth in diabetic foot ulcer severity assessment?",
"filters": {
"english_only": true
},
"max_results": 10
}
```
Returns:
- `query_used`
- `query_explanation`
- `ranked_articles`
- `citations`
### Fetch PMC full text
```json
{
"pmcid": "PMC9446755"
}
```
Returns parsed sections when the article is available in PubMed Central.
## Architecture
```mermaid
flowchart LR
Client["MCP client"] --> Server["pubmed-clinical-mcp server"]
Server --> Query["clinical query builder"]
Server --> PubMed["NCBI PubMed E-utilities"]
Server --> PMC["PubMed Central XML"]
Server --> Unpaywall["Unpaywall API"]
Server --> Rank["ranking + PICO + summarization helpers"]
Server --> Cache["optional JSON cache"]
```
Core modules:
```text
src/pubmed_clinical_mcp/
server.py # MCP tool definitions
sources/pubmed.py # PubMed esearch, efetch, elink
sources/pmc.py # PMC full-text XML parsing
sources/unpaywall.py # DOI open-access checks
clinical/query_builder.py # natural language -> PubMed query
clinical/ranking.py # relevance ranking
clinical/pico.py # rough PICO extraction
clinical/summarizer.py # evidence table + limitations
```
## Development
Tests use fixtures and do not call live APIs:
```bash
PYTHONPATH=src python3 -m unittest discover -s tests
```
Compile check:
```bash
PYTHONPATH=src python3 -m compileall src tests
```
## API And Rate-Limit Notes
- PubMed and PMC use NCBI E-utilities.
- NCBI allows higher request rates when `NCBI_API_KEY` is configured.
- The server includes basic retry/backoff for `429` and transient `5xx` failures.
- The cache is intentionally simple and optional. It is not a vector database.
## Safety And Scope
This server:
- retrieves public biomedical literature metadata and legal open-access text;
- does not diagnose;
- does not prescribe treatment;
- does not bypass paywalls;
- does not scrape publisher websites;
- does not automate university or hospital library login;
- does not store institutional credentials.
Any clinical interpretation should be performed by qualified clinicians using the retrieved sources and appropriate guidelines.
TDQS
Scored across 10 tools
Each tool has a clearly distinct purpose: building queries, checking availability, extracting PICO, fetching full text, fetching articles, finding related articles, ranking, searching (with and without full pipeline), and summarizing. No ambiguity.
All tool names follow a consistent verb_noun pattern in snake_case (e.g., build_clinical_query, fetch_pubmed_articles, summarize_evidence). No deviations or mixed conventions.
10 tools is well-scoped for a clinical PubMed assistant. Each tool serves a distinct step in the research workflow without unnecessary overlap or missing critical functionality.
The tool set covers the full clinical evidence retrieval workflow: natural language query conversion, search, article fetch, full text retrieval, PICO extraction, ranking, summarization, and related article discovery. No obvious gaps.