PubMed Search MCP

PyPI version Python 3.10+ License: Apache 2.0 MCP CI

Professional Literature Research Assistant for AI Agents - More than just an API wrapper

PubMed Search MCP research workflow

A Domain-Driven Design (DDD) based MCP server that serves as an intelligent research assistant for AI agents, providing task-oriented literature search and analysis capabilities.

✨ What's Included:

  • πŸ”§ 45 MCP Tools - Streamlined PubMed, Europe PMC, CORE, NCBI database access, and Research Chronicle / Context Graph
  • πŸ›‘οΈ Multi-Agent Service Mode - Deploy once and serve many agents: per-tenant sessions, caches, and artifacts, bearer-token auth, and per-tenant fair-share limits. See DEPLOYMENT.md
  • πŸ–ΌοΈ OA Figure Extraction - Pull figure captions, direct image URLs, and PDF links from PMC Open Access articles
  • πŸ“˜ Docs Site - Browse the complete language-switchable handbook: user workflows, architecture, 45-tool reference, pipeline tutorials, source/broker contracts, integrations and operations, security, and deployment at u9401066.github.io/pubmed-search-mcp
  • πŸ“– GitHub Wiki - GitHub-native mirror of the same canonical documentation at github.com/u9401066/pubmed-search-mcp/wiki
  • πŸ“š 26 Claude Skills - Ready-to-use workflow guides for AI agents (Claude Code-specific)
  • πŸ“– Copilot Instructions - VS Code GitHub Copilot integration guide

🌐 Language: English | 繁體中文

πŸ“˜ Documentation Map: README is the quick project entry point. Use the Docs Site for the best reading experience, the GitHub Wiki for GitHub-native navigation, and source docs for edits: User guide | Advanced workflows | Capability-first guide | Provider data planes | BioMCP architecture analysis | Developer guide | Complete index


πŸš€ Quick Install

Prerequisites

  • Python 3.10+ β€” Download

  • uv (recommended) β€” Install uv

    # macOS / Linux
    curl -LsSf https://astral.sh/uv/install.sh | sh
    # Windows
    powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
    
  • NCBI Email β€” Required by NCBI API policy. Any valid email address.

  • NCBI API Key (optional) β€” Get one here for higher rate limits (10 req/s vs 3 req/s)

  • OpenAlex API Key (optional) β€” set OPENALEX_API_KEY to use an authenticated credit allocation; without it, requests use OpenAlex's current anonymous casual-use budget. mailto is contact metadata, not authentication. Without source-specific emails, the server reuses the configured runtime contact email for OpenAlex, CrossRef, and Unpaywall.

Install & Run

# Option 1: Zero-install with uvx (recommended for trying out)
uvx pubmed-search-mcp

# Option 2: Add as project dependency
uv add pubmed-search-mcp

# Option 3: pip install
pip install pubmed-search-mcp

Python SDK Facade

For in-process Python integrations, use the stable SDK facade instead of importing MCP tool modules:

from pubmed_search.api import PubMedSearchClient, PubMedSearchConfig

client = PubMedSearchClient(PubMedSearchConfig(email="[email protected]"))
result = await client.unified_search("remimazolam ICU sedation", limit=20)

print(result.articles)
print(result.source_counts)
print(result.artifact)  # artifact locator when persistence is enabled

Use uvx pubmed-search-mcp or /mcp for agent tool discovery. Use the SDK for Python package/notebook calls where a typed object is easier than parsing an MCP response string.

Choose a Runtime Contract

Contract Command Network and trust boundary
Local stdio uvx pubmed-search-mcp Recommended for one local AI client; no listening MCP port
Local loopback HTTP pubmed-search-mcp-http --mode local --host 127.0.0.1 Trusted single-user integration; MCP requests share the durable default tenant, and the port must never be published
Multi-user service pubmed-search-mcp-http --mode service Remote/team use behind HTTPS; bearer auth, allowed hosts/origins, and per-principal storage are mandatory

