# PubMed Search (pypi · pubmed-search-mcp)

Multi-source biomedical literature search: PubMed, Europe PMC, OpenAlex, full text, citations

- Trust score: 77/100 (medium)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-10-25

## Components

- pypi · `pubmed-search-mcp`: 77/100 (this document), [markdown](https://verifymcp.io/servers/u9401066-pubmed-search-mcp/pubmed-search-mcp.md), [page](https://verifymcp.io/servers/u9401066-pubmed-search-mcp/pubmed-search-mcp)

## Channel facts

- Registry: `pypi`
- Package: `pubmed-search-mcp`
- Version: `0.8.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-10-25.

- **Supply Chain Security**: 100/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - Runs hatchling.build at install time, a recognised build step with no custom scripting around it.
  - 3 of 48 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 97/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to u9401066/pubmed-search-mcp).
  - Clear OSI-approved license (Apache-2.0).
  - Actively maintained (last published 4 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 69/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 18872 tokens (~343/item across 55 items; 41 tools + 14 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 0/100
  - Stability not yet verified: not enough scan history yet (needs a 30-day window).
- **Tool Coverage**: 68/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 4% of tool parameters carry a description.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - All 2 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.
  - An AI judge read all 43 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a current MCP spec version (2026-07-28).

**Unverified: 1 category.** A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### How do I install the PubMed Search MCP server?

PubMed Search runs locally as a PyPI package, launched with uvx pubmed-search-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add u9401066-pubmed-search-mcp -- uvx pubmed-search-mcp
```

### Cursor

```json
{
  "mcpServers": {
    "u9401066-pubmed-search-mcp": {
      "command": "uvx",
      "args": [
        "pubmed-search-mcp"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "u9401066-pubmed-search-mcp": {
      "command": "uvx",
      "args": [
        "pubmed-search-mcp"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add u9401066-pubmed-search-mcp -- uvx pubmed-search-mcp
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "u9401066-pubmed-search-mcp": {
      "type": "local",
      "command": [
        "uvx",
        "pubmed-search-mcp"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add u9401066-pubmed-search-mcp --command uvx --arg pubmed-search-mcp
```

### Hermes

```yaml
mcp_servers:
  u9401066-pubmed-search-mcp:
    command: "uvx"
    args: ["pubmed-search-mcp"]
```

### Netclaw

```json
{
  "McpServers": {
    "u9401066-pubmed-search-mcp": {
      "Transport": "stdio",
      "Command": "uvx",
      "Arguments": [
        "pubmed-search-mcp"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add u9401066-pubmed-search-mcp -t stdio -c uvx -a pubmed-search-mcp
```

### Other

```json
{
  "mcpServers": {
    "u9401066-pubmed-search-mcp": {
      "command": "uvx",
      "args": [
        "pubmed-search-mcp"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-10-21 (score 77, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-10-20 (score 62)

First indexed and scored.

## MCP tools (41)

### `unified_search` (~2427 tokens)

🔍 Unified Search - Single entry point for multi-source academic search.

Automatically analyzes your query and searches the best sources.
No need to choose between PubMed, OpenAlex, CrossRef, etc.

═══════════════════════════════════════════════════════════════════
WHAT IT DOES:
═══════════════════════════════════════════════════════════════════
1\. Analyzes your query (complexity, intent, PICO elements)
2\. Automatically selects best sources based on query type
3\. Searches multiple sources in parallel
4\. Deduplicates and merges results
5\. Ranks by configurable criteria
6\. Enriches with OA links (Unpaywall)
7\. Auto-detects ICD-9/10 codes and expands to MeSH terms
8\. Optionally searches preprints (arXiv, medRxiv, bioRxiv)

═══════════════════════════════════════════════════════════════════
EXAMPLES (most calls only need 1-2 params):
═══════════════════════════════════════════════════════════════════

Simple (1 param):
    unified_search("remimazolam ICU sedation")

With limit (2 params):
    unified_search("machine learning in anesthesia", limit=20)

Specify sources:
    unified_search("CRISPR gene therapy", sources="pubmed,openalex")

Auto minus one source:
    unified_search("sepsis biomarkers", sources="auto,-semantic_scholar")

Search all enabled sources except enrichment-only CrossRef:
    unified_search("icu sedation", sources="all,-crossref")

Clinical filters:
    unified_search("diabetes treatment",
                  filters="year:2020-2025,age_group:aged,clinical_query:therapy")

Include preprints + shallow search:
    unified_search("COVID-19 vaccine", options="preprints,shallow")

Provider-native semantic retrieval (OpenAlex capability):
    unified_search("mechanisms of treatment resistance",
                  sources="openalex", options="native_semantic")

Reproducible systematic retrieval (bulk/cursor where supported):
    unified_search("melanoma AND immunotherapy",
                  sources="openalex,semantic_scholar",
                  options="sys…

Input parameters:

- `dry_run`
- `filters`
- `fulltext`
- `limit`
- `options`
- `output_format`
- `pipeline`
- `query` (string)
- `ranking`
- `sources`
- `stop_at` (string)

### `analyze_search_query` (~117 tokens)

Analyze a search query without executing the search.

Useful for understanding how unified_search will process your query
before actually running it.

Args:
    query: The search query to analyze

Returns:
    Analysis including:
    - Complexity level (SIMPLE/MODERATE/COMPLEX/AMBIGUOUS)
    - Intent (LOOKUP/EXPLORATION/COMPARISON/SYSTEMATIC)
    - PICO elements (if detected)
    - Recommended sources
    - Recommended strategies

Input parameters:

- `query` (string, required)

### `validate_pico_plan` (~155 tokens)

Validate agent-provided P/I/C/O and return a runnable PICO pipeline.

\``question_type`` and ``profile`` are closed enums. ``sources`` is an
explicit array of supported unified-search providers; malformed values
fail instead of being silently replaced. When ``question_type`` is
omitted, the application service infers it from the clinical question.

Input parameters:

- `c`
- `c_query`
- `description` (string)
- `i`
- `i_query`
- `limit`
- `o`
- `o_query`
- `p`
- `p_query`
- `profile`
- `question_type`
- `sources`

### `generate_search_queries` (~812 tokens)

Gather search intelligence for a topic - returns RAW MATERIALS for Agent to decide.

This tool provides the BUILDING BLOCKS for search, not finished queries.
The Agent decides how to use them.

══════════════════════════════════════════════════════════════════════
TWO USAGE MODES:
══════════════════════════════════════════════════════════════════════

MODE 1: KEYWORD SEARCH (single topic)
─────────────────────────────────────
User: "搜尋 remimazolam 的文獻"

Step 1: generate_search_queries("remimazolam")
Step 2: Build a Boolean query from returned materials
Step 3: analyze_search_query(query="<combined_boolean_query>")
Step 4: unified_search(query="<combined_boolean_query>")

���═════════════════════════════════════════════════════════════════════

MODE 2: PICO SEARCH (clinical question)
───────────────────────────────────────
User: "remimazolam 在 ICU 鎮靜比 propofol 好嗎？會減少 delirium 嗎？"

Step 1: Agent extracts P/I/C/O from the clinical question, then calls
        validate_pico_plan(description=..., p=..., i=..., c=..., o=...) to
        validate the structured handoff and get a runnable PICO pipeline.

Step 2: For EACH PICO element, call generate_search_queries() IN PARALLEL:
        - generate_search_queries("ICU patients")     → P materials
        - generate_search_queries("remimazolam")      → I materials
        - generate_search_queries("propofol")         → C materials
        - generate_search_queries("delirium")         → O materials

Step 3: Combine materials using Boolean logic:
        High precision: (P_terms) AND (I_terms) AND (C_terms) AND (O_terms)
        Recall-oriented: (P_terms) AND (I_terms OR C_terms); validate against eligible seed papers

Step 4: Add Clinical Query filter if appropriate:
        - filters="clinical_query:therapy"   → 治療效果比較
        - filters="clinical_query:diagnosis" → 診斷相關
        - filters="clinical_query:prognosis" → 預後相關
        - filters="clinical_query:etiology"  → 病因相關

    Step 5: Validate the final query with analyze_sea…

Input parameters:

- `check_spelling`
- `include_suggestions`
- `strategy`
- `topic` (string, required)

### `find_related_articles` (~500 tokens)

Find articles related to a given PubMed article.
Uses PubMed's "Related Articles" feature to find similar papers.

═══════════════════════════════════════════════════════════════
🔗 CITATION NETWORK EXPLORATION WORKFLOW
═══════════════════════════════════════════════════════════════

This is ONE of THREE tools for exploring citation networks:

1️⃣ find_related_articles() ← YOU ARE HERE
   │  📌 Algorithm-based similarity (like PubMed "Similar Articles")
   │  📌 Finds papers with similar topics, MeSH terms, authors
   │  📌 Good for: Discovering related research you might have missed
   └─► Returns: Similar papers (not based on citations)

2️⃣ find_citing_articles()
   │  📌 Forward citation search (who cited THIS paper?)
   │  📌 Finds papers published AFTER the source article
   │  📌 Good for: Tracking impact, finding follow-up studies
   └─► Returns: Papers that cite this article

3️⃣ get_article_references()
   │  📌 Backward citation search (what did THIS paper cite?)
   │  📌 Finds papers published BEFORE the source article
   │  📌 Good for: Finding foundational papers, methodology sources
   └─► Returns: This article's bibliography

═══════════════════════════════════════════════════════════════
EXAMPLE WORKFLOW:
═══════════════════════════════════════════════════════════════

Step 1: Start with a key paper
    find_related_articles(pmid="23132851")
    → Find similar research directions

Step 2: Explore backward (foundations)
    get_article_references(pmid="23132851")
    → Find the foundational papers it builds on

Step 3: Explore forward (impact)
    find_citing_articles(pmid="23132851")
    → Find how the field developed after this paper

Args:
    pmid: PubMed ID of the source article ("12345678" or "PMID:12345678").
    limit: Maximum number of related articles to return (1-50, default: 5).

Returns:
    List of related articles with details.

Input parameters:

- `limit`
- `pmid` (string, required): Complete identifier string; optional identifier prefix, official article URL, or inline backticks. No numbers, foreign hosts, URL queries/fragments or partial identifiers.

### `find_citing_articles` (~373 tokens)

Find articles that cite a given PubMed article.
Uses PubMed Central's citation data to find papers that reference this article.

═══════════════════════════════════════════════════════════════
📈 FORWARD CITATION SEARCH (Impact Tracking)
═══════════════════════════════════════════════════════════════

Direction: Source Paper → Papers that cite it (FORWARD in time)

USE CASES:
──────────
\- 🔬 Track research impact: Who built on this work?
\- 📊 Find follow-up studies: What happened after this discovery?
\- 🔄 Identify controversies: Papers that challenge or refute findings
\- 📚 Literature review: Ensure you have the latest developments

COMPLEMENTARY TOOLS:
────────────────────
\- get_article_references(): BACKWARD search (what this paper cited)
\- find_related_articles(): Similar papers (topic-based, not citation-based)

═══════════════════════════════════════════════════════════════
EXAMPLE:
═══════════════════════════════════════════════════════════════

\# Find papers that cite a landmark CRISPR paper
find_citing_articles(pmid="23287718", limit=20)
→ Returns papers published AFTER 2012 that reference this work

\# Then analyze citation metrics
get_citation_metrics(pmids="last")
→ See which citing papers are most influential

Args:
    pmid: PubMed ID of the source article ("12345678" or "PMID:12345678").
    limit: Maximum number of citing articles to return (1-100, default: 10).

Returns:
    List of citing articles with details.

Input parameters:

- `limit`
- `pmid` (string, required): Complete identifier string; optional identifier prefix, official article URL, or inline backticks. No numbers, foreign hosts, URL queries/fragments or partial identifiers.

### `get_article_references` (~403 tokens)

Get the references (bibliography) of a PubMed article.

Returns the list of articles that this paper cites in its bibliography.
This is the OPPOSITE of find_citing_articles:
\- get_article_references: Papers THIS article cites (backward in time)
\- find_citing_articles: Papers that cite THIS article (forward in time)

═══════════════════════════════════════════════════════════════
📚 BACKWARD CITATION SEARCH (Foundation Discovery)
═══════════════════════════════════════════════════════════════

Direction: Source Paper → Papers it cited (BACKWARD in time)

USE CASES:
──────────
\- 🏛️ Find foundational papers: Core works the field builds on
\- ⚗️ Methodology sources: Papers describing techniques used
\- 📖 Background reading: Build understanding of a topic
\- 🔍 Verify claims: Check sources for specific assertions

═══════════════════════════════════════════════════════════════
EXAMPLE WORKFLOW:
═══════════════════════════════════════════════════════════════

\# Start with a recent review article
get_article_references(pmid="38123456", limit=50)
→ Get the bibliography of this review

\# Find most-cited foundational papers
get_citation_metrics(pmids="last", sort_by="citation_count")
→ Identify which references are the most influential

\# Read a foundational paper
fetch_article_details(pmids="12345678")
→ Get full details of an important reference

Args:
    pmid: PubMed ID of the source article ("12345678" or "PMID:12345678").
    limit: Maximum number of references to return (1-100, default: 20).

Returns:
    List of referenced articles with details.

Input parameters:

- `limit`
- `pmid` (string, required): Complete identifier string; optional identifier prefix, official article URL, or inline backticks. No numbers, foreign hosts, URL queries/fragments or partial identifiers.

### `fetch_article_details` (~172 tokens)

Fetch detailed information for one or more PubMed articles.

Args:
    pmids: PubMed IDs - accepts multiple formats:
           - "12345678" (single)
           - "12345678,87654321" (comma-separated)
           - "PMID:12345678" (with prefix)
           - ["12345678", "87654321"] (list)
           - '["12345678", "87654321"]' (JSON array string)
           - Newlines, semicolons, pipes, and Chinese separators are also accepted.
           Inputs are string-only and fail as a complete batch when any PMID is invalid.

Returns:
    Detailed information for each article.

Input parameters:

- `output_format`
- `pmids` (required): Explicit PMIDs; last is not supported.

### `get_citation_metrics` (~409 tokens)

Get citation metrics from NIH iCite for articles.

Returns field-normalized citation data including:
\- citation_count: Total number of citations
\- relative_citation_ratio (RCR): Field-normalized metric (1.0 = average)
\- nih_percentile: Percentile ranking (0-100)
\- citations_per_year: Citation velocity
\- apt: Approximate Potential to Translate (clinical relevance 0-1)

Can sort and filter results by citation metrics.

Args:
    pmids: PubMed IDs - accepts multiple formats:
           - "12345678,87654321" (comma-separated)
           - ["12345678", "87654321"] (list)
           - '["12345678", "87654321"]' (JSON array string)
           - "PMID:12345678" (with prefix)
           - "last" to use PMIDs from the last search
           Batches are fail-closed and limited to 1,000 items before deduplication.
    sort_by: Metric to sort by:
        - "citation_count": Raw citation count (default)
        - "relative_citation_ratio": Field-normalized (recommended)
        - "nih_percentile": Percentile ranking
        - "citations_per_year": Citation velocity
    min_citations: Filter out articles with fewer citations
    min_rcr: Filter out articles with RCR below threshold (e.g., 1.0 = average)
    min_percentile: Filter out articles below percentile (e.g., 50 = top half)

Returns:
    Articles with citation metrics, sorted and filtered as requested.
    iCite transport or response failures return an explicit retryable
    error and are never rendered as an empty/unindexed result.

Input parameters:

- `min_citations`
- `min_percentile`
- `min_rcr`
- `output_format`
- `pmids` (required)
- `sort_by`

### `verify_reference_list` (~300 tokens)

Verify a plain-text reference list against PubMed evidence.

First version scope:
    - Reference-list verification only
    - Client supplies the extracted reference list text
    - Backend parses entries and resolves them via PMID / DOI / ECitMatch

Second version scope:
    - Adds unresolved review workflow for ``partial_match`` and ``unresolved`` rows
    - Returns a manual-review queue with retry queries and review checklist
    - Supports human-in-the-loop acceptance/rejection in client-side workflows

Args:
    reference_text: Plain-text references, ideally one per line or a
        numbered reference list extracted from a file. Limited to
        200,000 characters / 400,000 UTF-8 bytes; each entry is limited
        to 4,000 characters / 8,000 UTF-8 bytes.
    source_name: Optional single-line file label for reporting (up to
        255 characters / 512 UTF-8 bytes).
    max_references: Hard input-entry limit from 1 through 200. Inputs
        above the selected limit are rejected instead of truncated.

Returns:
    JSON verification report with parsed fields, matched PubMed evidence,
    per-reference verification status, and explicit
    ``source_unavailable`` / ``not_checked`` rows when evidence could
    not be assessed.

Input parameters:

- `max_references`
- `reference_text` (string, required)
- `source_name` (string)

### `prepare_export` (~561 tokens)

Export citations to reference manager formats.

╔═══════════════════════════════════════════════════════════════════╗
║  RECOMMENDED: Use source="official" (default) for best quality   ║
╚═══════════════════════════════════════════════════════════════════╝

\## When to Use
\- Exporting references to EndNote, Zotero, Mendeley
\- Creating BibTeX for LaTeX documents
\- Generating citation lists for manuscripts

\## Source Options
\| Source     | Formats            | Quality    | Speed  |
\|------------|--------------------|------------|--------|
\| official   | ris, medline, csl  | ★���★★★     | Fast   |
\| local      | ris, bibtex, csv, medline, json | ★★★★ | Fast |

\## Format Selection Guide
\- ris: EndNote, Zotero, Mendeley (official recommended)
\- medline: NBIB format for PubMed tools
\- csl: JSON for programmatic citation styling
\- bibtex: LaTeX documents (local only)
\- csv: Data analysis, Excel (local only)

Args:
    pmids: Articles to export. Accepts:
           - "last" → results from previous search
           - "12345678,87654321" → comma-separated PMIDs
           - ["12345678", "87654321"] → list of PMIDs
           - '["12345678", "87654321"]' → JSON array string
           - "PMID:12345678" → with prefix
    format: Export format (default: "ris")
           - official API: ris, medline, csl
           - local only: bibtex, csv, json
    include_abstract: Include abstracts in output (default: True).
        False requires source="local"; official payloads are returned unmodified.
    source: Citation source (default: "official")
           - "official": NCBI Citation API (recommended, best quality)
           - "local": Local formatting (more formats, offline capable)

Returns:
    JSON with status and export_text containing formatted citations.

Examples:
    # Export last search results (recommended)
    prepare_export(pmids="last", format="ris")

    # Export specific PMIDs to BibTeX
    prepare_export(pmids="12345678,87654321", format="bibtex", source="local")…

Input parameters:

- `format`
- `include_abstract`
- `pmids` (required)
- `source`

### `save_literature_notes` (~500 tokens)

Save searched articles as guided local wiki/Foam/Markdown notes.

\## When to Use
\- After unified_search, persist the selected literature into a local note library.
\- Give agents a structured alternative to generic write_file calls.
\- Create wiki notes with Foam-compatible wikilinks, MedPaper-like reference notes, and frontmatter.
\- Use stable wiki/Foam link targets and return wiki_validation for unresolved-link checks.

\## Local Directory Resolution
1\. output_dir argument, if provided
2\. PUBMED_NOTES_DIR environment variable
3\. PUBMED_WORKSPACE_DIR/references
4\. PUBMED_DATA_DIR/references

\## Authenticated Service Boundary
Remote authenticated callers cannot choose output_dir or template_file.
Their notes always go to references/ under the current tenant's installed
SessionManager data root; process-wide notes/workspace environment paths
are intentionally ignored.

Args:
    pmids: Articles to save. Accepts "last", delimited PMID text, a string array, or a JSON array string.
    output_dir: Optional target folder for notes.
    note_format: "wiki" (default, Foam-compatible), "foam", "markdown", or "medpaper".
    include_abstract: Include abstracts in article notes.
    overwrite: Overwrite existing per-article notes when filenames collide.
    create_index: Create a collection index note linking saved articles.
    collection_name: Optional title/file stem for the index note.
    template_file: Optional Markdown template with placeholders like {title}, {pmid}, {citation_key}.
    include_csl_json: Write references.csl.json beside notes for citation-manager handoff.

Returns:
    JSON with written/skipped files, index information, and wiki_validation.
    Local callers receive filesystem paths. Authenticated callers receive
    tenant-relative logical locators and never receive server host paths.

Examples:
    save_literature_notes(pmids="last")
    save_literature_notes(pmids="last", note_format="medpaper", output_dir="./references")
    save_literature_notes(pm…

Input parameters:

- `collection_name`
- `create_index`
- `include_abstract`
- `include_csl_json`
- `note_format`
- `output_dir`
- `overwrite`
- `pmids`
- `template_file`

### `get_fulltext` (~493 tokens)

🔥 Enhanced multi-source fulltext retrieval.

Automatically tries multiple sources to find the best fulltext:
1\. Europe PMC (if PMC ID available)
2\. Unpaywall (finds OA versions via DOI)
3\. Institutional direct/EZproxy fetch (when DOI-backed and enabled)
4\. CORE (open-access repository metadata and available text)

With extended_sources=True, also searches:
5\. CrossRef (publisher links)
6\. DOAJ (Gold OA journals)
7\. Zenodo (research repository)
8\. PubMed LinkOut (external providers)
9\. Semantic Scholar, OpenAlex, arXiv, bioRxiv, medRxiv

\``source`` is a discriminated identifier object, so the schema itself
requires exactly one explicit PMID, PMCID, or DOI kind.

Args:
    source: One object such as {"kind":"pmid","value":"12345678"},
            {"kind":"pmcid","value":"PMC7096777"}, or
            {"kind":"doi","value":"10.1001/jama.2024.1234"}.
    sections: Filter body sections (e.g., "introduction,methods,results").
        Missing titles are reported with available sections; abstracts are
        never substituted for missing body evidence.
    include_pdf_links: Include PDF download links (default: True). False
        skips link enrichment when structured fulltext is already available.
    include_figures: Include figure metadata with image URLs (default: False)
    extended_sources: Search the extended downloader chain after the standard policy (default: False)
    output_format: Response format - "markdown" (default), "json", or "toon"
    allow_browser_session: Control browser-session fallback.
        - True: force broker fallback when configured
        - False: disable broker fallback
        - None: use auto mode from broker configuration

Returns:
    Fulltext content with PDF links from all available sources.

Example:
    get_fulltext(source={"kind":"pmcid","value":"PMC7096777"})
    get_fulltext(source={"kind":"doi","value":"10.1038/s41586-021-03819-2"})

Input parameters:

- `allow_browser_session`
- `extended_sources`
- `include_figures`
- `include_pdf_links`
- `output_format`
- `sections`
- `source` (required)

### `get_text_mined_terms` (~195 tokens)

Get text-mined annotations from Europe PMC.

Returns entities extracted from the article text including genes, diseases,
chemicals, organisms, and more. ``source`` is exactly one PMID or PMCID.

Args:
    source: {"kind":"pmid","value":"12345678"} or
            {"kind":"pmcid","value":"PMC7096777"}.
    semantic_type: Filter by entity type. Options:
        - "GENE_PROTEIN": Genes and proteins
        - "DISEASE": Diseases and conditions
        - "CHEMICAL": Drugs and chemicals
        - "ORGANISM": Species and organisms
        - "GO_TERM": Gene Ontology terms
        - None: Return all types (default)

Returns:
    List of text-mined entities with counts and sections.

Input parameters:

- `output_format`
- `semantic_type`
- `source` (required)

### `get_article_figures` (~213 tokens)

Get structured figure metadata (label, caption, image URL) and PDF links from a PMC Open Access article.

Returns all figures with their captions and direct image URLs, plus
PDF download links for the complete article.

\``source`` is a discriminated identifier object, so the schema itself
requires exactly one explicit PMID or PMCID.

Args:
    source: {"kind":"pmcid","value":"PMC12086443"} or
            {"kind":"pmid","value":"40384072"}.
    include_subfigures: Parse sub-figures (e.g., Figure 3A, 3B) as separate entries.
    include_tables: Also extract tables rendered as images.

Returns:
    Structured figure data with image URLs, captions, and PDF links.

Example:
    get_article_figures(source={"kind":"pmcid","value":"PMC12086443"})

Input parameters:

- `include_subfigures`
- `include_tables`
- `output_format`
- `source` (required)

### `search_gene` (~151 tokens)

Search NCBI Gene database for gene information.

═══════════════════════════════════════════════════════════════
USE CASES:
═══════════════════════════════════════════════════════════════
\- Look up gene function and description
\- Find gene aliases and official symbols
\- Get chromosome location
\- Find genes by name or function

Args:
    query: Gene name, symbol, or function keyword
    organism: Filter by organism (e.g., "human", "Homo sapiens", "mouse")
    limit: Maximum results (1-50)

Returns:
    JSON with gene records including symbols, names, locations

Input parameters:

- `limit`
- `organism`
- `query` (string, required)

### `get_gene_details` (~65 tokens)

Get detailed information about a gene by NCBI Gene ID.

Args:
    gene_id: NCBI Gene ID (from search results or known)

Returns:
    JSON with gene details including symbol, name, summary, location

Input parameters:

- `gene_id` (string, required)

### `get_gene_literature` (~92 tokens)

Get PubMed articles linked to a gene.

This uses NCBI's curated gene-to-publication links, which are
more precise than keyword searches.

Args:
    gene_id: NCBI Gene ID
    limit: Maximum PubMed IDs to return (1-100)

Returns:
    JSON with linked PubMed IDs

Input parameters:

- `gene_id` (string, required)
- `limit`

### `search_compound` (~116 tokens)

Search PubChem for chemical compounds.

═══════════════════════════════════════════════════════════════
USE CASES:
═══════════════════════════════════════════════════════════════
\- Look up drug/compound information
\- Find molecular formula and structure
\- Get compound synonyms and identifiers
\- Research chemical properties

Args:
    query: Compound name or description
    limit: Maximum results (1-50)

Returns:
    JSON with compound records including names, formulas, properties

Input parameters:

- `limit`
- `query` (string, required)

### `get_compound_details` (~54 tokens)

Get detailed information about a compound by PubChem CID.

Args:
    cid: PubChem Compound ID

Returns:
    JSON with compound details including formula, SMILES, properties

Input parameters:

- `cid` (string, required)

### `get_compound_literature` (~80 tokens)

Get PubMed articles linked to a compound.

Uses NCBI's curated compound-to-publication links.

Args:
    cid: PubChem Compound ID
    limit: Maximum PubMed IDs to return (1-100)

Returns:
    JSON with linked PubMed IDs

Input parameters:

- `cid` (string, required)
- `limit`

### `search_clinvar` (~122 tokens)

Search ClinVar for clinical variants.

═══════════════════════════════════════════════════════════════
USE CASES:
═══════════════════════════════════════════════════════════════
\- Look up clinical significance of genetic variants
\- Find variants associated with diseases
\- Research gene-disease associations
\- Get variant pathogenicity classifications

Args:
    query: Gene name, variant, or disease condition
    limit: Maximum results (1-50)

Returns:
    JSON with variant records including significance and conditions

Input parameters:

- `limit`
- `query` (string, required)

### `build_citation_tree` (~680 tokens)

Build a citation tree (network) from a single article.

🌳 Creates a visual citation network showing research lineage:
\- Forward (citing): Who cites this paper? (newer research)
\- Backward (references): What does this paper cite? (foundational work)

⚠️ IMPORTANT: Only accepts ONE PMID at a time to control API load.
For multiple papers, call this tool separately for each.

📊 Output Formats (output_format parameter):
\- "cytoscape": Cytoscape.js format (default, academic standard)
\- "g6": AntV G6 format (modern, high-performance)
\- "d3": D3.js force graph format (flexible, Observable)
\- "vis": vis-network format (simple, quick prototypes)
\- "graphml": GraphML XML (desktop tools: Gephi, yEd, VOSviewer)
\- "mermaid": Mermaid diagram (VS Code preview, Markdown)

Args:
    pmid: Single PubMed ID (e.g., "12345678").
          Only ONE PMID accepted - do NOT pass multiple.
    depth: How many levels to traverse (1-3, default 2).
           - depth=1: Direct citations/references only
           - depth=2: Also get citations of citations (recommended)
           - depth=3: Maximum depth (can be slow, ~100+ API calls)
    direction: Which direction to build the tree:
           - "forward": Only citing articles (who cites this)
           - "backward": Only references (what this cites)
           - "both": Both directions (default, recommended)
    limit_per_level: Max articles to fetch per node per level (default 5)
    output_format: Graph format for visualization (default "cytoscape")
           - "cytoscape": Cytoscape.js (academic standard, bioinformatics)
           - "g6": AntV G6 (modern, TypeScript, great for large graphs)
           - "d3": D3.js force layout (most flexible, Observable notebooks)
           - "vis": vis-network (simple and easy)
           - "graphml": GraphML XML (Gephi, VOSviewer, yEd, Pajek)
           - "mermaid": Mermaid diagram (preview in VS Code Markdown)

Returns:
    Markdown summary followed by JSON with graph data in the requested forma…

Input parameters:

- `depth`
- `direction`
- `limit_per_level`
- `output_format`
- `pmid` (string, required): Complete identifier string; optional identifier prefix, official article URL, or inline backticks. No numbers, foreign hosts, URL queries/fragments or partial identifiers.

### `build_research_chronicle` (~703 tokens)

Build a persisted, versioned, evidence-backed Research Chronicle.

A chronicle is the durable record of how a research topic evolved, and
the single entry point for research-evolution work (it replaces the older
one-shot timeline tools). It is stored with a monotonic revision number,
so re-running it later produces revision N+1 and you can diff revisions
to see exactly what changed.

The primary axis is chronological; research branches are a secondary
organizing dimension. Both come from the same stored snapshot, and
preserve shared provenance in `output="timeline"` and `output="tree"`.
Agreement between projections is not independent evidence verification.

Every entry carries:
\- a one-sentence claim with inline citations
\- supporting / contradicting / updating evidence articles
\- a research branch (lineage) assignment
\- provenance and a confidence score

The typed provenance graph links Topic → Branch → Entry → EvidenceArticle
and is validated against edge invariants. The audit reports evidence
coverage, identifier coverage, branch coverage, graph integrity, and
chronology gaps, so you always know how complete the picture is.

Args:
    topic: Research topic (drug, gene, disease, intervention).
           Required unless `pmids` or a stored `chronicle_id` is supplied.
    pmids: Delimited PMIDs, a string array or JSON array string, or "last" to chronicle the previous
           search results instead of running a new search.
    max_events: Maximum timeline events to consider (topic mode).
                Omit to inherit the continued revision's value, else 30.
    min_year: Earliest publication year to include (topic mode).
    max_year: Latest publication year to include (topic mode).
    chronicle_id: Continue an existing chronicle (creates revision N+1)
                  instead of deriving the ID from the topic. Passing it
                  alone re-runs the stored scope, so the resulting diff
                  shows research movement rather than a changed…

Input parameters:

- `chronicle_id`
- `max_events`
- `max_year`
- `min_year`
- `output`
- `pmids`
- `topic`

### `read_research_chronicle` (~491 tokens)

Read stored Research Chronicles: load, list, diff, narrate, analyze, compare.

This is the read facade over chronicles created by
\`build_research_chronicle`. Chronicles persist across sessions, so you
can revisit a topic weeks later and see precisely what moved. Because the
evidence is already stored, analysis and comparison are instant and do
not re-run any search.

Actions:
\- "load": read one revision (defaults to latest) in any output format
\- "list": list stored chronicles, most recently updated first
\- "diff": compare two revisions — added, not observed/removed from the
  later view, and updated entries, plus evidence churn, branch churn,
  and the audit status transition. Absence does not prove retirement.
\- "narrate": render evidence-backed Markdown where every claim carries
  its entry ID and article identifiers
\- "milestones": entry-type and status distribution, per-year activity,
  evidence quality, and landmark entries for one chronicle
\- "compare": compare 2-5 chronicles side by side, including the evidence
  articles they share

The required ``request`` discriminator makes invalid field combinations
unrepresentable. ``compare`` takes one typed ``selection`` containing
either 2-5 topic strings or 2-5 Chronicle IDs.

Returns:
    Markdown or JSON text depending on the action and output format.

Examples:
    read_research_chronicle(request={"action":"list"})
    read_research_chronicle(request={"action":"load","chronicle_id":"remimazolam-9f2b1c4d","output":"tree"})
    read_research_chronicle(request={"action":"diff","chronicle_id":"remimazolam-9f2b1c4d","from_revision":1})
    read_research_chronicle(request={"action":"narrate","chronicle_id":"remimazolam-9f2b1c4d","mode":"full"})
    read_research_chronicle(request={"action":"milestones","chronicle_id":"remimazolam-9f2b1c4d"})
    read_research_chronicle(request={"action":"compare","selection":{"kind":"topics","values":["remimazolam","propofol"]}})

Input parameters:

- `request` (required)

### `prepare_figure_search` (~636 tokens)

Analyze a scientific figure or image for literature search.

═══════════════════════════════════════════════════════════════════════
🔬 VISION-TO-LITERATURE SEARCH (Experimental)
═══════════════════════════════════════════════════════════════════════

This tool enables searching for scientific literature based on images.

WORKFLOW (the host agent performs the analysis and search):
─────────────────────────────────────────────────────────
1\. Provide an image (URL or base64-encoded)
2\. This tool returns the image using MCP ImageContent protocol
3\. YOU (the Agent) analyze the image using your vision capabilities
4\. Extract relevant ENGLISH search terms from the image
5\. Call `search_biomedical_images()` or `unified_search()` with extracted
   terms when literature retrieval is within the user-requested scope
6\. Return both the analysis and search results to the user

⚠️ IMPORTANT RULES:
────────────────
\- ALL search queries must be in ENGLISH (Open-i requirement)
\- This tool returns an image and guidance; it does not invoke a vision model
\- The host agent controls any subsequent search within its permissions
\- If the image shows a medical condition, extract the medical term in English

SEARCH TYPES:
─────────────
\- "comprehensive": General analysis, extract all relevant terms (default)
\- "methodology": Focus on methods, equipment, techniques shown
\- "results": Focus on data, graphs, statistical findings
\- "structure": Focus on molecular/chemical structures
\- "medical": Focus on clinical/medical imaging findings

USE CASES:
──────────
\- 📊 Scientific figures → Find papers with similar data/charts
\- 🔬 Microscopy images → Find related research
\- 🧬 Molecular structures → Find papers about the compound
\- 📈 Graphs/plots → Find papers with similar analyses
\- 🏥 Medical images → Find case reports or clinical studies
\- ⚗️ Lab equipment → Find methodology papers

IMPORTANT:
──────────
Image observations are search hypotheses that require source verification.
Follow the user…

Input parameters:

- `context`
- `search_type`
- `source` (required)

### `configure_institutional_access` (~597 tokens)

Configure your institution's link resolver for full-text access.

═══════════════════════════════════════════════════════════════════════════════
🏛️ INSTITUTIONAL ACCESS CONFIGURATION
═══════════════════════════════════════════════════════════════════════════════

This tool configures OpenURL link resolver integration, allowing you to
access paywalled articles through your institution's library subscription.

Remote service callers may call this tool with no configuration
arguments to inspect the operator-installed configuration, but cannot
mutate the server-owned, deployment-wide OpenURL settings. Configure
those at deployment time or from a trusted local server instead.

═══════════════════════════════════════════════════════════════════════════════
HOW IT WORKS:
═══════════════════════════════════════════════════════════════════════════════

1\. Your library subscribes to journals through publishers
2\. Library provides a "Link Resolver" service (SFX, 360 Link, Primo, etc.)
3\. OpenURL passes article metadata to the resolver
4\. Resolver checks your subscriptions and provides full-text access

═══════════════════════════════════════════════════════════════════════════════
USAGE:
═══════════════════════════════════════════════════════════════════════════════

Option 1: Use a preset (easiest)
─────────────────────────────────
configure_institutional_access(preset="ntu")

Available presets:
\- 台灣: "ntu" (台大), "ncku" (成大), "nthu" (清大), "nycu" (陽明交大)
\- 美國: "harvard", "stanford", "mit", "yale"
\- 英國: "oxford", "cambridge"
\- 通用: "sfx", "360link", "primo" (需要 resolver_url)

Option 2: Custom URL
─────────────────────
configure_institutional_access(
    resolver_url="https://your.library.edu/openurl"
)

Option 3: Disable
─────────────────────
configure_institutional_access(enable=False)

═══════════════════════════════════════════════════════════════════════════════
FINDING YOUR RESOLVER URL:
═══════════════════════════════════════════════════════════════════════════════

1.…

Input parameters:

- `enable`
- `preset`
- `resolver_url`

### `get_institutional_link` (~290 tokens)

Generate institutional access link (OpenURL) for an article.

═══════════════════════════════════════════════════════════════════════════════
🔗 GET LIBRARY ACCESS LINK
═══════════════════════════════════════════════════════════════════════════════

Generate an OpenURL that will take you through your library's link resolver
to access the full text of an article.

PREREQUISITES:
─────────────────
Must first call configure_institutional_access() to set up your resolver.

USAGE:
─────────────────

With PMID (easiest):
    get_institutional_link(
        source={"kind": "pmid", "value": "38353755"}
    )

With DOI:
    get_institutional_link(
        source={"kind": "doi", "value": "10.1001/jama.2024.1234"}
    )

With full metadata (most reliable):
    get_institutional_link(
        source={
            "kind": "metadata",
            "title": "Some Article Title",
            "journal": "JAMA",
            "year": 2024,
            "volume": "331",
            "issue": "1",
            "pages": "45-52"
        }
    )

Args:
    source: Exactly one explicit PMID, DOI, or bounded metadata object.

Returns:
    OpenURL link or error message

Input parameters:

- `source` (required)

### `list_resolver_presets` (~88 tokens)

List available institutional link resolver presets.

═══════════════════════════════════════════════════════════════════════════════
📚 AVAILABLE RESOLVER PRESETS
═══════════════════════════════════════════════════════════════════════════════

These presets contain pre-configured URLs for common institutions.
Use them with configure_institutional_access(preset="name").

Returns:
    List of available presets with URLs

### `test_institutional_access` (~298 tokens)

Test your institutional link resolver configuration.

═══════════════════════════════════════════════════════════════════════════════
🧪 TEST INSTITUTIONAL ACCESS
═══════════════════════════════════════════════════════════════════════════════

Tests if your configured link resolver is:
1\. Properly configured
2\. Reachable (network connection)
3\. Returns a valid response

NOTE: This only tests if the resolver endpoint is reachable.
Actual full-text access depends on your institution's subscriptions.

═══════════════════════════════════════════════════════════════════════════════
FREE TEST OPTIONS:
═══════════════════════════════════════════════════════════════════════════════

If you don't have institutional access, you can test with:

1\. Use "test_free" preset (EBSCO public resolver):
   configure_institutional_access(preset="test_free")
   test_institutional_access()

2\. Most university resolvers will respond even without VPN,
   they just won't provide full-text (shows "Access options" page)

Args:
    pmid: PMID to use for testing (default: 38353755)

Returns:
    Test results including:
    - Configuration status
    - Network reachability
    - Generated OpenURL
    - Link to test manually

Input parameters:

- `pmid` (string): Complete identifier string; optional identifier prefix, official article URL, or inline backticks. No numbers, foreign hosts, URL queries/fragments or partial identifiers.

### `diagnose_institutional_access` (~410 tokens)

Diagnose why institutional fulltext access succeeds or fails for an article.

Runs up to three probes and reports each path's outcome:

1\. **Direct fetch** (Phase 1, IP-aware) — follows ``https://doi.org/<doi>``
   and classifies whether the publisher served fulltext, a paywall, or a
   login page. Works automatically when your network IP is on the
   publisher's institutional allow-list (campus / VPN).

2\. **EZproxy fetch** (Phase 2, BYO-cookie) — rewrites the publisher
   hostname to your library's EZproxy host and replays your exported
   browser session cookie. Configured via env vars:
   \- ``EZPROXY_HOST`` (e.g. ``ezproxy.lib.ntu.edu.tw``)
   \- ``EZPROXY_COOKIE_FILE`` (path to browser-exported cookies.json)
   \- ``EZPROXY_ENABLED=1``

3\. **OpenURL handoff** — generated for you to open manually in a browser
   when the automated paths fail.

Usage:
    diagnose_institutional_access(
        source={"kind": "doi", "value": "10.1097/ALN.0000000000003599"}
    )

    diagnose_institutional_access(
        source={"kind": "pmid", "value": "38353755"},
        try_ezproxy=False
    )

Args:
    source: Exactly one PMID or DOI. A PMID is resolved to a DOI when
        possible so direct and EZproxy probes can run.
    try_direct: Run the Phase 1 direct probe (default True).
    try_ezproxy: Run the Phase 2 EZproxy probe (default True).

Returns:
    Markdown report listing every probe's status, classification, and
    advice on the next action to take.

Input parameters:

- `source` (required)
- `try_direct`
- `try_ezproxy`

### `convert_icd_mesh` (~100 tokens)

Query the curated ICD/MeSH crosswalk in one explicit direction.

Use ``icd_to_mesh`` with one complete ICD-9-CM or ICD-10-CM code, or
\``mesh_to_icd`` with a MeSH term. The returned mapping is a limited
convenience crosswalk, not a substitute for a current licensed UMLS
terminology service.

Input parameters:

- `direction` (required)
- `value` (string, required)

### `search_biomedical_images` (~1281 tokens)

🖼️ Search biomedical images from NLM Open-i.

Searches medical/scientific images from Open-i and returns
image URLs with metadata (caption, article info, MeSH terms).

═══════════════════════════════════════════════════════════════        ⚠️ CRITICAL - LANGUAGE REQUIREMENT:
═══════════════════════════════════════════════════════════
Open-i ONLY supports English queries. If the user queries in
non-English (Chinese, Japanese, Korean, etc.), you MUST:
1\. Translate the query to English medical terminology first
2\. Then call this tool with the English query
Example: "喉頭水腫" → "laryngeal edema"
         "胸部X光肺炎" → "chest X-ray pneumonia"
The tool has built-in translation hints for common CJK medical
terms, but YOU should always verify the translation is correct.

═══════════════════════════════════════════════════════════        SOURCES:
═══════════════════════════════════════════════════════════════
\- Open-i (NLM): X-ray, microscopy, clinical images

═══════════════════════════════════════════════════════════════
EXAMPLES:
═══════════════════════════════════════════════════════════════

General image search:
    search_biomedical_images("chest pneumonia CT scan")

X-ray only:
    search_biomedical_images("fracture", image_type="x")

Microscopy images:
    search_biomedical_images("histology liver", image_type="mc")

Clinical teaching images (MedPix):
    search_biomedical_images("pneumothorax", collection="mpx")

Case reports with CC-BY license, sorted by date:
    search_biomedical_images(
        "lung cancer",
        article_type="cr",
        license_type="by",
        sort_by="d"
    )

Cardiology specialty images:
    search_biomedical_images("echocardiogram", specialty="c")

Video content only:
    search_biomedical_images("surgery technique", video_only=True)

═══════════════════════════════════════════════════════════════

Args:
    query: Search query (e.g., "chest X-ray pneumonia")
    image_type: Filter by image type (Open-i only):
        Positive filters…

Input parameters:

- `article_type`
- `collection`
- `hmp_type`
- `image_type`
- `license_type`
- `limit`
- `query` (string, required)
- `search_fields`
- `sort_by`
- `specialty`
- `subset`
- `video_only`

### `save_pipeline` (~228 tokens)

Save a pipeline configuration for later reuse.

The config format is identical to unified_search's pipeline parameter
(YAML or JSON). Saved pipelines can be loaded later by name:
    unified_search(pipeline="saved:weekly_remimazolam")

Args:
    name: Unique identifier (alphanumeric + hyphens/underscores, max 64 chars).
          Overwrites if name already exists (upsert semantics).
    config: Pipeline YAML/JSON string. Same format as unified_search pipeline param.
    tags: Bounded array of canonical tags (e.g., ["anesthesia", "sedation"]).
    description: Human-readable description of the pipeline's purpose.
    scope: Storage scope - "workspace" (project-level, git-trackable),
           "global" (user-level, cross-project), or "auto" (workspace if
           available, otherwise global). Default: "auto".

Returns:
    Confirmation with pipeline metadata.

Input parameters:

- `config` (string, required)
- `description` (string)
- `name` (string, required)
- `scope`
- `tags`

### `list_pipelines` (~83 tokens)

List all saved pipeline configurations.

Args:
    tag: Filter by tag (e.g., "sedation"). Empty = show all.
    scope: Filter by scope: "workspace", "global", or "" (show all).

Returns:
    Table of saved pipelines with name, scope, description, tags.

Input parameters:

- `scope`
- `tag` (string)

### `load_pipeline` (~131 tokens)

Load a pipeline configuration for review or editing.

Loads from either source:
\- Saved name: "weekly_remimazolam" or "saved:weekly_remimazolam"
\- Local-only file: "file:path/to/pipeline.yaml" (disabled for authenticated service callers)

The returned YAML can be reviewed, modified, and then:
\- Executed directly: unified_search(pipeline="<yaml>")
\- Saved with changes: save_pipeline(name="...", config="<yaml>")

Args:
    source: Pipeline source identifier (see above).

Returns:
    Full pipeline YAML content + metadata.

Input parameters:

- `source` (string, required)

### `delete_pipeline` (~78 tokens)

Permanently delete a saved pipeline configuration and execution history.

For the default tenant, any process-level schedule is removed only
after the stored pipeline deletion succeeds. Isolated tenants never
mutate the shared process scheduler.

Args:
    name: Name of the saved pipeline to delete.

Returns:
    Confirmation of deletion.

Input parameters:

- `name` (string, required)

### `get_pipeline_history` (~94 tokens)

Get execution history for a saved pipeline.

Shows past execution results with diff analysis: which articles are new
compared to the previous run.

Args:
    name: Name of the saved pipeline.
    limit: Maximum number of history entries to return (default: 5).

Returns:
    Execution history with date, article count, new/removed articles, status.

Input parameters:

- `limit`
- `name` (string, required)

### `schedule_pipeline` (~114 tokens)

Schedule a saved pipeline for periodic execution.

Args:
    name: Saved pipeline name.
    cron: Required 5-field cron expression. Example: "0 9 * * 1" (Mon 9am).
    diff_mode: When True, store diff-mode preference with the schedule.
    notify: When True, store notify preference with the schedule.

Returns:
    Schedule confirmation or removal result.

Input parameters:

- `cron` (string, required)
- `diff_mode`
- `name` (string, required)
- `notify`

### `unschedule_pipeline` (~55 tokens)

Remove the active schedule for a saved pipeline.

Args:
    name: Saved pipeline name whose schedule will be removed.

Returns:
    Removed schedule metadata, or a native MCP error when none exists.

Input parameters:

- `name` (string, required)

### `read_session` (~175 tokens)

Read session data through one schema-exact discriminated request.

Actions:
\- pmids: return PMIDs for one recorded search
\- article: return one cached article payload
\- summary: return current session summary and optional history
\- list_artifacts: list persistent MCP output artifact manifests
\- artifact: read one persistent artifact by artifact_id or artifact_uri
\- search_runs: list durable unified_search run envelopes
\- search_run: read one run by stable run_id
\- replay_search: return credential-free unified_search replay arguments

Each action accepts only its own fields. For remote artifact reads, select
an artifact_id or artifact_uri locator and use artifact_file plus
offset/max_chars to page through large files. Local paths remain redacted
unless both include_local_paths and the server setting allow them.

Input parameters:

- `request` (required)

## Diagnostics

Captured diagnostic sections: Provenance, Install scripts, Dependencies. The full working is on the page: https://verifymcp.io/servers/u9401066-pubmed-search-mcp/pubmed-search-mcp#diagnostics

## Score history

- 2026-10-25: 77
- 2026-10-24: 77
- 2026-10-23: 77
- 2026-10-22: 77
- 2026-10-21: 77
- 2026-10-20: 62

## Common questions

### What is the PubMed Search MCP server?

PubMed Search is an MCP server listed in the public MCP registry as io.github.u9401066/pubmed-search-mcp. Multi-source biomedical literature search: PubMed, Europe PMC, OpenAlex, full text, citations. This page covers its PyPI package (pubmed-search-mcp).

### Is the PubMed Search MCP server safe to use?

PubMed Search scores 77 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 25 October 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the PubMed Search MCP server expose?

PubMed Search exposes 41 tools: unified_search, analyze_search_query, validate_pico_plan, generate_search_queries, find_related_articles, and 36 more. Their descriptions and schemas cost roughly 14,842 tokens of context every time the server is loaded.

### Is the PubMed Search MCP server still maintained?

PubMed Search is still listed as active in the MCP registry. We last reached this channel on 25 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the PubMed Search MCP server under?

PubMed Search declares the Apache-2.0 licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- PyPI project: https://pypi.org/project/pubmed-search-mcp/
- Socket report: https://socket.dev/pypi/package/pubmed-search-mcp
- Repository: https://github.com/u9401066/pubmed-search-mcp
- Website: https://u9401066.github.io/pubmed-search-mcp/
- Changelog RSS feed: https://verifymcp.io/servers/u9401066-pubmed-search-mcp/pubmed-search-mcp.xml
- Changelog JSON feed: https://verifymcp.io/servers/u9401066-pubmed-search-mcp/pubmed-search-mcp.json
- HTML version of this page: https://verifymcp.io/servers/u9401066-pubmed-search-mcp/pubmed-search-mcp
