PubMed Search MCP
Professional Literature Research Assistant for AI Agents - More than just an API wrapper
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_KEYto use an authenticated credit allocation; without it, requests use OpenAlex's current anonymous casual-use budget.mailtois 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 settingsto 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_EMAILis required by NCBI API policy. Optionally setNCBI_API_KEYfor 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
- Vocabulary Translation Layer - Agent speaks naturally, we translate to each database's terminology (MeSH, ICD-10, text-mined entities)
- Unified Search Gateway - One
unified_search()call, capability-aware dispatch across PubMed, Europe PMC, CORE, OpenAlex, Semantic Scholar, and enabled preprint/commercial sources - PICO Handoff + Pipeline - the Agent extracts P/I/C/O,
parse_pico()validates that structured handoff, and the backendtemplate: picopipeline executes O-aware precision/recall searches - 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
- Citation Network Analysis - Build multi-level citation trees to map an entire research landscape from a single paper
- Full Research Lifecycle - From search β discovery β full text β analysis β export, all in one server
- 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 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)
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
| 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 linksget_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
| 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
| 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
| 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
| 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 statussession://last-searchβ latest search metadatasession://last-search/pmidsβ latest PMID list + CSV formsession://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_statusdescribes the bounded retrieval outcome:state(completed,empty,partial, orfailed),bounded=true,exhaustive=false, returned count, attempted/successful/failed/retryable sources, and continuation/unknown-completeness source lists.search_runis the recovery handoff: stablerun_id, journal status,recoverable, exactread_sessioninspect/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
No comments yet
Be the first to share your take.