Local and service deployments are intentionally separate contracts. Do not turn the local HTTP command into a public service by changing only its bind address. The explicit local profile retains pmids="last", sessions, cache, and exports across MCP requests and reconnects in its durable default tenant; this is safe only inside the enforced loopback/Host/Origin boundary. Service mode never inherits that trust: it fails closed without a bearer principal. Use DEPLOYMENT.md for the service environment and Compose profile. The current service profile supports many authenticated principals in one server process; keep one replica until sessions, locks, artifacts, and subscriptions have shared backends.

The protocol baseline is MCP SDK v2 (mcp>=2.0,<3). Modern 2026-07-28 clients send tools/list and tools/call directly, without an initialize handshake or Mcp-Session-Id. Local mode retains filesystem features. Authenticated service callers cannot load file: pipelines, select note output_dir/template_file, or inherit a process-wide pipeline workspace; the service Compose scheduler is disabled. See the Integrations & Operations Guide for the capability matrix.


βš™οΈ Configuration

This MCP server works with any MCP-compatible AI tool. Choose your preferred client:

VS Code / Cursor (.vscode/mcp.json)

{
  "servers": {
    "pubmed-search": {
      "type": "stdio",
      "command": "uvx",
      "args": ["pubmed-search-mcp"],
      "env": {
        "NCBI_EMAIL": "[email protected]"
      }
    }
  }
}

Optional: enable browser-session PDF fallback once and let tools auto-use it:

{
  "servers": {
    "pubmed-search": {
      "type": "stdio",
      "command": "uvx",
      "args": ["pubmed-search-mcp"],
      "env": {
        "NCBI_EMAIL": "[email protected]",
        "BROWSER_FETCH_CONFIG": "{\"enabled\":true,\"auto_enabled\":true,\"broker_url\":\"http://127.0.0.1:8766/fetch\",\"token\":\"<random-32-byte-token>\",\"allowed_hosts\":[\"jamanetwork.com\",\"*.jamanetwork.com\",\"nejm.org\",\"*.nejm.org\"]}"
      }
    }
  }
}

With this setting, get_fulltext will automatically try the local broker for institutional or publisher landing pages. Pass allow_browser_session=false only when you want to suppress it for a specific call.

Run the local broker with download interception:

uv sync --extra browser-broker
uv run playwright install chromium
uv run python -c "import secrets; print(secrets.token_urlsafe(32))"
uv run pubmed-browser-fetch-broker --token "<same-random-32-byte-token>"

Copy the generated value into both commands/configurations; never reuse a published example token. If --token is omitted, the broker generates and prints a high-entropy runtime token. The broker launches a persistent browser profile with download interception enabled. Log in once inside that broker-controlled browser window, and subsequent PDF downloads will be captured automatically without a native "Save As" dialog.

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "pubmed-search": {
      "command": "uvx",
      "args": ["pubmed-search-mcp"],
      "env": {
        "NCBI_EMAIL": "[email protected]"
      }
    }
  }
}

Config file location:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • Linux: ~/.config/Claude/claude_desktop_config.json

Claude Code

claude mcp add pubmed-search -- uvx pubmed-search-mcp

Or add to .mcp.json in your project root:

{
  "mcpServers": {
    "pubmed-search": {
      "command": "uvx",
      "args": ["pubmed-search-mcp"],
      "env": {
        "NCBI_EMAIL": "[email protected]"
      }
    }
  }
}

Zed AI (settings.json)

Zed editor (z.ai) supports MCP servers natively. Add to your Zed settings.json:

{
  "context_servers": {
    "pubmed-search": {
      "command": "uvx",
      "args": ["pubmed-search-mcp"],
      "env": {
        "NCBI_EMAIL": "[email protected]"
      }
    }
  }
}

Tip: Open Command Palette β†’ zed: open settings to edit, or go to Agent Panel β†’ Settings β†’ "Add Custom Server".

OpenClaw 🦞 (~/.openclaw/openclaw.json)

OpenClaw uses MCP servers via the mcp-adapter plugin. Install the adapter first:

openclaw plugins install mcp-adapter

Then add to ~/.openclaw/openclaw.json:

{
  "plugins": {
    "entries": {
      "mcp-adapter": {
        "enabled": true,
        "config": {
          "servers": [
            {
              "name": "pubmed-search",
              "transport": "stdio",
              "command": "uvx",
              "args": ["pubmed-search-mcp"],
              "env": {
                "NCBI_EMAIL": "[email protected]"
              }
            }
          ]
        }
      }
    }
  }
}

Restart the gateway after configuration:

openclaw gateway restart
openclaw plugins list  # Should show: mcp-adapter | loaded

Cline (cline_mcp_settings.json)

{
  "mcpServers": {
    "pubmed-search": {
      "command": "uvx",
      "args": ["pubmed-search-mcp"],
      "env": {
        "NCBI_EMAIL": "[email protected]",
        "S2_API_KEY": "your_semantic_scholar_key",
        "PUBMED_SEARCH_DISABLED_SOURCES": ""
      },
      "alwaysAllow": [],
      "disabled": false
    }
  }
}

Other MCP Clients

Any MCP-compatible client can use this server via stdio transport:

# Command
uvx pubmed-search-mcp

# With environment variable
[email protected] uvx pubmed-search-mcp

Note: NCBI_EMAIL is required by NCBI API policy. Optionally set NCBI_API_KEY for higher rate limits (10 req/s vs 3 req/s). πŸ“– Detailed Integration Guides: See docs/INTEGRATIONS.md for all environment variables, Copilot Studio setup, Docker deployment, proxy configuration, and troubleshooting.


🎯 Design Philosophy

Core Positioning: The intelligent middleware between AI Agents and academic search engines.

Why This Server?

Other tools give you raw API access. We give you vocabulary translation + intelligent routing + research analysis:

Challenge Our Solution
Agent uses ICD codes, PubMed needs MeSH βœ… Auto ICDβ†’MeSH conversion
Multiple databases, different APIs βœ… Unified Search single entry point
Clinical questions need structured search βœ… PICO handoff + pipeline (parse_pico validates agent-provided P/I/C/O and returns a runnable template: pico pipeline)
Typos in medical terms βœ… ESpell auto-correction
Too many results from one source βœ… Parallel multi-source with dedup
Need to trace research evolution βœ… Research Chronicle & Tree with landmark detection, diagnostics, sub-topic branching, and versioned revisions
Citation context is unclear βœ… Citation Tree forward/backward/network
Can't access full text βœ… Multi-source fulltext (Europe PMC XML, Unpaywall OA locations, institutional direct/EZproxy, CORE, and downloader fallbacks)
Gene/drug info scattered across DBs βœ… NCBI Extended (Gene, PubChem, ClinVar)
Need cutting-edge preprints βœ… Preprint search (arXiv, medRxiv, bioRxiv) with peer-review filtering
Export to reference managers βœ… One-click export (official RIS/MEDLINE/CSL JSON; local RIS/BibTeX/CSV/MEDLINE/JSON)

Key Differentiators

  1. Vocabulary Translation Layer - Agent speaks naturally, we translate to each database's terminology (MeSH, ICD-10, text-mined entities)
  2. Unified Search Gateway - One unified_search() call, capability-aware dispatch across PubMed, Europe PMC, CORE, OpenAlex, Semantic Scholar, and enabled preprint/commercial sources
  3. PICO Handoff + Pipeline - the Agent extracts P/I/C/O, parse_pico() validates that structured handoff, and the backend template: pico pipeline executes O-aware precision/recall searches
  4. Research Chronicle & Lineage Tree - Detect milestones with policy-driven heuristics, identify landmark papers via multi-signal scoring, surface diagnostics, persist versioned revisions you can diff, and visualize research evolution as branching trees by sub-topic
  5. Citation Network Analysis - Build multi-level citation trees to map an entire research landscape from a single paper
  6. Full Research Lifecycle - From search β†’ discovery β†’ full text β†’ analysis β†’ export, all in one server
  7. Agent-First Design - Output optimized for machine decision-making, not human reading

πŸ“‘ External APIs & Data Sources

This MCP server integrates with multiple academic databases and APIs:

Core Data Sources

Source Coverage Vocabulary Auto-Convert Description
NCBI PubMed 36M+ articles MeSH βœ… Native Primary biomedical literature
NCBI Entrez Multi-DB MeSH βœ… Native Gene, PubChem, ClinVar
Europe PMC 33M+ Text-mined βœ… Extraction Full text XML access
CORE 200M+ None ➑️ Free-text Open access aggregator
Semantic Scholar Evolving graph + operator datasets S2 fields / bulk syntax βœ… Broker-compiled modes Relevance, bounded bulk, batch, citation graph, and metadata-only release/diff plane; no partition download
OpenAlex Evolving open research graph Topics / keywords βœ… Keyword + bounded native semantic Cursor, cost provenance, entity graph, and declared operator snapshot path; no local index yet
NIH iCite PubMed N/A N/A Citation metrics (RCR)

πŸ”‘ Key: βœ… = Full vocabulary support | ➑️ = Query pass-through (no controlled vocabulary)

ICD Codes: Auto-detected and converted to MeSH before PubMed search

Environment Variables

# Required
[email protected]          # Required by NCBI policy

# Optional - For higher rate limits
NCBI_API_KEY=your_ncbi_api_key     # Get from: https://www.ncbi.nlm.nih.gov/account/settings/
CORE_API_KEY=your_core_api_key     # Get from: https://core.ac.uk/services/api
[email protected]      # Optional override; defaults to server/NCBI email
[email protected]     # Optional override; defaults to server/NCBI email
S2_API_KEY=your_s2_api_key         # Alias: SEMANTIC_SCHOLAR_API_KEY
OPENALEX_API_KEY=your_openalex_key # Raises the OpenAlex credit budget; actual grant is response-driven
PUBMED_SEARCH_DISABLED_SOURCES=    # Example: semantic_scholar

# Optional - Network settings
HTTP_PROXY=http://proxy:8080       # HTTP proxy for API requests
HTTPS_PROXY=https://proxy:8080     # HTTPS proxy for API requests

# Optional - Institutional fulltext access
INSTITUTIONAL_DIRECT_FETCH=true    # Try DOI publisher pages before CORE fallback
EZPROXY_ENABLED=false              # Enable only after configuring EZPROXY_HOST + cookie
EZPROXY_HOST=ezproxy.example.edu
EZPROXY_COOKIE_FILE=/path/to/cookies.json

# Optional - Local note export
PUBMED_NOTES_DIR=/path/to/wiki/references  # save_literature_notes target folder
PUBMED_WORKSPACE_DIR=/path/to/project       # fallback: references/ under this workspace
PUBMED_DATA_DIR=~/.pubmed-search-mcp        # fallback: references/ under this data dir

CrossRef and Unpaywall reuse the runtime server contact email (NCBI_EMAIL, CLI --email, or detected git email) unless a source-specific email is configured. OpenAlex accepts casual anonymous use and an optional API key; the broker reads its response credit/rate metadata instead of assuming a permanent "polite pool" quota.

Local note export resolves directories in this order: output_dir argument, PUBMED_NOTES_DIR, PUBMED_WORKSPACE_DIR/references, PUBMED_DATA_DIR/references, then ~/.pubmed-search-mcp/references. This path/template selection applies only to trusted local mode. Authenticated service notes always use a built-in format below the current tenant's isolated references/ directory. For LLM wiki compatibility, wiki and foam exports use stable link targets based on PMID, DOI, PMCID, or fallback identifiers; titles remain aliases/display labels, and the response includes wiki_validation for unresolved wikilink checks.

πŸ”„ How It Works: The Middleware Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              AI AGENT                                        β”‚
β”‚                                                                              β”‚
β”‚   "Find papers about I10 hypertension treatment in diabetic patients"       β”‚
β”‚                                                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                  β”‚
                                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     πŸ”„ PUBMED SEARCH MCP (MIDDLEWARE)                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚  β”‚  1️⃣ VOCABULARY TRANSLATION                                              β”‚β”‚
β”‚  β”‚     β€’ ICD-10 "I10" β†’ MeSH "Hypertension"                                β”‚β”‚
β”‚  β”‚     β€’ "diabetic" β†’ MeSH "Diabetes Mellitus"                             β”‚β”‚
β”‚  β”‚     β€’ ESpell: "hypertention" β†’ "hypertension"                           β”‚β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚  β”‚  2️⃣ INTELLIGENT ROUTING                                                 β”‚β”‚
β”‚  β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚β”‚
β”‚  β”‚     β”‚ PubMed   β”‚  β”‚Europe PMCβ”‚  β”‚   CORE   β”‚  β”‚ OpenAlex β”‚             β”‚β”‚
β”‚  β”‚     β”‚  36M+    β”‚  β”‚   33M+   β”‚  β”‚  200M+   β”‚  β”‚  250M+   β”‚             β”‚β”‚
β”‚  β”‚     β”‚  (MeSH)  β”‚  β”‚(fulltext)β”‚  β”‚  (OA)    β”‚  β”‚(metadata)β”‚             β”‚β”‚
β”‚  β”‚     β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜             β”‚β”‚
β”‚  β”‚          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β”‚β”‚
β”‚  β”‚                              β–Ό                                          β”‚β”‚
β”‚  β”‚  3️⃣ RESULT AGGREGATION: Dedupe + Rank + Enrich                         β”‚β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                  β”‚
                                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         UNIFIED RESULTS                                      β”‚
β”‚   β€’ 150 unique papers (deduplicated from 4 sources)                          β”‚
β”‚   β€’ Ranked by relevance + citation impact (RCR)                              β”‚
β”‚   β€’ Full text links enriched from Europe PMC                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ› οΈ MCP Tools Overview

If you want to understand the tool surface as a usable system, do not start by memorizing 45 tool names.

Start with the Tools Usage Guide: it compresses the current 45 tools into 8 capability families, explains the theoretical lower bound, and gives intent-based routing for both humans and agents.

πŸ” Search & Query Intelligence

Search and query intelligence workflow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      SEARCH ENTRY POINT                          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚   unified_search()          ← 🌟 Single entry for all sources    β”‚
β”‚        β”‚                                                         β”‚
β”‚        β”œβ”€β”€ Quick search     β†’ Direct multi-source query          β”‚
β”‚        β”œβ”€β”€ Native semantic β†’ Bounded OpenAlex semantic mode    β”‚
β”‚        β”œβ”€β”€ Systematic       β†’ Bounded provider bulk/cursor mode  β”‚
β”‚        β”œβ”€β”€ PICO hints       β†’ Detects comparison, shows P/I/C/O  β”‚
β”‚        └── ICD expansion    β†’ Auto ICDβ†’MeSH conversion           β”‚
β”‚                                                                  β”‚
β”‚   Sources: PubMed Β· Europe PMC Β· CORE Β· OpenAlex Β· S2            β”‚
β”‚   Auto: Deduplicate β†’ Rank β†’ Enrich full-text links              β”‚
β”‚                                                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   QUERY INTELLIGENCE                                             β”‚
β”‚                                                                  β”‚
β”‚   generate_search_queries() β†’ MeSH expansion + synonym discovery β”‚
β”‚   parse_pico()              β†’ Agent-provided PICO handoff        β”‚
β”‚   analyze_search_query()    β†’ Query analysis without execution   β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

One search entry, three retrieval policies

Generic literature discovery is intentionally exposed through exactly one MCP tool: unified_search. Provider-specific APIs remain internal broker capabilities:

# Default relevance/keyword routing across enabled sources
unified_search(query="treatment resistance")

# OpenAlex native semantic search (provider maximum 50 results)
unified_search(
    query="mechanisms of treatment resistance",
    sources="openalex",
    options="native_semantic",
)

# Deterministic/bounded retrieval: OpenAlex cursor and S2 bulk where selected
unified_search(
    query="melanoma AND immunotherapy",
    sources="pubmed,openalex,semantic_scholar",
    options="systematic",
)

native_semantic and systematic are mutually exclusive and disable the multi-strategy deep-search expansion. Explicit source selections fail before a network call when a requested retrieval mode is unsupported; automatic source selection retains only capable providers. limit remains at most 100 per source, so systematic means deterministic, bounded provider executionβ€”not an exhaustive systematic-review guarantee. Structured output and artifacts record retrieval_mode plus per-source source_metadata (requested/provider mode, canonical or compiled query, continuation availability, cost/rate metadata, and warnings when available).

The public request boundary is fail-closed. limit must be an integer from 1 through 100; unknown or malformed filters / options, reversed or out-of-range years, and unsupported ranking or output modes return a validation error before provider I/O. In the default deep-search policy, limit is one total budget per source divided across that source's query strategiesβ€”not limit results for every strategy. Strategy calls use bounded global/per-source concurrency and timeouts, and successful sources remain usable when another source times out, is rate-limited, or fails.

Europe PMC, Scopus, and Web of Science remain keyword-only in this release; explicit systematic requests for those sources fail before I/O instead of mislabeling a single page as systematic coverage.

See Source Contracts, Semantic Scholar, and OpenAlex for provider limits and operator data-plane boundaries.

πŸ”¬ Discovery Tools (After Finding Key Papers)

Article discovery and citation workflow

                        Found important paper (PMID)
                                   β”‚
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚                       β”‚                       β”‚
           β–Ό                       β–Ό                       β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  BACKWARD   β”‚        β”‚  SIMILAR    β”‚        β”‚  FORWARD    β”‚
    β”‚  ◀──────    β”‚        β”‚  β‰ˆβ‰ˆβ‰ˆβ‰ˆβ‰ˆβ‰ˆ     β”‚        β”‚  ──────▢    β”‚
    β”‚             β”‚        β”‚             β”‚        β”‚             β”‚
    β”‚ get_article β”‚        β”‚find_related β”‚        β”‚find_citing  β”‚
    β”‚ _references β”‚        β”‚ _articles   β”‚        β”‚ _articles   β”‚
    β”‚             β”‚        β”‚             β”‚        β”‚             β”‚
    β”‚ Foundation  β”‚        β”‚  Similar    β”‚        β”‚ Follow-up   β”‚
    β”‚  papers     β”‚        β”‚   topic     β”‚        β”‚  research   β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

    fetch_article_details()   β†’ Detailed article metadata
    get_citation_metrics()    β†’ iCite RCR, citation percentile
    build_citation_tree()     β†’ Full network visualization (6 formats)

πŸ“š Full Text, Figure Extraction & Export

Full text, figures, and biomedical image workflow

Category Tools
Full Text get_fulltext β†’ Europe PMC XML when a PMCID is available; DOI-backed Unpaywall, institutional direct/EZproxy, CORE, and downloader fallbacks when needed
Figures get_article_figures β†’ Extract figure labels, captions, image URLs, and PDF links from PMC Open Access articles
Figure-aware Full Text get_fulltext(include_figures=True) β†’ Embed figure metadata alongside structured fulltext
Text Mining get_text_mined_terms β†’ Extract genes, diseases, chemicals
Export prepare_export β†’ official RIS/MEDLINE/CSL JSON or local RIS/BibTeX/CSV/MEDLINE/JSON; save_literature_notes β†’ local wiki/Foam-compatible/Markdown/MedPaper-style notes plus collection-level CSL JSON

πŸ–ΌοΈ OA Figure-First Exploration

Use the PMC Open Access path when an agent needs evidence figures, not just article text:

  • get_article_figures(identifier="PMC12086443") β†’ Figure labels, captions, image URLs, and PDF/article links
  • get_fulltext(pmcid="PMC7096777", include_figures=True) β†’ Structured fulltext with figures inline
  • Figure output preserves article context, so agents can connect each figure back to the sections where it is mentioned

🧬 NCBI Extended Databases

NCBI extended biomedical data workflow

Tool Description
search_gene Search NCBI Gene database
get_gene_details Gene details by NCBI Gene ID
get_gene_literature PubMed articles linked to a gene
search_compound Search PubChem compounds
get_compound_details Compound details by PubChem CID
get_compound_literature PubMed articles linked to a compound
search_clinvar Search ClinVar clinical variants

πŸ•°οΈ Research Chronicle & Lineage Tree

Evaluation and timeline workflow

Tool Description
build_research_chronicle Build a persisted, versioned chronicle with landmark detection. Output: summary, chronicle_map, timeline, tree, graph, evidence, milestones, mermaid, timeline_mermaid, mindmap, narrative, json
read_research_chronicle Load, list, diff revisions, narrate with citations, analyze milestone distribution, or compare up to five topics

mermaid is the canonical combined view: a horizontal year spine with each observed research line branching at its earliest dated paper within the retrieved scope. This is an explainable grouping, not a causal genealogy or a claim about the field's true first paper. Lineages prefer MeSH descriptors and author keywords shared by multiple papers; singleton-only or insufficient signals trigger a warned research-stage fallback. Same-year display order is stable, but does not assert precedence when publication precision cannot prove it. timeline_mermaid preserves the older flat timeline view. See the implemented contract in docs/RESEARCH_CHRONICLE_REFACTOR_SPEC.md.

Chronicle Mermaid output is built from structured nodes and edges, with safe label escaping, cycle/orphan repair, collision-resistant IDs, and bounded graph size. It falls back from rich to safe to minimal syntax instead of failing the whole chronicle. mermaid_validation.json records every correction, fallback, and omitted visual item; chronicle.mmd remains pure Mermaid source.

Chronicle revisions are immutable and appended atomically. When session artifact persistence is enabled, artifact failure is surfaced explicitly while the saved Chronicle revision remains available.

Topic builds send year limits to PubMed before bounded retrieval, then preserve the first and last observed papers while filling the cap with landmarks and temporal spread. The audit records PubMed returned / available counts and warns when availability is unknown or any retrieval/selection cap makes the view non-exhaustive. PubMed errors or a scope with no article evidence do not publish an empty revision.

Explicit PMID input is strict (12345678 or PMID:12345678, positive ASCII digits, at most 20 digits); DOI or mixed text is rejected instead of being coerced. Records without a reliable publication date appear as Undated after dated entries and are excluded from the displayed year span. Entry IDs follow PMID/DOI evidence identity across date or classifier corrections, and topic continuity uses one Unicode/case/whitespace canonical key. Multi-signal papers keep one primary branch plus explicit cross-links; overlap of 20% or more is audited as a warning. In revision diffs, absence means not_observed_in_revision / removed_from_view, never conclusive retirement.

πŸ₯ Institutional Access & ICD Conversion

Institutional access workflow

Tool Description
configure_institutional_access Configure institution's link resolver
get_institutional_link Generate OpenURL access link
list_resolver_presets List resolver presets
test_institutional_access Test resolver configuration
diagnose_institutional_access Diagnose direct DOI, EZproxy, and OpenURL handoff paths
convert_icd_mesh Convert between ICD codes and MeSH terms (bidirectional)
unified_search Auto-detect ICD codes in queries and expand them to MeSH

πŸ’Ύ Session Management

Session and pipeline workflow

Tool Description
get_session_pmids Retrieve cached PMID lists
get_cached_article Get article from session cache (no API cost)
get_session_summary Session status overview
read_session Facade for PMIDs, cached articles, durable search runs, replay arguments, history, and persistent artifacts

Dynamic MCP resources are also available for agents that can read resources directly:

  • session://context β€” active session status
  • session://last-search β€” latest search metadata
  • session://last-search/pmids β€” latest PMID list + CSV form
  • session://last-search/results β€” cached article payloads for the latest search

Persistent Artifacts

Persistent MCP output artifacts are saved for reusable unified_search and get_fulltext responses when session persistence is configured. Tool responses act like index cards: they include enough counts, source warnings, and artifact hints for an agent to answer immediately, while the full evidence payload stays in files that can be read repeatedly. The compact artifact locator includes artifact_id, artifact_uri, primary_file, summary, file inventory, read_order, audit status, and exact read_session(...) retrieval hints. Set PUBMED_ARTIFACT_INCLUDE_LOCAL_PATHS=true only when a local MCP client should also receive local_path and manifest_path directly.

Remote clients that cannot read the server filesystem can retrieve the same content through the session facade:

read_session(action="list_artifacts")
read_session(action="artifact", artifact_id="...")
read_session(action="artifact", artifact_uri="artifact://...")
read_session(action="artifact", artifact_uri="artifact://...", artifact_file="audit.json")
read_session(action="artifact", artifact_uri="artifact://...", artifact_file="query_strategy.json")
read_session(action="artifact", artifact_uri="artifact://...", artifact_file="results.json", offset=0, max_chars=200000)
read_session(action="list_artifacts", include_local_paths=true)

Recoverable search runs

When session management is active, every unified_search invocation receives a stable run ID. This includes normal searches, validation/planning failures, and inline, saved:<name>, or dry_run=true pipeline execution. Structured results and errors attach the search_run handoff; Markdown returns the same run ID as a compact recovery note. Normal literature-result envelopes expose two separate machine contracts:

  • search_status describes the bounded retrieval outcome: state (completed, empty, partial, or failed), bounded=true, exhaustive=false, returned count, attempted/successful/failed/retryable sources, and continuation/unknown-completeness source lists.
  • search_run is the recovery handoff: stable run_id, journal status, recoverable, exact read_session inspect/replay arguments, and the artifact URI when one was committed.

The tenant-scoped search-run/v1 journal is published before provider I/O or a terminal validation response and records the sanitized request, plan, physical per-source or per-pipeline-step attempts, counts, safe failures, result references, and artifact locator when applicable. It reaches a terminal completed, partial, failed, or cancelled state; a valid zero-result search is a completed run whose search_status.state is empty. On restart, an unfinished started / planned / running entry is recovered once as interrupted instead of disappearing. A non-dry-run saved pipeline additionally keeps its PipelineStore report/run history; that is complementary to the invocation-level search journal, not a replacement for it.

Pipeline replay preserves the original inline or saved:<name> argument plus dry_run / stop_at. Pipeline text containing keys, tokens, cookies, passwords, or other credential material is rejected and recorded as a failed run; provider credentials belong in server environment/configuration, never pipeline YAML or JSON.

read_session(action="search_runs")
read_session(action="search_runs", run_status="partial")
read_session(action="search_run", run_id="...")
read_session(action="replay_search", run_id="...")

replay_search only returns the original credential-free unified_search kwargs. It never executes a network call automatically; the agent or user must review and explicitly submit them. Provider cursor/token values are retained as opaque provenance in source_metadata and query_strategy.json, but there is no public cursor-resume parameter yet, so replay starts a new bounded search.

If the terminal journal write cannot be recovered, the response reports search_run.status="history_unavailable", history_available=false, the intended terminal status, and a warning. It deliberately omits inspect/replay actions because durable recovery is not guaranteed; the search result itself may still be usable.

unified_search artifacts use a research envelope. Start with audit.json for source-count and completeness warnings, then query_strategy.json for the exact executed plan, and finally results.json / results.toon for the complete article list. This keeps MCP response tokens small without losing academic traceability.

Artifacts are generated from the already-computed result object, so reading an artifact does not rerun searches or fulltext retrieval. If a crash occurs after an artifact directory is atomically published but before the session index is updated, session reload discovers only complete, checksum-indexed manifests and relinks the orphaned artifact to its search run by search_run_id (with a conservative query match for older artifacts). read_session redacts local filesystem paths by default; local_path and manifest_path are server-local paths, not portable client paths. Artifacts from get_fulltext may contain article body text, including subscription or institutionally accessed content. Store and share them according to publisher, license, and institutional access terms. Large get_fulltext responses are returned inline as a preview when an artifact is available; use the artifact locator to retrieve the saved full content.

When one source fails but the overall search can continue, JSON responses may include source_errors; markdown responses show a Source warnings line. For Semantic Scholar HTTP 429s, set S2_API_KEY / SEMANTIC_SCHOLAR_API_KEY, retry later, or temporarily exclude it with