pubmed-search-mcp
This server is an MCP-based academic literature research assistant that gives AI agents a unified, task-oriented search, retrieval, analysis, and export workflow across multiple scholarly databases.
🔍 Unified search across PubMed, Europe PMC, CORE, OpenAlex, Semantic Scholar, preprints, and ClinicalTrials.gov with deduplication, ranking, and OA-link enrichment
🧠 Query intelligence: analyze queries, generate MeSH-expanded search queries, auto-correct spelling, and convert ICD codes to MeSH
🩺 PICO clinical workflow: validate agent-provided P/I/C/O and execute structured pipeline searches
🔗 Discovery & citation analysis: find related/citing/reference articles, fetch details, get iCite metrics, and build citation trees
📄 Full text & figures: retrieve fulltext from multiple sources, extract figure captions/image URLs, and mine text-mined entities
🧬 NCBI extended databases: search Gene, PubChem, and ClinVar and link them to literature
🕰️ Research Chronicle: build versioned topic timelines with landmark detection, lineage trees, narratives, revision diffs, and cross-topic comparison
📤 Export & notes: export RIS/BibTeX/CSV/MEDLINE/CSL JSON and save wiki/Foam/Markdown literature notes
🔁 Pipeline management: save, load, schedule, and review reusable search pipelines
💾 Session & artifacts: read session state, durable search-run journals, replay arguments, and persistent artifacts
🏛️ Institutional access: configure OpenURL resolvers, generate access links, and diagnose direct/EZproxy access paths
🖼️ Vision & image search: prepare figures for agent vision analysis and search biomedical images via Open-i
📋 Reference verification: verify plain-text reference lists against PubMed evidence
🛡️ Flexible deployment: local stdio, loopback HTTP, or authenticated multi-tenant service mode
Supports preprint search across arXiv, medRxiv, and bioRxiv with peer-review filtering capabilities.
Provides tools for searching PubMed, retrieving citations, full text, and related metadata, with features like auto-correction (ESpell) and vocabulary translation (ICD to MeSH).
Integrates Semantic Scholar API for enhanced citation and full-text access, configurable via API key.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@pubmed-search-mcpsearch for recent papers on CRISPR gene therapy"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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:
🔧 41 MCP Tools - Streamlined PubMed, Europe PMC, CORE, NCBI database access, and the versioned Research Chronicle
🛡️ 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, 41-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 | Unified Search architecture | 41-tool quality audit | 60-repository academic retrieval landscape | Provider data planes | BioMCP architecture analysis | Developer guide | Complete index
Documentation map · Maintenance scripts
Provider-safe scheduling — v0.7.4
Pipeline branches now proceed as their dependencies finish while API request-rate limits remain unchanged. Shared concurrency uses the most conservative caller limit; 429 cooldowns survive timeouts and cancelled PubMed workers. Historical plans are archived behind a documentation map. See the release review and offline latency experiment; fixed-delay timing is not a live-provider throughput or retrieval-quality claim.
Related MCP server: ScholarMCP
Core review and reliability — v0.7.3
Completed the ten-phase core review: 223 source files and 2,901 definitions with authored decisions and current file hashes. This release repairs source-failure handling, article identity, persistence, cancellation, exports, and evaluation checkpoints while keeping all 41 tools. Harness installation preserves user customizations; contributors run the full local gate before push, with an independent smoke gate in ordinary CI. See the changelog for behavior changes. Local regression results do not establish a new public benchmark gain.
Research quality and evaluation — v0.7.2
This release improves query-aware ranking and fusion, cross-source article deduplication, bibliographic verification, section filtering, and concurrent cache fetches. The canonical 41-tool interface remains unchanged.
The benchmark report separates component quality from the value of the complete agent package. On public BEIR NFCorpus, an earlier BM25 component comparison improved test nDCG@10 from 0.293357 to 0.297831. That result does not measure this release's full agent performance. The three-question native Codex/package pilot is too small to establish a product-level gain; the complete 5,000-question evaluation is prepared but has not been started.
Read the reliability audit for reproduced defects, validation boundaries, and revision fingerprints. Reference verification checks bibliographic consistency; confirming that a paper supports a claim still requires inspecting the relevant passage.
🚀 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-mcpPython 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
async with PubMedSearchClient(PubMedSearchConfig(email="your@email.com")) as client:
result = await client.unified_search("remimazolam ICU sedation", limit=20)
print(result.articles)
print(result.source_counts)
print(result.source_errors)
print(result.result_filter_counts)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.
The SDK executes the application use case directly and intentionally has no MCP
session journal or artifact side effects; use the MCP tool when durable replay
and artifact locators are required.
The async context owns and closes every provider client and HTTP pool. If a
long-lived application does not use async with, call await client.aclose()
during shutdown.
Choose a Runtime Contract
Contract | Command | Network and trust boundary |
Local stdio |
| Recommended for one local AI client; no listening MCP port |
Local loopback HTTP |
| Trusted single-user integration; MCP requests share the durable |
Multi-user 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. Note responses use tenant-relative
logical locators and never reveal server filesystem paths. 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": "your@email.com"
}
}
}
}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": "your@email.com",
"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. --token, BROWSER_FETCH_BROKER_TOKEN, or the
shared BROWSER_FETCH_TOKEN is required; the broker fails closed instead of
generating or logging a secret. 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": "your@email.com"
}
}
}
}Config file location:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
Claude Code
claude mcp add pubmed-search -- uvx pubmed-search-mcpOr add to .mcp.json in your project root:
{
"mcpServers": {
"pubmed-search": {
"command": "uvx",
"args": ["pubmed-search-mcp"],
"env": {
"NCBI_EMAIL": "your@email.com"
}
}
}
}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": "your@email.com"
}
}
}
}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-adapterThen 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": "your@email.com"
}
}
]
}
}
}
}
}Restart the gateway after configuration:
openclaw gateway restart
openclaw plugins list # Should show: mcp-adapter | loadedCline (cline_mcp_settings.json)
{
"mcpServers": {
"pubmed-search": {
"command": "uvx",
"args": ["pubmed-search-mcp"],
"env": {
"NCBI_EMAIL": "your@email.com",
"SEMANTIC_SCHOLAR_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
NCBI_EMAIL=your@email.com uvx pubmed-search-mcpNote:
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 ( |
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 detected-preprint filtering; this does not verify peer-review status |
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 sourcesPICO Handoff + Pipeline - the Agent extracts P/I/C/O,
validate_pico_plan()validates that structured handoff, and the backendtemplate: picopipeline executes O-aware precision/recall searchesResearch 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
NCBI_EMAIL=your@email.com # 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
CROSSREF_EMAIL=your@email.com # Optional override; defaults to server/NCBI email
UNPAYWALL_EMAIL=your@email.com # Optional override; defaults to server/NCBI email
SEMANTIC_SCHOLAR_API_KEY=your_semantic_scholar_key # https://www.semanticscholar.org/product/api
OPENALEX_API_KEY=your_openalex_key # Raises the OpenAlex credit budget; actual grant is response-driven
PUBMED_SEARCH_DISABLED_SOURCES= # Example: semantic_scholar
# Optional - Pipeline run-wide safety budgets
PUBMED_PIPELINE_RUN_TIMEOUT_SECONDS=120 # Shared end-to-end deadline (max 3600)
PUBMED_PIPELINE_MAX_EXTERNAL_CALLS=40 # Shared across sequential/parallel steps (max 1000)
# 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 dirCrossRef 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 41 tool names.
Start with the Tools Usage Guide: it compresses the current 41 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 │
│ validate_pico_plan() → 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="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.
PubMed, 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 |
|
Figures |
|
Figure-aware Full Text |
|
Text Mining |
|
Export |
|
get_fulltext reports coverage_status, exact sources_tried /
sources_completed, and sanitized source_errors. A usable article or link
from one source plus a failure from another is therefore partial, not a
misleading complete success or empty result. Extended PDF discovery carries the
same immutable typed coverage envelope through discovery, download, extraction,
tool output, and artifacts.
🖼️ OA Figure-First Exploration
Use the PMC Open Access path when an agent needs evidence figures, not just article text:
get_article_figures(source={"kind":"pmcid","value":"PMC12086443"})→ Figure labels, captions, image URLs, and PDF/article linksget_fulltext(source={"kind":"pmcid","value":"PMC7096777"}, include_figures=True)→ Structured fulltext with figures inlineFigure output preserves article context, so agents can connect each figure back to the sections where it is mentioned
🧬 NCBI Extended Databases
Tool | Description |
| Search NCBI Gene database |
| Gene details by NCBI Gene ID |
| PubMed articles linked to a gene |
| Search PubChem compounds |
| Compound details by PubChem CID |
| PubMed articles linked to a compound |
| Search ClinVar clinical variants |
🕰️ Research Chronicle & Lineage Tree
Tool | Description |
| Build a persisted, versioned chronicle with landmark detection. Output: summary, chronicle_map, timeline, tree, graph, evidence, milestones, mermaid, narrative, json |
| Load, list, diff revisions, narrate with citations, analyze milestone distribution, or compare up to five topics |
# 1. Build from topic (retrieves PubMed, scores landmarks, clusters lineages)
build_research_chronicle(topic="remimazolam intraoperative", output="mermaid", max_events=30)
# 2. Continue an existing chronicle (inherits stored topic and filters to produce Revision N+1)
build_research_chronicle(chronicle_id="remimazolam-intraoperative-08c229f3")
# 3. Read revision diff, milestone analytics, or cross-topic comparison
read_research_chronicle(request={"action":"diff","chronicle_id":"remimazolam-intraoperative-08c229f3","from_revision":1})
read_research_chronicle(request={"action":"milestones","chronicle_id":"remimazolam-intraoperative-08c229f3"})
read_research_chronicle(request={"action":"compare","selection":{"kind":"topics","values":["remimazolam intraoperative","propofol intraoperative"]}})mermaid is the canonical combined view: a horizontal year spine (X-axis) with each
observed research line (Y-axis) 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. See
Advanced Research Workflows (docs/ADVANCED_RESEARCH_WORKFLOWS.md) and
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.
Retrieval provenance separates ranking_requested from the effective
ranking. iCite ordering is claimed only when a validated citation count was
actually applied. The versioned citation-metrics coverage records complete,
partial, empty, error, and not-requested outcomes with safe counts and errors;
the audit warns or fails rather than treating an outage as zero citations.
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, never
conclusive retirement.
🏥 Institutional Access & ICD Conversion
Tool | Description |
| Configure institution's link resolver |
| Generate OpenURL access link |
| List resolver presets |
| Test resolver configuration |
| Diagnose direct DOI, EZproxy, and OpenURL handoff paths |
| Convert between ICD codes and MeSH terms (bidirectional) |
| Auto-detect ICD codes in queries and expand them to MeSH |
Resolver bases must be credential-free HTTP(S) URLs without a query or
fragment. PMID diagnosis reports resolved, not_found, or error for the
PubMed-to-DOI step, so an upstream outage is never described as a missing DOI.
💾 Session Management
Tool | Description |
| Strict action-discriminated reader for PMIDs, cached articles, summaries, logs, durable search runs, replay arguments, 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(request={"action":"list_artifacts"})
read_session(request={"action":"artifact","locator":{"kind":"artifact_id","value":"..."}})
read_session(request={"action":"artifact","locator":{"kind":"artifact_uri","value":"artifact://..."}})
read_session(request={"action":"artifact","locator":{"kind":"artifact_uri","value":"artifact://..."},"artifact_file":"audit.json"})
read_session(request={"action":"artifact","locator":{"kind":"artifact_uri","value":"artifact://..."},"artifact_file":"query_strategy.json"})
read_session(request={"action":"artifact","locator":{"kind":"artifact_uri","value":"artifact://..."},"artifact_file":"results.json","offset":0,"max_chars":200000})
read_session(request={"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(request={"action":"search_runs"})
read_session(request={"action":"search_runs","status":"partial"})
read_session(request={"action":"search_run","run_id":"..."})
read_session(request={"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 SEMANTIC_SCHOLAR_API_KEY, retry
later, or temporarily exclude it with sources="auto,-semantic_scholar" or
PUBMED_SEARCH_DISABLED_SOURCES=semantic_scholar.
Pipeline Management
Pipeline management uses seven single-purpose, schema-exact tools. Each tool accepts only the fields relevant to that operation, so misspelled or unrelated arguments fail closed instead of being silently ignored.
Tool | Description |
| Save a pipeline config for later reuse (YAML/JSON, auto-validated) |
| List saved pipelines (filter by tag/scope) |
| Load by saved name; trusted local callers may also load a file |
| Delete pipeline and its execution history |
| View execution history with article diff analysis |
| Create or update a recurring pipeline schedule |
| Remove a recurring pipeline schedule |
Authenticated service callers use named pipelines in their tenant-derived
store; workspace and file: access are local-only. The service Compose
profile does not execute schedules without a separately designed single leader.
Pipeline history is fail-closed: one malformed persisted run produces a safe
explicit error instead of a partial list or a false “no history” result.
Step-by-step tutorials:
👁️ Vision & Image Search
Tool | Description |
| Handoff an uploaded image, image URL, or data URI to agent vision for search-term extraction |
| Search biomedical images across Open-i (X-ray, microscopy, photos, diagrams) |
Use prepare_figure_search when the user supplies an image and the agent
must interpret its meaning first. The tool returns MCP ImageContent plus
instructions for the LLM agent to extract English biomedical terms, then
continue with search_biomedical_images for similar Open-i images or
unified_search for related papers.
Open-i results carry typed per-source coverage. A valid total=0 and empty
list means no matches; a malformed response or source outage is failed, and
mixed valid/invalid rows are partial. Failed sources are excluded from
sources_used, their total stays unknown, and Markdown shows the sanitized
coverage instead of claiming “no images.”
📄 Preprint Search
Search arXiv, medRxiv, and bioRxiv preprint servers via unified_search options flags:
Source, filter, and option tokens use exact canonical spelling. Do not add whitespace around comma-separated tokens or repeat a token; aliases and case variants are rejected.
preprints: Search preprint servers and merge preprints into the main aggregated result set witharticle_type=PREPRINT.include_detected_preprints: Keep records identified by the preprint heuristic in otherwise selected scholarly sources, without adding a preprint-server crawl.
Preprint source metadata reports the provider query/window, result limit, unknown corpus total, and local year-filter counts. Unknown-year records are excluded when a hard year range is requested. medRxiv/bioRxiv use a bounded date feed with literal all-term filtering, so Boolean or grouped query syntax fails before network I/O instead of being silently reinterpreted.
Recommended combinations:
Empty
options: Records detected as preprints are filtered. This heuristic does not prove that every remaining record was peer reviewed.options="preprints": Searches arXiv, medRxiv, and bioRxiv, then ranks/dedupes those preprints with the main results.options="include_detected_preprints": No preprint-server crawl; detected preprints already returned by selected sources are retained.
Preprint detection — articles are identified as preprints by:
Article type from source API (OpenAlex, CrossRef, Semantic Scholar)
arXiv ID present without PubMed ID
Known preprint server source or journal name
DOI prefix matching preprint servers (e.g.,
10.1101/→ bioRxiv/medRxiv,10.48550/→ arXiv)
For chronological research lineage, use build_research_chronicle; it is the
only research-chronology capability and supplies the audited timeline,
branching map, narrative, and revision history.
🧪 Clinical-Trial Registry Adjunct
ClinicalTrials.gov is never queried implicitly. Add options="clinical_trials" to a
search when a bounded registry adjunct is useful. It remains separate from the
literature-source plan, article ranking, and source counts. Markdown renders up
to three records; JSON/TOON returns the same requested adjunct as structured
data. The versioned clinical-trials-adjunct/v1 coverage records retrieval and
format status, returned count, completeness, warnings, and sanitized failures
consistently across the response and durable artifact.
unified_search(query="remimazolam ICU sedation", options="clinical_trials")📊 Count-First Orientation
unified_search can also front-load the existing source coverage and decision hints for agents that want routing help before reading the ranked list:
Option Flag | Description |
| Add a source-count table, coverage summary, and next-tool recommendations to the response |
Example:
unified_search(query="remimazolam ICU sedation", options="counts_first")This mode is useful when the agent should decide whether to expand a source, inspect the lead PMID, fetch fulltext, extract figures, or pivot into timeline exploration.
⏱️ MCP Progress Reporting
When the MCP client provides a progress token, unified_search, build_research_chronicle, get_fulltext, and get_text_mined_terms emit progress updates for their major phases.
This reduces the "black box" wait time for agents during longer searches.
Progress callbacks are best-effort and have a 100 ms hard deadline. A stalled
callback is cancelled; if a broken host suppresses cancellation, its task is
quarantined in a server-owned pool capped at 32 entries so core tools remain
responsive without unbounded background work.
📋 Agent Usage Examples
1️⃣ Quick Search (Simplest)
# Agent just asks naturally - middleware handles everything
unified_search(query="remimazolam ICU sedation", limit=20)
# Or with clinical codes - auto-converted to MeSH
unified_search(query="I10 treatment in E11.9 patients")
# ↑ ICD-10 ↑ ICD-10
# Hypertension Type 2 Diabetes2️⃣ PICO Clinical Question
Simple path — unified_search can search directly (no PICO decomposition):
# unified_search searches as-is; detects "A vs B" pattern and shows PICO hints in metadata
unified_search(query="Is remimazolam better than propofol for ICU sedation?")
# → Multi-source keyword search + PICO hint metadata in output
# ⚠️ This does NOT auto-decompose PICO or expand MeSH!
# For structured PICO search, use the Agent workflow belowAgent workflow — agent-provided PICO + backend pipeline search (recommended for clinical questions):
┌─────────────────────────────────────────────────────────────────────────┐
│ "Is remimazolam better than propofol for ICU sedation?" │
└─────────────────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ validate_pico_plan() │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ P │ │ I │ │ C │ │ O │ │
│ │ ICU │ │remimaz- │ │propofol │ │sedation │ │
│ │patients │ │ olam │ │ │ │outcomes │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
└───────┼────────────┼────────────┼────────────┼──────────────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ generate_search_queries() × 4 (parallel) │
│ │
│ P → "Intensive Care Units"[MeSH] │
│ I → "remimazolam" [Supplementary Concept], "CNS 7056" │
│ C → "Propofol"[MeSH], "Diprivan" │
│ O → "Conscious Sedation"[MeSH], "Deep Sedation"[MeSH] │
└─────────────────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Agent combines with Boolean logic │
│ │
│ (P) AND (I) AND (C) AND (O) ← High precision │
│ (P) AND (I OR C) AND (O) ← High recall │
└─────────────────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ unified_search() (auto multi-source + dedup) │
│ │
│ PubMed + Europe PMC + CORE + OpenAlex → Auto deduplicate & rank │
└─────────────────────────────────────────────────────────────────────────┘# Step 1: Agent extracts P/I/C/O, then validates the structured handoff
pico = validate_pico_plan(
description="Is remimazolam better than propofol for ICU sedation?",
p="ICU patients requiring sedation",
i="remimazolam",
c="propofol",
o="sedation efficacy, delirium, hypotension"
)
# Returns validation plus a ready-to-run `template: pico` pipeline.
# Step 2: Get MeSH for each element (parallel!)
generate_search_queries(topic="ICU patients") # P
generate_search_queries(topic="remimazolam") # I
generate_search_queries(topic="propofol") # C
generate_search_queries(topic="sedation") # O
# Step 3: Either pass expanded fragments back as p_query/i_query/c_query/o_query
# or let the backend pipeline use the structured P/I/C/O labels.
# Step 4: Search (backend runs O-aware precision/recall searches, dedup, rank)
unified_search(
query="Is remimazolam better than propofol for ICU sedation?",
pipeline=pico["pipeline"]
)3️⃣ Explore from Key Paper
# Found landmark paper PMID: 33475315
find_related_articles(pmid="33475315") # Similar methodology
find_citing_articles(pmid="33475315") # Who built on this?
get_article_references(pmid="33475315") # What's the foundation?
# Build complete research map
build_citation_tree(pmid="33475315", depth=2, output_format="mermaid")4️⃣ Gene/Drug Research
# Research a gene
search_gene(query="BRCA1", organism="human")
get_gene_literature(gene_id="672", limit=20)
# Research a drug compound
search_compound(query="propofol")
get_compound_literature(cid="4943", limit=20)5️⃣ Export Results
# Export last search results
prepare_export(pmids="last", format="ris") # → EndNote/Zotero
prepare_export(pmids="last", format="bibtex", source="local") # → LaTeX
prepare_export(pmids="last", format="csl") # → CSL JSON from the official NCBI Citation API
save_literature_notes(pmids="last") # → local wiki note + Foam-compatible wikilinks + CSL JSON
save_literature_notes(pmids="last", note_format="medpaper", output_dir="./references")
save_literature_notes(pmids="last", template_file="./reference-template.md")
# Retrieve full text for a selected paper from the last search
get_fulltext(source={"kind":"pmid","value":"12345678"}, extended_sources=True)6️⃣ Preprint Search
# Search preprint sources alongside the regular scholarly-source set
unified_search(query="COVID-19 vaccine efficacy", options="preprints")
# → Main aggregated results include labelled arXiv, medRxiv, and bioRxiv preprints
# Retain preprints detected in otherwise selected sources without adding a crawl
unified_search(query="CRISPR gene therapy", options="include_detected_preprints")
# Default heuristic policy
unified_search("diabetes treatment")
# → Detected preprints are filtered; remaining peer-review status is not proven7️⃣ Pipeline (Reusable Search Plans)
# Save a template-based pipeline through the primary facade
save_pipeline(
name="icu_sedation_weekly",
config="template: pico\ntemplate_params:\n P: ICU patients\n I: remimazolam\n C: propofol\n O: delirium",
tags=["anesthesia","sedation"],
description="Weekly ICU sedation monitoring"
)
# Save a custom DAG pipeline
save_pipeline(
name="brca1_comprehensive",
config="""
steps:
- id: expand
action: expand
params: { topic: BRCA1 breast cancer }
- id: pubmed
action: search
params: { query: BRCA1, sources: [pubmed], limit: 50 }
- id: expanded
action: search
inputs: [expand]
params: { strategy: mesh, sources: [pubmed, openalex], limit: 50 }
- id: merged
action: merge
inputs: [pubmed, expanded]
params: { method: rrf }
- id: enriched
action: metrics
inputs: [merged]
output:
limit: 30
ranking: quality
"""
)
# Execute a saved pipeline
unified_search(pipeline="saved:icu_sedation_weekly")
# List & manage
list_pipelines(tag="anesthesia")
load_pipeline(source="brca1_comprehensive") # Review YAML
get_pipeline_history(name="icu_sedation_weekly") # View past runs🔍 Search Mode Comparison
┌─────────────────────────────────────────────────────────────────────────┐
│ SEARCH MODE DECISION TREE │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ "What kind of search do I need?" │
│ │ │
│ ├── Know exactly what to search? │
│ │ └── unified_search(query="topic keywords") │
│ │ → Quick, auto-routing to best sources │
│ │ │
│ ├── Have a clinical question (A vs B)? │
│ │ └── Agent P/I/C/O → validate_pico_plan() handoff │
│ │ → unified_search(template:pico) or expanded Boolean │
│ │ │
│ ├── Need comprehensive systematic coverage? │
│ │ └── generate_search_queries() → parallel search │
│ │ → MeSH expansion, multiple strategies, merge │
│ │ │
│ └── Exploring from a key paper? │
│ └── find_related/citing/references → build_citation_tree │
│ → Forward/backward citation network │
│ │
└─────────────────────────────────────────────────────────────────────────┘Mode | Entry Point | Best For | Auto-Features |
Quick |
| Fast topic search | ICD→MeSH, multi-source, dedup |
PICO | Agent P/I/C/O -> | Clinical questions | Validate handoff -> |
Systematic |
| Reproducible review seed | MeSH/synonyms plus bounded bulk/cursor execution; not an exhaustiveness claim |
Native semantic |
| Conceptual similarity in title/abstract space | Capability validation; OpenAlex semantic mode, max 50 |
Exploration |
| From key paper | Citation network, related |
🤖 Claude Skills (AI Agent Workflows)
Pre-built workflow guides in .claude/skills/, divided into Usage Skills (for using the MCP server) and Development Skills (for maintaining the project):
📚 Usage Skills (11) — For AI Agents Using This MCP Server
Skill | Description |
| Basic search with filters |
| MeSH expansion, comprehensive |
| Clinical question decomposition |
| Citation tree, related articles |
| Persistent, versioned research evolution |
| Gene/PubChem/ClinVar |
| Europe PMC, CORE full text |
| RIS/BibTeX/CSV/CSL export guidance |
| Cross-database unified search |
| Complete tool reference guide |
| Save, load, reuse search plans |
🔧 Development Skills (15) — For Project Contributors
Skill | Description |
| Auto-update CHANGELOG.md |
| DDD architecture refactoring |
| Code quality & security review |
| DDD scaffold for new features |
| Sync docs before commits |
| Pre-commit workflow orchestration |
| Save context to Memory Bank |
| Update Memory Bank files |
| Extract and inventory citation-ready PDF assets |
| Initialize new projects |
| Multilingual README sync |
| Sync README with code changes |
| Update ROADMAP.md status |
| Generate test suites |
| Keep the MCP registry and generated tool documentation aligned |
📁 Location:
.claude/skills/*/SKILL.md(Claude Code-specific, and the single source of truth for repo skills) Do not mirror or split repo skills into.github/skills/. These repo skills are project-scoped and should remain version-controlled. Personal cross-project skills belong in a user directory such as~/.copilot/skills/or~/.claude/skills/, not in this repository.
Research skill installation preserves existing customizations. See the installation and upgrade policy. Contributors run the full local gate before push; ordinary CI runs a smaller independent smoke gate.
The completed ten-phase core review covers all 223 Python files in src/pubmed_search/: 456 classes and 2,445 functions/methods/nested functions. Each of the 2,901 definitions has a recorded decision, evidence, and current file SHA-256; none are pending or stale. This is an authored self-review, separate from test results. Recheck the current tree with uv run python scripts/perf/symbol_inventory.py --require-reviewed src/; subsequent source edits invalidate affected reviews. Tests and scripts are inventoried but are outside this complete core-review claim.
Real MCP Regression Gate
Every one of the 41 public tools is called through the MCP protocol over source-tree stdio, Streamable HTTP, and stdio from a freshly installed wheel. The wheel path imports server code exclusively from its blank virtual environment; the external fixture supplies only deterministic provider seams. The deterministic child server replaces external-provider boundaries; registry, schemas, application services, persistence, artifacts, Chronicle revisions, pipelines, and scheduling remain real. The opt-in extended CI also renders the exact Chronicle and citation Mermaid sources returned over MCP with pinned Mermaid 11.16.1, so presentation-layer syntax damage fails the gate. An additional real-stdio rejection pass confirms that retired tool names, legacy flat request shapes, and scalar/stringified coercions remain rejected.
uv run pytest -q tests/test_all_tools_mcp_acceptance.pySee the Developer Guide for the test architecture, CI gates, and live-provider boundary.
🏗️ Architecture (DDD)
This project uses Domain-Driven Design (DDD) architecture, with literature research domain knowledge as the core model.
src/pubmed_search/
├── domain/ # Core business logic
│ └── entities/article.py # UnifiedArticle, Author, etc.
├── application/ # Use cases
│ ├── search/ # QueryAnalyzer, ResultAggregator
│ ├── export/ # Citation export (RIS, BibTeX...)
│ └── session/ # SessionManager
├── infrastructure/ # External systems
│ ├── ncbi/ # Entrez, iCite, Citation Exporter
│ ├── sources/ # Europe PMC, CORE, CrossRef...
│ └── http/ # HTTP clients
├── presentation/ # User interfaces
│ ├── mcp_server/ # MCP tools, prompts, resources
│ │ ├── tools/ # discovery, strategy, pico, export...
│ │ └── http_cli.py # Canonical Streamable HTTP/SSE launcher
│ └── browser_fetch_broker.py # Optional isolated browser-fetch service
└── shared/ # Cross-cutting concerns
├── exceptions.py # Unified error handling
└── async_utils.py # Rate limiter, retry, circuit breakerInternal Mechanisms (Transparent to Agent)
Mechanism | Description |
Session | Auto-create, auto-switch |
Cache | Auto-cache search results, avoid duplicate API calls |
Rate Limit | Auto-comply with NCBI API limits (0.34s/0.1s) |
MeSH Lookup |
|
ESpell | Auto spelling correction ( |
Query Analysis | Each suggested query shows how PubMed actually interprets it |
Vocabulary Translation Layer (Key Feature)
Our Core Value: We are the intelligent middleware between Agent and Search Engines, automatically handling vocabulary standardization so Agent doesn't need to know each database's terminology.
Different data sources use different controlled vocabulary systems. This server provides automatic conversion:
API / Database | Vocabulary System | Auto-Conversion |
PubMed / NCBI | MeSH (Medical Subject Headings) | ✅ Full support via |
ICD Codes | ICD-10-CM / ICD-9-CM | ✅ Auto-detect & convert to MeSH |
Europe PMC | Text-mined entities (Gene, Disease, Chemical) | ✅ |
OpenAlex | Topics / keywords (model-inferred) | ✅ Broker keyword mode; bounded native semantic mode when selected |
Semantic Scholar | S2 fields / bulk query syntax | ✅ Broker chooses relevance or bounded bulk mode; provider annotations keep provenance |
CORE | None | ❌ Free-text only |
CrossRef | None | ❌ Free-text only |
Automatic ICD → MeSH Conversion
When searching with ICD codes (e.g., I10 for Hypertension), unified_search() automatically:
Detects ICD-10/ICD-9 patterns via
detect_and_expand_icd_codes()Looks up corresponding MeSH terms from internal mapping (
ICD10_TO_MESH,ICD9_TO_MESH)Expands query with MeSH synonyms for comprehensive search
# Agent calls unified_search with clinical terminology
unified_search(query="I10 treatment outcomes")
# Server auto-expands to PubMed-compatible query
"(I10 OR Hypertension[MeSH]) treatment outcomes"📖 Full architecture documentation: ARCHITECTURE.md
MeSH Auto-Expansion + Query Analysis
When calling generate_search_queries("remimazolam sedation"), internally it:
ESpell Correction - Fix spelling errors
MeSH Query -
Entrez.esearch(db="mesh")to get standard vocabularySynonym Extraction - Get synonyms from MeSH Entry Terms
Query Analysis - Analyze how PubMed interprets each query
{
"mesh_terms": [
{
"input": "remimazolam",
"preferred": "remimazolam [Supplementary Concept]",
"synonyms": ["CNS 7056", "ONO 2745"]
}
],
"all_synonyms": ["CNS 7056", "ONO 2745", ...],
"suggested_queries": [
{
"id": "q1_title",
"query": "(remimazolam sedation)[Title]",
"purpose": "Exact title match - highest precision",
"estimated_count": 8,
"pubmed_translation": "\"remimazolam sedation\"[Title]"
},
{
"id": "q3_and",
"query": "(remimazolam AND sedation)",
"purpose": "All keywords required",
"estimated_count": 561,
"pubmed_translation": "(\"remimazolam\"[Supplementary Concept] OR \"remimazolam\"[All Fields]) AND (\"sedate\"[All Fields] OR ...)"
}
]
}Value of Query Analysis: Agent thinks
remimazolam AND sedationonly searches these two words, but PubMed actually expands to Supplementary Concept + synonyms, results go from 8 to 561. This helps Agent understand the difference between intent and actual search.
🔒 Local HTTPS Demo and Service Deployment
The bundled self-signed certificates and curl -k flow are a local TLS demo,
not a production security profile. For a shared service, use the authenticated
service Compose file and a trusted certificate as described in
DEPLOYMENT.md.
Local HTTPS Smoke Test
# Step 1: Generate SSL certificates
./scripts/generate-ssl-certs.sh
# Step 2: Start HTTPS service (Docker)
./scripts/start-https-docker.sh up
# Verify deployment
curl -k https://localhost/HTTPS Endpoints
Service | URL | Description |
MCP |
| Streamable HTTP MCP endpoint |
Health |
| Health check |
Ready |
| Readiness check |
Info |
| Runtime transport and endpoint metadata |
Exports |
| Local prepared export listing; service mode requires bearer auth and tenant scope |
Remote MCP Client Configuration
{
"mcpServers": {
"pubmed-search": {
"url": "https://localhost/mcp"
}
}
}🏢 Microsoft Copilot Studio Integration
Integrate PubMed Search MCP with Microsoft 365 Copilot (Word, Teams, Outlook)!
Quick Start
# Unpublished local schema/protocol smoke only; never tunnel local mode
pubmed-search-mcp-http --mode local --transport streamable-http \
--copilot-compatible --host 127.0.0.1 --port 8765
# Public Copilot endpoint: authenticated service mode is mandatory
export PUBMED_AUTH_TOKENS="copilot:$(openssl rand -hex 32)"
export NGROK_DOMAIN="your-assigned-domain.ngrok.dev"
./scripts/start-copilot-studio.sh --with-ngrokCopilot Studio Configuration
Field | Value |
Server name |
|
Server URL |
|
Authentication | Bearer token for service mode; |
📖 Full documentation: copilot-studio/README.md
Use
pubmed-search-mcp-http --copilot-compatiblefor packaged Copilot HTTP semantics.run_server.pyremains a source-tree development wrapper;run_copilot.pyis a loopback-only smoke launcher for the same canonical 41-tool strict registry, not a second compatibility surface. The tunnel script requires an assignedNGROK_DOMAIN, refuses occupied backend ports, and publishes only after--mode servicepasses readiness and unauthenticated-rejection checks.⚠️ Note: SSE transport deprecated since Aug 2025. Use
streamable-http.
📖 More documentation:
Architecture → ARCHITECTURE.md
Pipeline tutorial (English) → docs/PIPELINE_MODE_TUTORIAL.en.md
Pipeline tutorial (zh-TW) → docs/PIPELINE_MODE_TUTORIAL.md
Deployment guide → DEPLOYMENT.md
Copilot Studio → copilot-studio/README.md
🔐 Security
Security Features
Layer | Feature | Description |
HTTPS | TLS termination | Required for remote credentials; the bundled self-signed profile is local-only |
Bearer authentication | Stable principal | Mandatory in service mode and used for tenant authorization |
Tenant storage | Filesystem isolation | Sessions, artifacts, exports, chronicles, and pipelines are stored below the authenticated principal |
Fairness and rate policy | Tenant concurrency + shared upstream budgets | Prevents one caller from multiplying an upstream API allowance |
Security headers | Clickjacking/MIME hardening | Reverse-proxy headers complement authentication; they are not CSRF authorization |
Secret handling | Runtime secret injection | API keys and bearer tokens must come from deployment secrets/environment and must not be committed or logged |
See DEPLOYMENT.md for detailed deployment instructions.
📤 Export Formats
Export your search results in formats compatible with major reference managers:
Format | Source | Compatible With | Use Case |
RIS | official or local | EndNote, Zotero, Mendeley | Universal import |
MEDLINE | official or local | PubMed tools | Native PubMed-style archiving |
CSL JSON | official | Citation processors | Programmatic citation styling |
BibTeX | local | LaTeX, Overleaf, JabRef | Academic writing |
CSV | local | Excel, Google Sheets | Data analysis |
JSON | local | Programmatic access | Custom processing |
Exported Fields
Core: PMID, Title, Authors, Journal, Year, Volume, Issue, Pages
Identifiers: DOI, PMC ID, ISSN
Content: Abstract (HTML tags cleaned)
Metadata: Language, Publication Type, Keywords
Access: DOI URL, PMC URL, Full-text availability
Special Character Handling
BibTeX exports use pylatexenc for proper LaTeX encoding
Nordic characters (ø, æ, å), umlauts (ü, ö, ä), and accents are correctly converted
Example:
Søren Hansen→S{\o}ren Hansen
📚 Citation
GitHub will show Cite this repository from CITATION.cff. If you use PubMed Search MCP in research, methods sections, or internal technical reports, prefer the GitHub-generated citation or reuse the repository metadata directly.
@software{pubmed_search_mcp,
title = {PubMed Search MCP},
author = {u9401066},
url = {https://github.com/u9401066/pubmed-search-mcp}
}📄 License
Apache License 2.0 - see LICENSE
🔗 Links
Available Tools
41 toolsanalyze_search_queryARead-onlyIdempotent
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
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds the key behavioral fact that no search is executed and enumerates the analysis output (complexity, intent, PICO, recommendations), which is genuine value beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and constraint in the first sentence, then efficiently documents args and returns. The Returns list is a bit verbose but each line conveys distinct return fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by enumerating the analysis return fields. For a single-param read-only tool whose annotations cover safety, this is nearly complete; only deeper query-format guidance is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and there is one parameter, so the description must carry the meaning. It only restates 'query: The search query to analyze' with no added syntax, format, or length guidance beyond the schema's minLength/maxLength constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Analyze a search query') and immediately scopes it with the constraint 'without executing the search', which cleanly distinguishes it from the sibling unified_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly frames usage as a pre-flight step to unified_search ('understanding how unified_search will process your query before actually running it'), naming the alternative and the condition that selects this tool. It does not state when not to use it, but the routing is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
build_citation_treeARead-onlyIdempotent
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 format. Includes metadata and statistics regardless of format.
Example usage: # Build 2-level tree for a paper (default Cytoscape.js format) build_citation_tree(pmid="33475315", depth=2, direction="both")
# Use AntV G6 format for modern web visualization
build_citation_tree(pmid="33475315", depth=2, output_format="g6")
# Export GraphML for Gephi analysis
build_citation_tree(pmid="33475315", depth=2, output_format="graphml")
| Name | Required | Description | Default |
|---|---|---|---|
| pmid | Yes | ||
| depth | No | ||
| direction | No | both | |
| output_format | No | cytoscape | |
| limit_per_level | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, but the description adds substantial behavioral detail: API load control via single-PMID restriction, performance caveats for depth=3 ('~100+ API calls'), return format (Markdown summary followed by JSON graph data), and the guarantee that metadata and statistics are included regardless of format. This goes well beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with clear headers, bullet lists, and practical examples, and the critical single-PMID warning is front-loaded. However, it is somewhat redundant: the output_format options are listed twice—once in the overview and again in the Args section—with overlapping wording. Some trimming would make it tighter without losing value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with five parameters, no output schema, and multiple dependent concepts, the description is remarkably complete. It covers input constraints, parameter semantics, performance behavior, output structure, format options, and example invocations. An agent has everything needed to select and invoke the tool correctly, including how to interpret the returned data.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the full burden of explaining parameters, and it does. Each parameter—pmid, depth, direction, limit_per_level, output_format—receives meaningful semantics including examples, default values, allowed ranges, and format-specific use cases. The description fully compensates for the empty schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Build a citation tree (network) from a single article,' a specific verb-resource pairing that clearly defines the tool's function. It further distinguishes itself from siblings like find_citing_articles and get_article_references by emphasizing the visual network/lineage aspect across both citing and referenced directions, making the tool's unique purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: it accepts only one PMID at a time, explains multi-paper usage, and recommends defaults like depth=2 and direction='both'. However, it does not explicitly instruct when to prefer this tool over sibling tools such as find_citing_articles or get_article_references, nor does it state exclusions beyond the single-PMID constraint.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
build_research_chronicleA
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: Comma-separated PMIDs, 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 window.
output: "summary" (default compact Markdown with the chronological
spine), "json", "chronicle_map", "timeline", "tree",
"graph", "evidence", "milestones", "mermaid" (horizontal
time spine with lineage branches), or "narrative".
"json", "chronicle_map", "timeline", "tree", "graph",
"evidence", and "milestones" return JSON; the rest return
Markdown.
Returns:
The requested rendering plus an artifact locator when durable
artifact persistence is enabled and succeeds. The artifact contains
the full snapshot, projections, evidence table, milestone analysis,
and audit regardless of output. Artifact failure is reported but
does not roll back the already saved Chronicle revision.
Examples: build_research_chronicle(topic="remimazolam") build_research_chronicle(pmids="last", topic="My Reading List") build_research_chronicle(topic="CAR-T therapy", output="mermaid") build_research_chronicle(chronicle_id="remimazolam-9f2b1c4d")
| Name | Required | Description | Default |
|---|---|---|---|
| pmids | No | ||
| topic | No | ||
| output | No | summary | |
| max_year | No | ||
| min_year | No | ||
| max_events | No | ||
| chronicle_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, idempotentHint=false, destructiveHint=false), the description discloses key behavioral traits: it persists a revision-numbered chronicle, re-running creates revision N+1, artifact failure is reported without rolling back the saved chronicle, and agreement between projections is not independent evidence verification. This is rich, non-obvious behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although long, the description is tightly organized and information-dense: a front-loaded definition, a concise conceptual model, then a structured Args block and Returns explanation. Every section adds decision-relevant detail for a complex 7-parameter tool, and no sentence merely restates the tool name or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with no required parameters, no output schema, and three invocation modes, the description is complete. It covers all parameter interdependencies, rendering formats, return behavior, artifact persistence, and failure semantics, leaving no critical gap an agent would need to guess about.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden, and it delivers. Every parameter is semantically explained: topic's mutual exclusivity with pmids/chronicle_id, the special 'last' value for pmids, max_events inheritance behavior, year bounds, chronicle_id continuation semantics, and detailed return-type differences for output values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb-plus-resource statement: 'Build a persisted, versioned, evidence-backed Research Chronicle.' It then distinguishes itself from older one-shot timeline tools and names its role as the single entry point for research-evolution work, making it easy for an agent to differentiate this from siblings like read_research_chronicle.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes usage conditions explicit: it replaces older one-shot timeline tools, topic mode versus pmids mode versus continuing via chronicle_id are clearly explained, and parameter-specific guidance (e.g., 'pmids="last"', 'Passing it alone re-runs the stored scope') tells the agent exactly when each invocation style is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
configure_institutional_accessADestructiveIdempotent
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: ═══════════════════════════════════════════════════════════════════════════════
Your library subscribes to journals through publishers
Library provides a "Link Resolver" service (SFX, 360 Link, Primo, etc.)
OpenURL passes article metadata to the resolver
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: ═══════════════════════════════════════════════════════════════════════════════
Go to your library's website
Look for "Find Full Text", "Link Resolver", or "OpenURL"
Or search: "[Your University] link resolver"
The URL usually looks like:
Args: resolver_url: Your institution's link resolver URL preset: Use a known institution's preset configuration enable: Whether to enable OpenURL links (default: True) Returns: Configuration status message
| Name | Required | Description | Default |
|---|---|---|---|
| enable | No | ||
| preset | No | ||
| resolver_url | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=true, and idempotentHint=true. The description adds meaningful behavioral context: remote callers can inspect the operator-installed configuration with no arguments, cannot mutate server-owned OpenURL settings, and should configure those via deployment or a trusted local server. It does not explicitly state what happens if a remote caller attempts mutation or whether applying a preset overwrites existing settings.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loads the core purpose and security constraint, but it is long and includes nonessential content such as the four-step 'HOW IT WORKS' explanation and detailed 'FINDING YOUR RESOLVER URL' instructions. The ASCII decoration adds visual structure but also verbosity; it is more of a user guide than a tightly focused agent tool definition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description at least states 'Returns: Configuration status message.' It covers all invocation modes, parameter semantics, preset options, and the important remote-vs-deployment permission distinction. It would be more complete if it pointed to test_institutional_access or diagnose_institutional_access for verifying or troubleshooting the configured access, and if it described the return format more precisely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates well by explaining resolver_url, preset, and enable, including examples and the note that sfx, 360link, and primo require resolver_url. It maps to all three parameters and gives defaults for enable. Minor gaps: the preset 'test_free' from the schema is not documented, and the description does not state whether preset and resolver_url are mutually exclusive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb and resource: 'configure your institution's link resolver for full-text access' and 'This tool configures OpenURL link resolver integration.' It is distinct from most sibling tools by name and stated purpose, though it does not explicitly contrast itself with close siblings like test_institutional_access or diagnose_institutional_access.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives three concrete usage modes: preset, custom URL, and disable. It also provides an explicit boundary for remote callers: they may inspect with no arguments but cannot mutate server-owned deployment-wide settings, and should configure those at deployment time or from a trusted local server. It does not explicitly mention sibling tools like list_resolver_presets as alternatives, but the context is otherwise clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
convert_icd_meshARead-onlyIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | ||
| direction | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, and closed-world traits, so the bar is lower. The description adds genuinely useful context beyond them: the crosswalk is 'curated' and a 'limited convenience' mapping, disclosing data-quality/coverage limitations an agent would not otherwise know.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with the core purpose and followed by direction routing and a limitation. No filler; every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description bears the burden of describing returns. It gestures at the mapping quality ('limited convenience crosswalk') but never describes the shape of the result (single term vs. list, ambiguity handling), leaving a gap for a mapping tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does: it explains that 'value' must be one complete ICD-9-CM or ICD-10-CM code for the icd_to_mesh direction or a MeSH term for mesh_to_icd. It does not address code formatting (dots) or the 500-char limit, so it is not exhaustive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Query the curated ICD/MeSH crosswalk in one explicit direction.' An agent immediately knows this maps between ICD and MeSH vocabularies, and no sibling tool covers terminology crosswalking, so differentiation is moot.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes each enum value: 'icd_to_mesh' with a complete ICD-9-CM/ICD-10-CM code, 'mesh_to_icd' with a MeSH term. It also adds a when-not caveat (not a substitute for a licensed UMLS service), which is exactly the kind of selection guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_pipelineADestructiveIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds genuinely useful context beyond them: that execution history is destroyed (not just the config) and that process-level schedules are removed only after the deletion succeeds, with isolated tenants exempt from scheduler mutation. That is real side-effect disclosure the annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the destructive action in the first sentence, then adds the tenant/scheduler caveat, then Args/Returns. Efficient and well-organized, though the tenant-scheduler sentence is somewhat more detailed than most callers need.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description covers the return ('Confirmation of deletion'), the scope of destruction, and the scheduler side effect. It is nearly complete for a single-parameter destructive tool; only name-discovery and irreversibility recovery guidance are missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description only restates the obvious ('name: Name of the saved pipeline to delete'). It does not explain the naming constraints already implied by the schema (lowercase, pattern, 64-char limit) or how to discover valid names, so it adds little beyond a bare restatement.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Permanently delete a saved pipeline configuration and execution history'), which is enough to separate it from save_pipeline, list_pipelines, and load_pipeline. It does not explicitly contrast itself with the very similar unschedule_pipeline sibling, which also touches scheduling, so sibling differentiation is only partial.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the word 'Permanently' hints this is the irreversible removal path, but there is no explicit when-to-use/when-not guidance and no pointer to unschedule_pipeline for the case where the user only wants to cancel scheduling. The agent must infer the boundary between delete and unschedule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diagnose_institutional_accessARead-onlyIdempotent
Diagnose why institutional fulltext access succeeds or fails for an article.
Runs up to three probes and reports each path's outcome:
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).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
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.
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | ||
| try_direct | No | ||
| try_ezproxy | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only/idempotent/open-world, but the description adds substantial operational context beyond them: a three-phase probe strategy, IP-awareness, BYO-cookie EZproxy replay, the specific env vars required, and a manual OpenURL handoff. It also discloses that a PMID is converted to a DOI before probing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the one-line purpose, then a numbered probe list, usage examples, and args/returns sections — well organized and largely waste-free. It is on the long side, but the length is justified by the multi-phase behavior and configuration requirements.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by describing the return value ('Markdown report listing every probe's status, classification, and advice'). Combined with the phase breakdown and required env vars, an agent has everything needed to invoke and interpret the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden and largely does: 'source' is explained as exactly one PMID or DOI with the PMID-to-DOI resolution note, and try_direct/try_ezproxy are mapped to Phase 1 and Phase 2 with their defaults. Minor gap: it doesn't restate the DOI/PMID value formats already enforced by the schema patterns.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Diagnose why institutional fulltext access succeeds or fails for an article') and enumerates the three probe phases, which cleanly separates it from siblings like test_institutional_access and configure_institutional_access. An agent can identify the tool's job without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains the conditions under which each probe runs (IP allow-list auto-works; EZproxy requires env vars; OpenURL is a manual fallback) and provides concrete usage examples with try_ezproxy=False. However, it never explicitly routes the agent against alternatives such as test_institutional_access or get_fulltext, leaving that comparison to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_article_detailsBRead-onlyIdempotent
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) Inputs are string-only and fail as a complete batch when any PMID is invalid.
Returns: Detailed information for each article.
| Name | Required | Description | Default |
|---|---|---|---|
| pmids | Yes | ||
| output_format | No | markdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, openWorldHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds meaningful behavioral detail beyond annotations, especially the batch failure semantics: inputs fail as a complete batch when any PMID is invalid. This is genuinely useful and not inferable from schema or annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, well-organized with 'Args' and 'Returns', and front-loads the core purpose before parameter details. The bulleted pmids format list is efficient. The only minor issue is the slightly ambiguous phrase 'Inputs are string-only' after listing array support, and the 'Returns' line adds little beyond the first sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema, the description covers batch input behavior and the main parameter well. But it omits the output_format parameter, does not explain return details or structure, and lacks guidance on when this tool is preferable to sibling tools. These gaps leave the agent with uncertainty about how to use the tool effectively in a larger workflow.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It does a good job for pmids by listing accepted formats and the string-only constraint. However, it completely ignores output_format, which is surfaced only in the schema. The enum and default are self-explanatory, but the description still misses an opportunity to clarify formats like 'toon'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb ('Fetch') and resource ('detailed information for ... PubMed articles'), and signals batch capability with 'one or more'. However, it does not distinguish this tool from sibling retrieval tools like get_fulltext, find_related_articles, or get_article_figures, so it falls short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives, and it does not mention any exclusions or prerequisites. While the accepted pmids formats are documented, the usage context—such as 'use this for article metadata, get_fulltext for full text'—is entirely absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_citing_articlesARead-onlyIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| pmid | Yes | ||
| limit | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, open-world, and non-destructive behavior. The description adds the PubMed Central citation data source and the forward-in-time direction, but does not cover rate limits, permissions, or detailed return behavior beyond a generic list. With annotations carrying the safety profile, this is useful added context but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is front-loaded and the description is well organized. However, it is heavily padded with decorative separators, emojis, and repeated headers, and some content is redundant, which hurts conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, usage, parameters, data source, and a basic return description. Since there is no output schema, it could more precisely describe the citing-article fields or pagination behavior, but it is largely complete for a simple read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It documents both parameters: the pmid format ('12345678' or 'PMID:12345678') and the limit range/default (1-100, default 10). This fully covers the two parameters and adds meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: find articles that cite a given PubMed article, explicitly scoped as a forward citation search. The complementary tools section names get_article_references and find_related_articles and explains how they differ, so an agent can select this tool without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit use cases such as tracking research impact, finding follow-up studies, identifying controversies, and literature review. It also names the backward-search and topic-based alternatives, giving clear when-to-use and when-not-to-use context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_search_queriesARead-onlyIdempotent
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="") Step 4: unified_search(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_search_query()
Step 6: Execute unified_search() with the final Boolean query══════════════════════════════════════════════════════════════════════
Features:
Spelling correction via NCBI ESpell
MeSH term lookup for standardized vocabulary
Synonym expansion from MeSH database
Query analysis: Shows how PubMed actually interprets each query (Agent's understanding vs PubMed's actual interpretation)
Args: topic: Search topic - can be a single keyword or PICO element strategy: Affects suggested_queries (if included) - "comprehensive": Multiple angles, includes reviews (default) - "focused": Adds RCT publication-type filter; study quality still requires appraisal - "exploratory": Broader search with more synonyms check_spelling: Whether to check/correct spelling (default: True) include_suggestions: Include pre-built query suggestions (default: True)
Returns: JSON with RAW MATERIALS: - corrected_topic: Spell-checked topic - keywords: Extracted significant keywords - mesh_terms: MeSH data with preferred terms and synonyms - all_synonyms: Flattened list of all synonyms - suggested_queries: Optional pre-built queries with: - estimated_count: How many results PubMed would return - pubmed_translation: How PubMed actually interprets the query
| Name | Required | Description | Default |
|---|---|---|---|
| topic | Yes | ||
| strategy | No | comprehensive | |
| check_spelling | No | ||
| include_suggestions | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false. The description adds meaningful behavior beyond this: it returns raw materials rather than final queries, performs spelling correction via NCBI ESpell, does MeSH/synonym expansion, and can show PubMed's actual interpretation of a query. This gives the agent an accurate model of what the tool does and does not do.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and then structured into two clear usage modes, which helps an agent navigate a complex workflow. It is quite long with decorative separators and redundant step numbering, but nearly every section carries operational value, so the verbosity is justified for this tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully enumerates the return fields: corrected_topic, keywords, mesh_terms, all_synonyms, and suggested_queries with estimated_count and pubmed_translation. It also covers the two main invocation contexts and how to chain with siblings, so an agent has everything needed to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description's Args section fully compensates. It explains topic as 'a single keyword or PICO element,' defines all three strategy values with their effects on suggested_queries, states defaults for check_spelling and include_suggestions, and clarifies how the parameters affect behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb and resource: 'Gather search intelligence for a topic' and explicitly frames the output as 'RAW MATERIALS' and 'BUILDING BLOCKS for search, not finished queries.' This distinguishes it from siblings like analyze_search_query and unified_search, whose jobs are to validate and execute queries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides two explicit usage modes with step-by-step protocols: Mode 1 for single-topic keyword search and Mode 2 for PICO-based clinical questions. It names exact sibling tools to call before and after this tool, including validate_pico_plan, analyze_search_query, and unified_search, so an agent knows when to use this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_article_figuresARead-onlyIdempotent
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"})
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | ||
| output_format | No | markdown | |
| include_tables | No | ||
| include_subfigures | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, open-world, and non-destructive behavior. The description adds meaningful context beyond annotations: it restricts to PMC Open Access articles, explains that PDF links are returned, and clarifies the effects of include_subfigures and include_tables. It does not discuss authentication or rate limits, but these are likely unnecessary for a read-only open API.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with Args, Returns, and Example sections and front-loads the core purpose. However, the return information is repeated across the opening paragraph and the Returns section, which is mildly redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given four parameters (one required), no output schema, and annotations that cover safety, the description provides example usage, return content, and parameter guidance, making it largely complete. The missing semantics for output_format and the absence of error or empty-result behavior are minor gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description compensates well for three of four parameters: source is explained with example JSON objects and a note about the discriminated union, and include_subfigures and include_tables are described in functional terms. The output_format parameter is not mentioned at all, leaving a notable gap in parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Get structured figure metadata... and PDF links') and scopes it to a PMC Open Access article, clearly differentiating it from tools that fetch full text, references, or general image searches. The inclusion of output fields (label, caption, image URL, PDF links) makes the purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use when figures from a PMC Open Access article are needed, but it does not explicitly state when to use this tool versus alternatives like fetch_article_details, get_fulltext, or search_biomedical_images. No conditions or exclusions are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_article_referencesARead-onlyIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| pmid | Yes | ||
| limit | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld, and non-destructive, so the safety profile is covered. The description adds genuine context: the backward-in-time direction, that it returns a bibliography list, and the limit range. It stops short of describing ordering or pagination behavior, but the annotation coverage lowers the bar.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core definition is correctly front-loaded in the first three lines, but the rest is bloated with emoji banners, ASCII rules, and a multi-step workflow example that repeats usage information already stated. Much of the decoration does not earn its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read tool with no output schema, the description covers purpose, direction, parameters, and usage adequately; the 'Returns' note is appropriately brief since it is itself a thin summary. Slightly more on result ordering or limit semantics would complete it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the load. It documents the pmid accepted formats ('12345678' or 'PMID:12345678') and the limit range/default, adding real meaning beyond the bare schema types. It could be slightly richer about what happens at the limit boundary, but it compensates well for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get the references of a PubMed article') and immediately distinguishes itself from the sibling find_citing_articles by contrasting citation direction. An agent can select this without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative (find_citing_articles), gives the condition that selects each, and lists four concrete use cases. Nothing is left to inference about when to reach for this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_citation_metricsARead-onlyIdempotent
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) - "PMID:12345678" (with prefix) - "last" to use PMIDs from the last search Batches are fail-closed and limited to 1,000 unique PMIDs. 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.
| Name | Required | Description | Default |
|---|---|---|---|
| pmids | Yes | ||
| min_rcr | No | ||
| sort_by | No | citation_count | |
| min_citations | No | ||
| output_format | No | markdown | |
| min_percentile | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, non-destructive and openWorld, so the safety profile is covered. The description adds genuine behavioral context beyond that: fail-closed batching capped at 1,000 unique PMIDs, and the guarantee that iCite transport/response failures surface as retryable errors rather than empty results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads purpose, then return fields, then args, then return behavior—logical and scannable. There is mild redundancy in listing the return fields once in the intro and again under 'Returns', but every section still earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by enumerating returned fields and explaining failure semantics, which is what an agent needs to call and interpret the tool. The only real gap is the undocumented output_format parameter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden, and it does so well for five of six parameters: accepted PMID formats, meaningful sort_by options with a recommended value, and threshold semantics for min_citations/min_rcr/min_percentile. It omits output_format (markdown/json/toon), leaving one enum undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get citation metrics from NIH iCite for articles'), names the upstream source, and enumerates exactly which metrics are returned. An agent can distinguish this from siblings like find_citing_articles or fetch_article_details without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides useful in-tool guidance such as accepting 'last' to reuse PMIDs from the preceding search, which implicitly ties it to the search workflow. However, it never states when to prefer this tool over siblings such as find_citing_articles or fetch_article_details, so usage is implied rather than directed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_compound_detailsBRead-onlyIdempotent
Get detailed information about a compound by PubChem CID.
Args: cid: PubChem Compound ID
Returns: JSON with compound details including formula, SMILES, properties
| Name | Required | Description | Default |
|---|---|---|---|
| cid | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is covered. The description adds value by stating the return payload contents (formula, SMILES, properties), but says nothing about error behavior for invalid CIDs or rate limits on the external PubChem service.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded one-line purpose followed by short Args/Returns blocks. No filler, though the Args/Returns labels are slightly heavy for a single-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple single-parameter read tool with no output schema, the description supplies enough: purpose, the parameter's meaning, and the shape of the return. The missing piece is routing guidance relative to search_compound.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the load. It expands 'cid' into 'PubChem Compound ID', which is more than the bare string-typed schema property, but it omits the numeric-string format constraint captured only by the schema pattern.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get detailed information about a compound') and names the identifying key (PubChem CID). It does not distinguish itself from the sibling search_compound, but an agent can still tell what this tool does from the name and description alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this over search_compound or get_compound_literature, nor any prerequisite or CID-acquisition note (e.g., you must first call search_compound). The agent is left to infer the workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_compound_literatureBRead-onlyIdempotent
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
| Name | Required | Description | Default |
|---|---|---|---|
| cid | Yes | ||
| limit | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld and non-destructive, so safety behavior needs no repetition. The description adds genuine value by disclosing provenance ('NCBI's curated compound-to-publication links') and a return summary, though with no output schema this remains thin on pagination or failure behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Short and front-loaded, with the core purpose in the first sentence and Args/Returns scaffolding after. The Args/Returns headers are slightly mechanical but cost little and aid scannability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter read tool with no output schema, the description covers purpose, both parameters, the data source, and the return shape (JSON with linked PubMed IDs). Nothing essential for a correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning, and it does: 'cid: PubChem Compound ID' and 'limit: Maximum PubMed IDs to return (1-100)'. This maps directly to both parameters and clarifies the cid format beyond the bare 'string' pattern, though it adds nothing about what happens when no links exist.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get PubMed articles linked to a compound') and names the underlying data source, which cleanly separates it from sibling literature tools like get_gene_literature by resource type. It stops short of explicitly naming or contrasting alternatives, so it is clear but not sibling-differentiating at the highest level.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no when-to-use, when-not-to-use, or alternative-tool guidance; an agent must infer from the resource name that this is the right call for compound-linked literature. The mention of NCBI's curated links hints at the data source but not at usage conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_fulltextA
🔥 Enhanced multi-source fulltext retrieval.
Automatically tries multiple sources to find the best fulltext:
Europe PMC (if PMC ID available)
Unpaywall (finds OA versions via DOI)
Institutional direct/EZproxy fetch (when DOI-backed and enabled)
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 sections (e.g., "introduction,methods,results") include_pdf_links: Include PDF download links (default: True) 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"})
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | ||
| sections | No | ||
| output_format | No | markdown | |
| include_figures | No | ||
| extended_sources | No | ||
| include_pdf_links | No | ||
| allow_browser_session | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses the source-selection order, extended source behavior, browser-session fallback semantics, and the return shape. This is valuable beyond the annotations, which only provide openWorldHint and non-destructive flags. It does not mention potential side effects like external network calls or rate limits, but it covers the core behavioral traits well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: source priority list, extended sources, per-parameter semantics, return value, and examples. It is well-structured with clear headings and no filler, making it easy for an agent to parse and act on.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 7 parameters, 0% schema description coverage, and no output schema, the description is thorough enough to allow correct invocation. It covers all parameter meanings, defaults, source input formatting, behavior, and return content. No critical operational detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden for parameters. It explains every parameter, gives concrete source object examples, clarifies output_format choices, and details allow_browser_session's three modes. This substantially exceeds what the raw schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves fulltext from multiple sources, with a specific priority chain and a source discriminated-union requirement. It distinguishes itself from sibling tools by emphasizing multi-source fulltext retrieval rather than metadata-only or figure-specific operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: when fulltext is needed and source identifiers (PMID, PMCID, DOI) are available. It also explains how to broaden retrieval with extended_sources. It does not explicitly name alternative sibling tools or state when not to use it, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_gene_detailsARead-onlyIdempotent
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
| Name | Required | Description | Default |
|---|---|---|---|
| gene_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered without the text. The description adds the return shape (symbol, name, summary, location), but says nothing about behavior for invalid/unknown gene IDs, rate limits, or external NCBI dependency despite openWorldHint=true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded one-line purpose followed by Args and Returns sections; every line earns its place with no filler or repetition of the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the Returns block usefully enumerates the JSON fields an agent can expect. Minor gap: no mention of error/missing-gene behavior, which matters for a single-required-param lookup tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the schema only conveys the type and a regex pattern, not meaning. The description compensates by defining gene_id as an NCBI Gene ID and indicating where to obtain it, which is more than the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Get detailed information') and resource ('a gene') keyed by NCBI Gene ID. It is clearly distinguishable from the search_gene sibling by the 'details vs search' distinction, though it never names that sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The parenthetical '(from search results or known)' implies the ID comes from a prior search, which is a useful workflow hint. However, it does not state when to use this over search_gene or get_gene_literature, nor any prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_gene_literatureARead-onlyIdempotent
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
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| gene_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds that it uses NCBI's curated links, which is useful behavioral context, but doesn't disclose rate limits, permissions, or return format details beyond a brief mention.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded: a clear one-sentence purpose, then a rationale, then parameter and return sections. Every part earns its place without unnecessary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with two parameters and no output schema, the description covers purpose, parameters, and return type adequately. It could mention pagination or handling of large result sets, but given the limit parameter and annotations, it is largely complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It documents both parameters: gene_id as NCBI Gene ID and limit as maximum PubMed IDs to return (1-100), matching the schema's constraints. This fully compensates for the lack of schema descriptions, though it doesn't elaborate on format beyond 'NCBI Gene ID'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Get) and resource (PubMed articles linked to a gene), and distinguishes itself from keyword-based search by explaining the source of the links. Sibling tools like search_gene and get_gene_details are clearly different, and get_gene_literature is explicitly about literature linked to a gene ID.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for retrieving linked articles but does not explicitly state when to use this versus alternatives like unified_search or get_compound_literature. It notes the method is 'more precise than keyword searches', which subtly suggests preference, but lacks clear when-to-use/when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_institutional_linkARead-onlyIdempotent
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
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, openWorld. The description adds valuable context beyond them: the hard dependency on prior resolver configuration and the fact that the call may return an error message rather than a link, which prepares the agent for a failure mode not captured in annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then prerequisites, then examples. The heavy ASCII separators add noise, but every substantive section (prerequisite, per-kind examples, args, returns) earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a single parameter, no output schema, and a rich annotation set, the description covers purpose, dependency, all three input shapes, and the return (link or error). Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Top-level schema description coverage is 0%, but the description compensates with full worked examples of each discriminated-union variant (pmid, doi, metadata), showing the 'kind' discriminator and field shapes. It also adds guidance ('easiest', 'most reliable') that the schema does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Generate institutional access link (OpenURL) for an article') and clarifies the mechanism (library link resolver to full text). An agent can distinguish it from siblings like get_fulltext or test_institutional_access without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the prerequisite ('Must first call configure_institutional_access()') and gives concrete usage patterns ranked by reliability ('easiest', 'most reliable'). It does not directly compare against alternatives such as get_fulltext for accessing full text, so it stops short of an explicit when-not-to-use rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_pipeline_historyARead-onlyIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| limit | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds real value beyond that by disclosing the return shape: per-entry date, article count, new/removed articles, and status. It doesn't mention behavior for a nonexistent pipeline name, but that is a minor gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose sentence followed by a short diff-analysis clarification, then Args/Returns blocks. The Args section mostly restates schema facts, which is minor redundancy, but nothing is padded or confusing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and 0% schema description coverage, the description supplies both parameter meaning and return-field detail, giving an agent enough to invoke and interpret the call. Only edge-case behavior (unknown pipeline name) is unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the burden and largely does: it explains 'name' as the saved pipeline's name and 'limit' as the maximum number of history entries with default 5. It omits the name pattern/max-length constraint and the limit's 1-100 range, which the schema does encode, so it is not fully compensating.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Get execution history for a saved pipeline') and adds the distinguishing detail that it returns diff analysis of new articles versus the previous run. It does not explicitly name how it differs from list_pipelines or load_pipeline, so it falls short of the 5 bar for sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to call this versus alternatives like list_pipelines, load_pipeline, or read_session. The description describes the content returned but never states a use context, prerequisite (e.g. the pipeline must already exist), or exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_text_mined_termsARead-onlyIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | ||
| output_format | No | markdown | |
| semantic_type | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so safety and repeatability are covered structurally. The description adds the useful constraint that `source` is exactly one PMID or PMCID (a scope limit not visible in annotations), but says nothing about rate limits, coverage gaps, or behavior for articles without mined terms.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and scope constraint are front-loaded in the first three lines, and the Args/Returns block is compact and scannable. Some redundancy exists between the prose entity list ('genes, diseases, chemicals, organisms') and the later semantic_type enumeration, costing a little efficiency.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly spends a line on return shape ('List of text-mined entities with counts and sections'). It is complete enough to call correctly, with the minor gaps of the undocumented output_format parameter and the missing EFO option.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden and largely does: it spells out the PMID/PMCID shape and enumerates the semantic_type options. It omits the `output_format` parameter entirely and omits the EFO value present in the schema enum, but the substantive parameters are well documented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get text-mined annotations from Europe PMC') and enumerates the entity types returned, which no sibling tool provides. An agent can distinguish this from get_article_figures, fetch_article_details, or get_fulltext without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains what is returned but gives no when-to-use or when-not-to-use guidance and names no alternative sibling (e.g., get_fulltext for raw text). The agent must infer that this tool is for entity extraction rather than full-text or figure retrieval.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_pipelinesARead-onlyIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No | ||
| scope | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the operation as read-only, idempotent, and non-destructive, lowering the burden. The description adds useful behavioral context by describing the returned table fields (name, scope, description, tags) and clarifying that empty filter values show all results. Minor gaps like ordering or pagination are not covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then uses compact Args and Returns sections. Every sentence adds information without redundancy, and the structure is easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool with rich annotations and no output schema, the description provides sufficient completeness by documenting filter semantics and the return table fields. Minor details like ordering or pagination are omitted but are not critical for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning. It documents both parameters well: tag with an example and empty behavior, and scope with its enum values and empty behavior. It does not mention the tag maxLength of 100 or the default values, but otherwise compensates thoroughly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (list) and resource (saved pipeline configurations), making the tool's purpose immediately clear. However, it does not explicitly differentiate itself from sibling pipeline tools like load_pipeline or get_pipeline_history.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description mentions filter behavior (tag and scope) but provides no guidance on when to use this tool versus alternatives such as load_pipeline or get_pipeline_history. No exclusions or prerequisites are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_resolver_presetsARead-onlyIdempotent
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
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a read-only, idempotent, non-destructive, closed-world listing tool. The description adds useful context about what the presets are and that the return value includes preset URLs, which matters because there is no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The substantive content is short and front-loaded, but the large ASCII banner and emoji add visual noise without conveying additional information. The core sentences earn their place, while the decorative formatting does not.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only listing tool with annotations covering safety and no output schema, the description adequately says what is returned: available presets with URLs. It could be slightly more precise about return structure, but it is complete enough to call correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
This tool takes zero parameters, so the baseline is 4. The description does not need to explain parameter semantics, and it does not introduce any confusion about inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List available institutional link resolver presets.' It also names the related sibling configure_institutional_access, which helps an agent distinguish listing presets from configuring access.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage by saying presets should be used with configure_institutional_access(preset="name"), but it does not explicitly say when to call this tool versus alternatives or when not to use it. The intended follow-up workflow is clear, but direct invocation guidance is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
load_pipelineARead-onlyIdempotent
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="")
Saved with changes: save_pipeline(name="...", config="")
Args: source: Pipeline source identifier (see above).
Returns: Full pipeline YAML content + metadata.
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as readOnly, idempotent, and non-destructive. The description adds useful behavioral details beyond those annotations, including the two supported source formats, the restriction on local-only files for authenticated service callers, and the fact that the returned YAML can be passed onward to unified_search or save_pipeline. This gives agents a clearer model of what happens after load.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded with the core purpose, followed by source formats, usage examples, and return behavior. It is slightly longer than strictly necessary because the Args/Returns formatting partially duplicates information already in the schema, but every section adds practical value for correct invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (one parameter), the description is nearly complete: it covers source variants, an important auth-related limitation, and the return value. It could arguably mention that list_pipelines can be used to discover valid saved names, but this is not essential for calling the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the schema only defines 'source' as a string with length constraints. The description fully compensates by explaining the accepted source formats with examples ('saved:weekly_remimazolam' and 'file:path/to/pipeline.yaml') and by clarifying the authentication restriction on file paths. This adds substantial meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Load a pipeline configuration for review or editing.' It clearly differentiates the load action from sibling tools like save_pipeline, delete_pipeline, and list_pipelines, and explains the two source types. The purpose is immediately understandable and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when this tool is appropriate: when a pipeline configuration needs to be reviewed, edited, or prepared for execution or saving. It also provides an explicit exclusion: local-only file sources are disabled for authenticated service callers. It does not explicitly name alternatives to avoid, but the workflow notes referencing unified_search and save_pipeline provide strong situational guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
prepare_exportA
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 - "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")
# Get CSL-JSON for programmatic use
prepare_export(pmids="last", format="csl", source="official")
| Name | Required | Description | Default |
|---|---|---|---|
| pmids | Yes | ||
| format | No | ris | |
| source | No | official | |
| include_abstract | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations by disclosing source-specific behavior, format restrictions, and a critical constraint: setting include_abstract=False requires source='local', while official payloads are returned unmodified. It also states the return shape despite the lack of an output schema, providing the agent with essential runtime expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although long, the description is well-organized with tables, section headings, and examples. Every section adds operational value, and the recommendation for source='official' is front-loaded. The length is justified by the tool's multiple interacting options and format-specific constraints.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with four parameters, no output schema, and format/source interactions, the description is remarkably complete. It covers input formats, format-by-source compatibility, return value shape, and includes three realistic examples. An agent has enough information to call this tool correctly in varied scenarios.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden. It thoroughly explains the pmids accepted forms ('last', comma-separated, list, 'PMID:' prefix), maps each format to its intended use, and clarifies source semantics. This adds substantial meaning beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Export citations to reference manager formats.' It clearly differentiates this tool from sibling search, retrieval, and analysis tools by listing concrete output formats such as RIS, BibTeX, and CSL, making its purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'When to Use' section explicitly names real-world scenarios like exporting to EndNote, Zotero, Mendeley, and generating BibTeX for LaTeX. It does not name alternatives to avoid, but the context is clear enough that an agent can infer when this tool is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
prepare_figure_searchARead-onlyIdempotent
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): ─────────────────────────────────────────────────────────
Provide an image (URL or base64-encoded)
This tool returns the image using MCP ImageContent protocol
YOU (the Agent) analyze the image using your vision capabilities
Extract relevant ENGLISH search terms from the image
Call
search_biomedical_images()orunified_search()with extracted terms when literature retrieval is within the user-requested scopeReturn 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-requested scope and the host agent's execution rules. Use English medical terminology in all search queries.
Args: source: Exactly one typed image source: {"kind": "base64", "data": "data:image/png;base64,..."} or {"kind": "url", "url": "https://example.org/figure.png"}. context: Optional context about what to look for in the image search_type: Type of analysis focus (comprehensive/methodology/results/structure/medical)
Returns: List containing: - ImageContent: The image for you to analyze - TextContent: Instructions for next steps
Example: prepare_figure_search(source={"kind": "url", "url": "https://example.com/figure1.png"}) prepare_figure_search( source={"kind": "base64", "data": "data:image/png;base64,iVBORw0..."} )
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | ||
| context | No | ||
| search_type | No | comprehensive |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds context about the tool's behavior (e.g., returns ImageContent, requires English terms, limitations like 'Experimental'), but it doesn't fully disclose edge cases or failure modes. The annotation readOnlyHint=true is consistent with the description, and the description adds some behavioral details beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is quite long and contains redundant explanations (e.g., repeating the workflow in different sections). It's structured with headings and examples, but it could be more concise. However, the structure helps readability, and the length is somewhat justified by the complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the tool's purpose, usage, examples, and search types, providing a fairly complete picture for an agent. It lacks some details like error handling or specific return format details, but overall it's comprehensive enough for basic usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description explains the 'source' parameter with examples and mentions 'context' and 'search_type' implicitly through the search types section. However, schema coverage is 0%, so the description carries more weight, but it doesn't fully explain all parameter nuances, especially 'context'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: it prepares a figure or image for literature search by returning the image for analysis. It includes specific action verbs and explains the workflow, which helps distinguish it from siblings like 'search_biomedical_images' or 'unified_search'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides detailed usage instructions, including step-by-step workflow, examples, and search types. It explicitly mentions the tool returns the image and that the host agent performs the analysis, but it doesn't explicitly differentiate when to use this tool versus alternatives like 'search_biomedical_images'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_research_chronicleARead-onlyIdempotent
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"]}})
| Name | Required | Description | Default |
|---|---|---|---|
| request | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/non-destructive, and the description adds genuine behavior beyond them: session-persistent evidence, instant analysis without re-search, and the important diff caveat that absence does not prove retirement. It also discloses that output is Markdown or JSON depending on action and format.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action inventory, then tightly scoped bullets per action, then the request-shape note and worked examples. Every section earns its place; the examples are justified by the discriminated-union request shape.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by stating the return type (Markdown or JSON, action/format dependent) and describing what each action yields. All six actions are individually explained, so nothing needed to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is reported as 0%, but the schema itself is highly self-documenting via consts, enums and discriminators. The description still adds meaning: `load` defaults to the latest revision, `diff`/`narrate` accept revisions, `compare` takes exactly 2-5 topics or Chronicle IDs, and enumerates valid `output` formats earlier than the enum list.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource ("Read stored Research Chronicles") and enumerates the six actions it fronts. It explicitly frames itself as the read facade over `build_research_chronicle`, so an agent can separate it from the sibling write tool without inspecting either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear context for when this tool is the right choice: chronicles persist across sessions and analysis/comparison are instant because no search is re-run. It does not name an explicit when-not-use case or point to competing read tools, but the purpose-driven context is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_sessionARead-onlyIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| request | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds non-obvious behavior the annotations do not: each action accepts only its own fields, local paths are redacted unless include_local_paths is set AND the server setting permits, and large artifacts require locator plus artifact_file with offset/max_chars paging.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with a one-line purpose, then a scannable action list, then a short paragraph of cross-cutting behavior; nearly every sentence carries information. The only waste is the omission of 'log' rather than an excess of text — nothing present is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly compensates by describing each action's return payload (PMIDs, cached article, summary plus optional history, artifact manifests, run envelopes, credential-free replay args). The main completeness gap is the unlisted 'log' action and the absence of any note on error/not-found or missing-session behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the schema is unusually self-documenting (patterns, enums, discriminator mapping, defaults), so the burden is light. The description still adds meaning beyond the schema by explaining the two locator kinds, the artifact_file/offset/max_chars paging contract, and the dual gating on include_local_paths, though it does not explain defaults such as search_index=-1 or session_id=null.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read session data') and then enumerates eight actions with their return payloads, so an agent can tell this apart from read_research_chronicle, fetch_article_details, and unified_search. The enumeration is incomplete, however: the schema defines nine discriminated requests but the 'log' action is omitted from the list, so an agent reading only the description would not know that action exists.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives real conditional guidance for the artifact path ('select an artifact_id or artifact_uri locator and use artifact_file plus offset/max_chars to page through large files') and warns that local paths are redacted unless two conditions are met. However, it never says when to choose read_session over its many siblings, nor does it state when an action is inappropriate; per-action field exclusivity is noted but not framed as selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_literature_notesADestructive
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
output_dir argument, if provided
PUBMED_NOTES_DIR environment variable
PUBMED_WORKSPACE_DIR/references
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", a PMID string, or a JSON array of PMID strings. 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(pmids="12345678,87654321", template_file="./ref-template.md")
| Name | Required | Description | Default |
|---|---|---|---|
| pmids | No | last | |
| overwrite | No | ||
| output_dir | No | ||
| note_format | No | wiki | |
| create_index | No | ||
| template_file | No | ||
| collection_name | No | ||
| include_abstract | No | ||
| include_csl_json | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true, idempotentHint=false and openWorldHint=true, and the description meaningfully extends this: it discloses the environment-variable resolution order, the tenant-isolation rule for authenticated callers (output_dir/template_file ignored), and that host paths are never leaked. That is context beyond what the annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the directive and well-sectioned under When to Use / Directory Resolution / Service Boundary / Args / Returns / Examples. The Args list is long but each entry earns its place; only minor trimming is possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 9 parameters, no output schema, and zero schema coverage, this description still supplies the write semantics, directory resolution, auth-boundary caveat, and an explicit Returns description including the wiki_validation output. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden for 9 params, and it does: pmids accepts 'last'/a string/JSON array, note_format's four values are explained, template_file placeholders are named, and include_csl_json's purpose (citation-manager handoff) is stated. Every parameter gets meaning the bare schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Save searched articles as ... wiki/Foam/Markdown notes') and immediately positions itself against siblings by calling out unified_search as the upstream and framing itself as 'a structured alternative to generic write_file calls'. An agent can identify the tool's role without reading the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Includes an explicit 'When to Use' section that sequences it after unified_search and names the alternatives it replaces. The Local Directory Resolution ordering and the Authenticated Service Boundary section add conditional guidance that decides how the tool behaves in different deployment contexts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_pipelineADestructive
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| tags | No | ||
| scope | No | auto | |
| config | Yes | ||
| description | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is known. The description adds genuinely useful behavior beyond that: upsert/overwrite semantics on name collision, the three-way scope meaning (workspace = git-trackable, global = cross-project, auto = fallback), and a return summary. One tension is worth noting: 'upsert semantics' implies repeated identical calls converge, while idempotentHint=false, and the description does not resolve this.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and format, then Args and Returns blocks that are easy to scan. The name constraint partially restates the schema's pattern/maxLength, a small redundancy, but otherwise every line carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter mutation tool with no output schema and empty schema descriptions, the definition covers all parameters, the config format, storage-scope semantics, overwrite behavior, and the retrieval path. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning, and it does: scope is spelled out with each enum's storage implication and default, tags are described as bounded canonical tags with an example, config is tied to the unified_search pipeline format, and name's uniqueness/overwrite behavior is stated. This fully compensates for the empty schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (save) and resource (pipeline configuration) plus the reuse intent. It is clearly distinguishable from siblings like list_pipelines, load_pipeline, delete_pipeline, and schedule_pipeline without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains the practical workflow: config format matches unified_search's pipeline param, and saved pipelines are retrieved via unified_search(pipeline="saved:name"), which tells the agent what this tool pairs with. It stops short of explicit when-not guidance or prerequisites (e.g., overwrite risk is mentioned but not framed as a caution).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
schedule_pipelineADestructive
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.
| Name | Required | Description | Default |
|---|---|---|---|
| cron | Yes | ||
| name | Yes | ||
| notify | No | ||
| diff_mode | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and openWorldHint=true, covering the mutation and external-effect profile. The description adds the cron-field requirement and clarifies that diff_mode/notify are 'stored preferences' rather than immediate actions, but doesn't disclose reversibility, auth needs, or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with Args/Returns sections and front-loaded purpose statement. The Returns section is somewhat filler since there's no output schema, but overall efficient and easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given four parameters at 0% schema coverage and no output schema, the description supplies the missing parameter semantics thoroughly. The main gap is lack of when-to-use guidance versus sibling pipeline tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the load. It documents all four parameters with meaning beyond the schema (cron field count and a concrete example, name = saved pipeline name, and the storage semantics of the two booleans). This compensates well for the undocumented schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (schedule) and resource (saved pipeline for periodic execution). The sibling unschedule_pipeline is the clear inverse, and this description correctly claims the scheduling side without conflating them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage (scheduling periodic execution) but never states when to use this versus save_pipeline or load_pipeline, nor any prerequisites like the pipeline already needing to exist. No exclusions or alternatives named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_biomedical_imagesARead-onlyIdempotent
🖼️ 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:
Translate the query to English medical terminology first
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: - "c": CT scan images - "g": Graphics / line art / diagrams - "m": MRI images - "mc": Microscopy / histology images - "p": PET scan images - "ph": Photographs / clinical photos - "u": Ultrasound images - "x": X-ray images Exclusion filters: - "xg": Exclude Graphics (removes graphic images from results) - "xm": Exclude Multipanel (removes multipanel images) - None: All types (default) collection: Filter by collection (Open-i only): - "pmc": PubMed Central articles - "mpx": MedPix clinical teaching images (high quality) - "cxr": Chest X-ray collection - "hmd": History of Medicine - "usc": USC collection - None: All collections (default) limit: Maximum number of images to return (default 10, max 50) sort_by: Sort results by (Open-i only): - "r": Relevance (default) - "d": Date (newest first) - "o": Oldest first - "t": Title - "e": Education relevance - "g": Graphics priority article_type: Filter by article type (Open-i only): - "cr": Case Report - "or": Original Research - "re": Review - "sr": Systematic Review - "ra": Research Article - "ed": Editorial - "lt": Letter - "bk": Book - and more... (see API docs) specialty: Filter by medical specialty (Open-i only): - "r": Radiology - "c": Cardiology - "ne": Neurology - "pu": Pulmonology - "d": Dermatology - "g": Gastroenterology - "or": Orthopedics - "o": Ophthalmology - "s": Surgery - "p": Pediatrics - "id": Infectious Disease - "i": Immunology - and more... (see API docs) license_type: Filter by Creative Commons license (Open-i only): - "by": CC-BY (Attribution) - "bync": CC-BY-NC (Attribution-NonCommercial) - "byncnd": CC-BY-NC-ND (Attribution-NonCommercial-NoDerivs) - "byncsa": CC-BY-NC-SA (Attribution-NonCommercial-ShareAlike) subset: Filter by subject subset (Open-i only): - "b": Behavioral Sciences - "c": Cancer - "e": Ethics - "s": Surgery - "x": Toxicology search_fields: Search in specific fields (Open-i only): - "t": Title only - "m": MeSH terms only - "ab": Abstract only - "msh": MeSH heading only - "c": Caption only - "a": Author only video_only: If True, only return video content (default False) hmp_type: History of Medicine publication type. Requires collection="hmd".
Returns: Formatted image results with URLs, captions, and article metadata
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| subset | No | ||
| sort_by | No | ||
| hmp_type | No | ||
| specialty | No | ||
| collection | No | ||
| image_type | No | ||
| video_only | No | ||
| article_type | No | ||
| license_type | No | ||
| search_fields | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context: the critical language requirement (Open-i only supports English), the built-in translation hints, and the fact that it returns formatted results with URLs and metadata. It doesn't contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections (CRITICAL, SOURCES, EXAMPLES, Args). The critical language requirement is front-loaded. The parameter documentation is repetitive with the schema enums, but the added explanations (e.g., 'x': X-ray images, 'mc': Microscopy) justify the length. Some decorative elements (box-drawing characters) add noise but don't harm readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 12-parameter tool with no output schema, the description is remarkably complete. It covers the source, the language constraint, all parameter semantics, example calls, and the return format. The only minor gap is that it doesn't describe pagination or error behavior, but the examples and parameter docs are sufficient for an agent to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden of explaining parameters. It does this thoroughly: every parameter (query, image_type, collection, limit, sort_by, article_type, specialty, license_type, subset, search_fields, video_only, hmp_type) is explained with its enum values and meaning. The examples show realistic usage patterns for each filter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool searches biomedical images from NLM Open-i and returns image URLs with metadata. It distinguishes itself from siblings like search_clinvar, get_article_figures, and unified_search by specifying the Open-i source and the exact output (image URLs with captions, article info, MeSH terms).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides extensive usage guidance: when to use it (searching biomedical images), explicit language requirements (translate non-English queries to English), and examples for various filter combinations. It also implicitly distinguishes from siblings by focusing on Open-i image search rather than article retrieval or gene/compound search.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_clinvarARead-onlyIdempotent
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
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld, and non-destructive, so safety is covered. The description adds the return shape ('JSON with variant records including significance and conditions'), which is useful since there is no output schema, but it discloses no rate limits, pagination, or scoping behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first line is well front-loaded, but the box-drawing banner section for USE CASES consumes vertical space without adding semantic content. The Args/Returns structure is efficient, but overall it is bulkier than needed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 2-parameter read tool with no output schema, the description covers purpose, accepted query forms, the limit bound, and the return content. It lacks pagination/ordering notes, but nothing critical to calling it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the load. It documents 'query' as accepting a gene name, variant, or disease condition (a real semantic addition the schema omits) and clarifies 'limit' as maximum results, compensating well for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: 'Search ClinVar for clinical variants.' The ClinVar domain distinguishes it from the many literature/gene/compound siblings, though it doesn't explicitly say how it differs from search_gene or search_compound.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The USE CASES block gives four concrete scenarios (clinical significance lookup, disease-associated variants, gene-disease associations, pathogenicity classification), which is clear context for when to reach for it. It offers no explicit exclusions or named sibling alternatives, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_compoundBRead-onlyIdempotent
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
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive, so the safety profile is covered. The description adds that results come back as 'JSON with compound records including names, formulas, properties' — useful since there is no output schema — but says nothing about rate limits or how PubChem misses are handled despite openWorldHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening sentence is correctly front-loaded and the content is short, but the boxed '═══' dividers and USE CASES/Args/Returns scaffolding consume lines without adding information — decoration rather than earned structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read-only search with no output schema, the description is adequate: it names the source, the use cases, the args, and the rough return shape. It stops short of explaining pagination, ranking, or the distinction from compound-detail siblings, leaving gaps for a tool with several close relatives.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the load: it labels query as 'Compound name or description' and limit as 'Maximum results (1-50)'. That compensates for both parameters, but shallowly — no format hints, examples, or handling of ambiguous names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource+source: 'Search PubChem for chemical compounds.' An agent immediately knows this queries PubChem. However, it does not distinguish itself from siblings get_compound_details and get_compound_literature, which are the obvious adjacent tools for compound lookups.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The USE CASES list implies when to reach for this tool (compound info, formulas, synonyms, properties), which is more than nothing. But it gives no when-NOT guidance and never mentions the alternatives (get_compound_details for a known compound, get_compound_literature for papers), so an agent must infer the routing itself.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_geneARead-onlyIdempotent
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
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| organism | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and non-destructive, so the safety profile is covered. Beyond that the description only adds the return shape; it says nothing about rate limits, result ordering, or relevance ranking for what is an open-world search.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with a one-line purpose, then scannable sections. The decorative separator lines and USE CASES header add formatting overhead but the content is tight and each bullet earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description appropriately summarizes the return (JSON with symbols, names, locations). All three parameters are covered and the use cases frame intent — a complete-enough definition for a simple three-param search.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does: it labels all three parameters and adds concrete value — organism examples ('human', 'Homo sapiens', 'mouse') and the limit range (1-50). Minor gap: it doesn't explain query matching mode (symbol vs. free-text function).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: search the NCBI Gene database for gene information. Sibling tools like get_gene_details and get_gene_literature exist, but the description never differentiates this lookup from them, so the agent must infer the split (search vs. fetch-details).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The USE CASES block gives clear situational context (look up function, aliases, chromosome location, find by name/function), which tells an agent when this tool applies. It stops short of naming an alternative or exclusion, so it's solid context without routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
test_institutional_accessARead-onlyIdempotent
Test your institutional link resolver configuration.
═══════════════════════════════════════════════════════════════════════════════ 🧪 TEST INSTITUTIONAL ACCESS ═══════════════════════════════════════════════════════════════════════════════
Tests if your configured link resolver is:
Properly configured
Reachable (network connection)
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:
Use "test_free" preset (EBSCO public resolver): configure_institutional_access(preset="test_free") test_institutional_access()
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
| Name | Required | Description | Default |
|---|---|---|---|
| pmid | No | 38353755 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover readOnly/idempotent/openWorld, but the description adds meaningful behavioral context: it clarifies that the test only verifies endpoint reachability, not full-text access, which is a critical limitation not expressed in annotations. Also documents the default pmid and expected return fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Heavily over-styled with ASCII dividers and duplicated headers (title repeats the name, banner box, repeated 'FREE TEST OPTIONS'). The core signal is buried under decorative formatting, wasting many tokens for a one-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, limitation note, test options, argument default, and return shape. For a simple read-only test tool this is largely sufficient, with minor room to be tighter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the single pmid parameter has no description in the schema; the description explains pmid is the PMID to use for testing with a default (38353755), adding needed meaning. Baseline for 1 param with low coverage is 3, and the added detail matches that.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (test) and resource (institutional link resolver configuration), and enumerates exactly what is being checked: configured, reachable, valid response. Clearly distinguishable from siblings like configure_institutional_access and diagnose_institutional_access.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear when-to-use context via the FREE TEST OPTIONS section explaining how to test without institutional access, and notes what the test does and does not verify. Slightly fewer explicit exclusions vs alternatives, but functional.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unified_searchA
🔍 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: ═══════════════════════════════════════════════════════════════════
Analyzes your query (complexity, intent, PICO elements)
Automatically selects best sources based on query type
Searches multiple sources in parallel
Deduplicates and merges results
Ranks by configurable criteria
Enriches with OA links (Unpaywall)
Auto-detects ICD-9/10 codes and expands to MeSH terms
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="systematic")
Full control: unified_search("propofol vs remimazolam", sources="pubmed,semantic_scholar,europe_pmc", ranking="impact", filters="year:2020-,sex:female,species:humans", options="preprints,no_relax")
ICD Code Auto-Detection: unified_search("E11 complications") → Auto-expands E11 to "Diabetes Mellitus, Type 2"[MeSH]
Args:
query: Search query (natural language, ICD codes, or structured).
Required unless pipeline is provided.
limit: Maximum results per source (default 10, max 100)
sources: Comma-separated list of sources to search.
Available: "pubmed", "openalex", "semantic_scholar",
"europe_pmc", "crossref", "core".
Commercial connectors may also appear when enabled via env,
e.g. "scopus" when SCOPUS_ENABLED=true and
SCOPUS_API_KEY are configured, or "web_of_science"
when WEB_OF_SCIENCE_ENABLED=true and
WEB_OF_SCIENCE_API_KEY are configured.
Default: auto-select based on query complexity.
Supports "auto" and "all" with exclusions.
Source keys are exact and canonical; legacy hyphenated,
spaced, abbreviated, or case-folded aliases are rejected.
Examples: "pubmed,openalex", "auto,-semantic_scholar",
or "all,-crossref"
Global disable env: PUBMED_SEARCH_DISABLED_SOURCES
Example: PUBMED_SEARCH_DISABLED_SOURCES=semantic_scholar,core
ranking: Ranking strategy:
- "balanced": Default, considers all factors
- "impact": Prioritize high-citation papers
- "recency": Prioritize recent publications
- "quality": Prioritize publication-type heuristics (RCTs, meta-analyses); not a quality assessment
output_format: "markdown" (human-readable), "json", or "toon" (programmatic)
filters: Comma-separated key:value pairs for filtering results.
Supported keys:
year:2020-2025 → publication year range
year:2020- → from 2020 onwards
year:-2025 → up to 2025
year:2024 → from 2024 onwards
age_group: → age group filter (PubMed).
Values: newborn, infant, preschool, child,
adolescent, young_adult, adult, middle_aged,
aged, aged_80
sex: → sex filter: male, female
species: → species filter: humans, animals
language: → language filter: english, chinese, etc.
clinical_query:
→ clinical query filter (PubMed EBM).
Values: therapy, therapy_narrow, diagnosis,
diagnosis_narrow, prognosis, prognosis_narrow,
etiology, etiology_narrow,
clinical_prediction, clinical_prediction_narrow
Tokens, keys, and values use exact canonical spelling with
no surrounding whitespace.
Example: "year:2020-2025,age_group:aged,sex:female,clinical_query:therapy"
options: Comma-separated flags to toggle behaviors.
Supported flags:
preprints → also search arXiv, medRxiv, bioRxiv
include_detected_preprints
→ retain records identified by the preprint
heuristic in otherwise selected sources;
this does not establish peer-review status
clinical_trials → add a bounded ClinicalTrials.gov adjunct
section to Markdown output (explicit opt-in)
no_oa → skip Unpaywall OA link enrichment
no_analysis → hide query analysis section in output
no_scores → hide ranking scores and rank percentiles
compact → compact structured JSON/TOON output
no_next → hide next-tool suggestions in structured output
no_provenance → hide section provenance in structured output
no_relax → disable auto-relaxation on 0 results
native_semantic → use provider-native semantic retrieval;
currently OpenAlex, max 50 results
systematic → use deterministic bulk/cursor retrieval where
supported (for example S2 and OpenAlex)
shallow → disable deep search (faster, keyword-only)
native_semantic and systematic are mutually exclusive
Option tokens use exact canonical spelling with no
surrounding whitespace.
and automatically disable multi-strategy query expansion.
Tokens use exact canonical spelling without surrounding
whitespace or duplicates.
Example: "preprints,shallow" or "no_analysis,no_scores"
pipeline: YAML/JSON string defining a multi-step search pipeline.
When provided, other parameters (except output_format) are
ignored and the pipeline DAG is executed instead.
Accepts **YAML** (recommended, human-friendly) or **JSON** format.
**Template mode — YAML** (shortcut for common workflows):
template: pico
template_params:
P: ICU patients
I: remimazolam
C: propofol
O: sedation
Other templates:
template: comprehensive
template_params:
query: CRISPR gene therapy
template: exploration
template_params:
pmid: "12345678"
template: gene_drug
template_params:
term: BRCA1
**Custom pipeline — YAML** (full DAG control, max 20 steps):
name: My Custom Search
steps:
- id: s1
action: search
params:
query: remimazolam ICU
sources: [pubmed, europe_pmc]
limit: 50
- id: s2
action: search
params:
query: propofol ICU
sources: [pubmed]
limit: 50
- id: merged
action: merge
inputs: [s1, s2]
params:
method: rrf
- id: enriched
action: metrics
inputs: [merged]
output:
format: markdown
limit: 20
ranking: impact
Shared params:
globals: default params inherited only by actions that
declare the same canonical parameter key
variables: typed values available as ${name} placeholders;
embedded replacements must be strings
Debugging controls:
dry_run: validate/preview the pipeline without searches
stop_at: execute through one step id, e.g. "merged"
**JSON also supported** (for programmatic use):
{"template": "pico", "template_params": {"P": "ICU patients", "I": "remimazolam"}}
Available actions:
search — literature search (params: query, sources, limit, min_year, max_year)
pico — PICO elements (params: P, I, C, O)
expand — MeSH/synonym expansion (params: topic)
details — fetch article details (params: pmids)
related — find related articles (params: pmid, limit)
citing — find citing articles (params: pmid, limit)
references — get article references (params: pmid, limit)
metrics — enrich with iCite citation metrics (inputs only)
merge — combine results (params: method=union|intersection|rrf)
filter — post-filter (params: min_year, max_year, article_types, min_citations, has_abstract)Returns: Formatted search results with: - Query analysis (complexity, intent, PICO) - ICD code expansions (if detected) - Search statistics (sources, dedup count) - Ranked articles with metadata - Open access links where available - Preprints (if options includes "preprints") - Relaxation info (if auto_relax triggered) - Pipeline step summary (if pipeline mode)
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | No | ||
| dry_run | No | ||
| filters | No | ||
| options | No | ||
| ranking | No | balanced | |
| sources | No | ||
| stop_at | No | ||
| pipeline | No | ||
| output_format | No | markdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavioral detail beyond the annotations: automatic source selection, auto-relaxation on zero results, shallow vs. deep search, deduplication, ICD/MeSH expansion, Unpaywall enrichment, source alias rejection, global env-based source disabling, and pipeline dry_run/stop_at semantics. This is far richer than the sparse annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with headers, a 'WHAT IT DOES' list, examples, and per-parameter explanations, and it is front-loaded with the core purpose. However, it is very long and contains redundancy, especially in the options section where the 'exact canonical spelling' warning appears twice and one sentence is grammatically broken ('and automatically disable multi-strategy query expansion').
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter tool with no output schema, the description is exceptionally complete: it covers return content, source availability, environment-based configuration, pipeline actions, templates, debugging controls, and edge-case behaviors such as auto-relaxation and preprint detection. An agent has enough information to call the tool correctly across simple and complex scenarios.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden, and it succeeds. Every parameter (query, limit, sources, ranking, output_format, filters, options, pipeline, dry_run, stop_at) is explained with defaults, valid values, examples, and behavioral effects, including canonical token spelling requirements and mutually exclusive options.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool is a 'Single entry point for multi-source academic search' that analyzes queries and searches multiple sources, with a concrete list of behaviors (deduplicates, merges, ranks, enriches with OA links, detects ICD codes). It does not explicitly name sibling tools or state how it differs from them, so it stops short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: it is the unified search entry point, and users do not need to choose between PubMed, OpenAlex, CrossRef, etc. Numerous examples show when to use basic, filtered, preprint, systematic, and pipeline modes, but it does not explicitly state when to prefer sibling tools like fetch_article_details or analyze_search_query.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unschedule_pipelineADestructiveIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false. The description adds one useful behavioral detail beyond that: the response is removed schedule metadata, or an MCP error when no schedule exists (consistent with idempotentHint). It does not state auth/permission needs or whether other schedule config is affected.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action, followed by concise Args/Returns sections. No filler; the one-line summary plus parameter and return notes earn their place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter mutation with no output schema, the description covers the action, the parameter's meaning, and the return/error behavior, while annotations cover the safety profile. Only permission requirements and interaction with other schedule state are unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the schema's 'name' property carries no prose. The description compensates by clarifying the parameter means the 'Saved pipeline name whose schedule will be removed,' disambiguating it from a schedule ID or arbitrary string.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb+resource: 'Remove the active schedule for a saved pipeline.' It is clearly distinct from delete_pipeline (removes the pipeline) and schedule_pipeline (adds a schedule), though it does not name those siblings explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the verb and the pipeline-scheduling sibling set, but the description never states when to use this versus schedule_pipeline, delete_pipeline, or what state the pipeline must be in. No alternatives or exclusions are offered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_pico_planBRead-onlyIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| c | No | ||
| i | No | ||
| o | No | ||
| p | No | ||
| limit | No | ||
| c_query | No | ||
| i_query | No | ||
| o_query | No | ||
| p_query | No | ||
| profile | No | balanced | |
| sources | No | ||
| description | No | ||
| question_type | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, so the safety profile is covered; the description adds non-obvious behavior: malformed enum/source values fail rather than being silently replaced, and question_type is inferred by the service when omitted. It does not say what the returned pipeline looks like, but the strictness and inference notes are valuable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Short and front-loaded: the purpose sentence comes first, followed by two focused behavioral clarifications. No filler, though the second paragraph shifts abruptly to schema details that belong closer to the parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Adequate for the strictness behavior it chooses to highlight, but incomplete for a 13-parameter, no-required, no-output-schema tool: the central P/I/C/O vs *_query contract and the meaning of the returned 'runnable pipeline' are left to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across 13 parameters, so the description carries the full burden yet only clarifies three (question_type, profile, sources). It never explains the difference between p/i/c/o free-text fields and the p_query/i_query/o_query variants, nor limit or description, leaving the most ambiguous pairing undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: validate agent-provided P/I/C/O and return a runnable PICO pipeline. An agent can tell it is a validation/production step rather than a search step, though it never names the siblings it is distinct from.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use or when-not-to-use guidance, and no mention of alternatives such as generate_search_queries or analyze_search_query which occupy adjacent territory. Usage is only inferable from the phrase 'agent-provided P/I/C/O'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_reference_listARead-onlyIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| source_name | No | ||
| max_references | No | ||
| reference_text | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the read-only, idempotent, open-world safety profile, so the bar is lower. The description adds real behavioral context beyond that: resolution mechanisms (PMID/DOI/ECitMatch), that inputs above max_references are rejected rather than truncated, that source_unavailable/not_checked rows are emitted, and the human-in-the-loop review workflow for partial/unresolved rows.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The Args and Returns sections are well-organized and front-loaded, but the 'First version scope' / 'Second version scope' roadmap paragraphs consume substantial space and do not help an agent invoke the tool correctly. The version meta-commentary is the main structural weakness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, but the Returns section describes the JSON verification report and its status values, and all three parameters are documented with limits. Behavioral and parameter context is sufficient for correct invocation, with only the absent when-to-use guidance leaving a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning, and it does: it documents reference_text formatting and size limits, source_name as an optional reporting label with its own limit, and max_references as a hard limit (1-200) with reject-not-truncate semantics. Only minor gap is that these limits echo the schema constraints without adding syntax guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence gives a specific verb and resource: 'Verify a plain-text reference list against PubMed evidence.' This distinguishes it from siblings like get_article_references (which fetches an article's own references) by making 'verification' the core action. The version-scope framing is odd but the core purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains what the tool does and its input format, but never states when to choose it over alternatives or when not to. It contrasts 'First version scope' vs 'Second version scope' rather than contrasting this tool against sibling tools like get_article_references or unified_search, leaving routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.7.3- Changed
fetch_article_details1 field changed- changed
Input schema / properties / output_format / enumPrevious value: -[ - "markdown", - "json" -]New value: +[ + "markdown", + "json", + "toon" +]
51 tool updates
v0.7.2- Removed
analyze_figure_for_search - Changed
analyze_search_query4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / query / maxLengthAdded value: +4096 - added
Input schema / properties / query / minLengthAdded value: +1 - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "analyze_search_queryOutput", - "type": "object" -}New value: +null
- Removed
analyze_timeline_milestones - Changed
build_citation_tree17 fields changed- added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / depth / anyOfRemoved value: -[ - { - "type": "integer" - }, - { - "type": "string" - } -] - added
Input schema / properties / depth / maximumAdded value: +3 - added
Input schema / properties / depth / minimumAdded value: +1 - added
Input schema / properties / depth / typeAdded value: +"integer" - added
Input schema / properties / direction / enumAdded value: +[ + "forward", + "backward", + "both" +] - removed
Input schema / properties / include_detailsRemoved value: -{ - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "string" - } - ], - "default": true, - "title": "Include Details" -} - removed
Input schema / properties / limit_per_level / anyOfRemoved value: -[ - { - "type": "integer" - }, - { - "type": "string" - } -] - added
Input schema / properties / limit_per_level / maximumAdded value: +20 - added
Input schema / properties / limit_per_level / minimumAdded value: +1 - added
Input schema / properties / limit_per_level / typeAdded value: +"integer" - added
Input schema / properties / output_format / enumAdded value: +[ + "cytoscape", + "g6", + "d3", + "vis", + "graphml", + "mermaid" +] - removed
Input schema / properties / pmid / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "integer" - } -] - added
Input schema / properties / pmid / maxLengthAdded value: +512 - added
Input schema / properties / pmid / minLengthAdded value: +1 - added
Input schema / properties / pmid / typeAdded value: +"string" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "build_citation_treeOutput", - "type": "object" -}New value: +null
- Added
build_research_chronicle - Removed
build_research_timeline - Removed
compare_timelines - Changed
configure_institutional_access5 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / preset / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "ntu", + "ncku", + "nthu", + "nycu", + "harvard", + "stanford", + "mit", + "yale", + "oxford", + "cambridge", + "sfx", + "360link", + "primo", + "test_free" + ], + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / properties / resolver_url / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 8192, + "type": "string" + }, + { + "type": "null" + } +] - removed
Input schema / properties / testRemoved value: -{ - "default": true, - "title": "Test", - "type": "boolean" -} - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "configure_institutional_accessOutput", - "type": "object" -}New value: +null
- Changed
convert_icd_mesh7 fields changed- added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / codeRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Code" -} - added
Input schema / properties / directionAdded value: +{ + "enum": [ + "icd_to_mesh", + "mesh_to_icd" + ], + "title": "Direction", + "type": "string" +} - removed
Input schema / properties / mesh_termRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Mesh Term" -} - added
Input schema / properties / valueAdded value: +{ + "maxLength": 500, + "minLength": 1, + "title": "Value", + "type": "string" +} - added
Input schema / requiredAdded value: +[ + "direction", + "value" +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "convert_icd_meshOutput", - "type": "object" -}New value: +null
- Changed
delete_pipeline5 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / name / maxLengthAdded value: +64 - added
Input schema / properties / name / minLengthAdded value: +1 - added
Input schema / properties / name / patternAdded value: +"^[a-z0-9](?:[a-z0-9_-]{0,63})$" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "delete_pipelineOutput", - "type": "object" -}New value: +null
- Changed
diagnose_institutional_access7 fields changed- added
Input schema / $defsAdded value: +{ + "DOISource": { + "additionalProperties": false, + "description": "An explicit DOI.", + "properties": { + "kind": { + "const": "doi", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 512, + "minLength": 7, + "pattern": "^10\\.[0-9]{4,9}/", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "DOISource", + "type": "object" + }, + "PMIDSource": { + "additionalProperties": false, + "description": "An explicit PubMed identifier.", + "properties": { + "kind": { + "const": "pmid", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 20, + "pattern": "^[1-9][0-9]{0,19}$", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "PMIDSource", + "type": "object" + } +} - added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / doiRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Doi" -} - removed
Input schema / properties / pmidRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Pmid" -} - added
Input schema / properties / sourceAdded value: +{ + "discriminator": { + "mapping": { + "doi": "#/$defs/DOISource", + "pmid": "#/$defs/PMIDSource" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/$defs/PMIDSource" + }, + { + "$ref": "#/$defs/DOISource" + } + ], + "title": "Source" +} - added
Input schema / requiredAdded value: +[ + "source" +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "diagnose_institutional_accessOutput", - "type": "object" -}New value: +null
- Changed
fetch_article_details3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / pmids / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "integer" - } -]New value: +[ + { + "maxLength": 100000, + "minLength": 1, + "type": "string" + }, + { + "items": { + "maxLength": 512, + "minLength": 1, + "type": "string" + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + } +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "fetch_article_detailsOutput", - "type": "object" -}New value: +null
- Changed
find_citing_articles8 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / limit / maximumAdded value: +100 - added
Input schema / properties / limit / minimumAdded value: +1 - removed
Input schema / properties / pmid / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "integer" - } -] - added
Input schema / properties / pmid / maxLengthAdded value: +512 - added
Input schema / properties / pmid / minLengthAdded value: +1 - added
Input schema / properties / pmid / typeAdded value: +"string" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "find_citing_articlesOutput", - "type": "object" -}New value: +null
- Changed
find_related_articles8 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / limit / maximumAdded value: +50 - added
Input schema / properties / limit / minimumAdded value: +1 - removed
Input schema / properties / pmid / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "integer" - } -] - added
Input schema / properties / pmid / maxLengthAdded value: +512 - added
Input schema / properties / pmid / minLengthAdded value: +1 - added
Input schema / properties / pmid / typeAdded value: +"string" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "find_related_articlesOutput", - "type": "object" -}New value: +null
- Changed
generate_search_queries9 fields changed- added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / check_spelling / anyOfRemoved value: -[ - { - "type": "boolean" - }, - { - "type": "string" - } -] - added
Input schema / properties / check_spelling / typeAdded value: +"boolean" - removed
Input schema / properties / include_suggestions / anyOfRemoved value: -[ - { - "type": "boolean" - }, - { - "type": "string" - } -] - added
Input schema / properties / include_suggestions / typeAdded value: +"boolean" - added
Input schema / properties / strategy / enumAdded value: +[ + "comprehensive", + "focused", + "exploratory" +] - added
Input schema / properties / topic / maxLengthAdded value: +2000 - added
Input schema / properties / topic / minLengthAdded value: +1 - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "generate_search_queriesOutput", - "type": "object" -}New value: +null
- Changed
get_article_figures8 fields changed- added
Input schema / $defsAdded value: +{ + "PMCIDSource": { + "additionalProperties": false, + "description": "An explicit PubMed Central identifier.", + "properties": { + "kind": { + "const": "pmcid", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 23, + "pattern": "^PMC[1-9][0-9]{0,19}$", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "PMCIDSource", + "type": "object" + }, + "PMIDSource": { + "additionalProperties": false, + "description": "An explicit PubMed identifier.", + "properties": { + "kind": { + "const": "pmid", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 20, + "pattern": "^[1-9][0-9]{0,19}$", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "PMIDSource", + "type": "object" + } +} - added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / identifierRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Identifier" -} - removed
Input schema / properties / pmcidRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Pmcid" -} - removed
Input schema / properties / pmidRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Pmid" -} - added
Input schema / properties / sourceAdded value: +{ + "discriminator": { + "mapping": { + "pmcid": "#/$defs/PMCIDSource", + "pmid": "#/$defs/PMIDSource" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/$defs/PMIDSource" + }, + { + "$ref": "#/$defs/PMCIDSource" + } + ], + "title": "Source" +} - added
Input schema / requiredAdded value: +[ + "source" +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "get_article_figuresOutput", - "type": "object" -}New value: +null
- Changed
get_article_references8 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / limit / maximumAdded value: +100 - added
Input schema / properties / limit / minimumAdded value: +1 - removed
Input schema / properties / pmid / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "integer" - } -] - added
Input schema / properties / pmid / maxLengthAdded value: +512 - added
Input schema / properties / pmid / minLengthAdded value: +1 - added
Input schema / properties / pmid / typeAdded value: +"string" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "get_article_referencesOutput", - "type": "object" -}New value: +null
- Removed
get_cached_article - Changed
get_citation_metrics7 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / min_citations / anyOfPrevious value: -[ - { - "type": "integer" - }, - { - "type": "null" - } -]New value: +[ + { + "maximum": 2000000000, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } +] - changed
Input schema / properties / min_percentile / anyOfPrevious value: -[ - { - "type": "number" - }, - { - "type": "null" - } -]New value: +[ + { + "maximum": 100, + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } +] - changed
Input schema / properties / min_rcr / anyOfPrevious value: -[ - { - "type": "number" - }, - { - "type": "null" - } -]New value: +[ + { + "maximum": 1000000, + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } +] - changed
Input schema / properties / pmids / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "integer" - } -]New value: +[ + { + "maxLength": 100000, + "minLength": 1, + "type": "string" + }, + { + "items": { + "maxLength": 512, + "minLength": 1, + "type": "string" + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + } +] - added
Input schema / properties / sort_by / enumAdded value: +[ + "citation_count", + "relative_citation_ratio", + "nih_percentile", + "citations_per_year" +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "get_citation_metricsOutput", - "type": "object" -}New value: +null
- Changed
get_compound_details7 fields changed- added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / cid / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "integer" - } -] - added
Input schema / properties / cid / maxLengthAdded value: +20 - added
Input schema / properties / cid / minLengthAdded value: +1 - added
Input schema / properties / cid / patternAdded value: +"^[1-9][0-9]{0,19}$" - added
Input schema / properties / cid / typeAdded value: +"string" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "get_compound_detailsOutput", - "type": "object" -}New value: +null
- Changed
get_compound_literature11 fields changed- added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / cid / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "integer" - } -] - added
Input schema / properties / cid / maxLengthAdded value: +20 - added
Input schema / properties / cid / minLengthAdded value: +1 - added
Input schema / properties / cid / patternAdded value: +"^[1-9][0-9]{0,19}$" - added
Input schema / properties / cid / typeAdded value: +"string" - removed
Input schema / properties / limit / anyOfRemoved value: -[ - { - "type": "integer" - }, - { - "type": "string" - } -] - added
Input schema / properties / limit / maximumAdded value: +100 - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / limit / typeAdded value: +"integer" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "get_compound_literatureOutput", - "type": "object" -}New value: +null
- Changed
get_fulltext10 fields changed- added
Input schema / $defsAdded value: +{ + "DOISource": { + "additionalProperties": false, + "description": "An explicit DOI.", + "properties": { + "kind": { + "const": "doi", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 512, + "minLength": 7, + "pattern": "^10\\.[0-9]{4,9}/", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "DOISource", + "type": "object" + }, + "PMCIDSource": { + "additionalProperties": false, + "description": "An explicit PubMed Central identifier.", + "properties": { + "kind": { + "const": "pmcid", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 23, + "pattern": "^PMC[1-9][0-9]{0,19}$", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "PMCIDSource", + "type": "object" + }, + "PMIDSource": { + "additionalProperties": false, + "description": "An explicit PubMed identifier.", + "properties": { + "kind": { + "const": "pmid", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 20, + "pattern": "^[1-9][0-9]{0,19}$", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "PMIDSource", + "type": "object" + } +} - added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / doiRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Doi" -} - removed
Input schema / properties / identifierRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Identifier" -} - removed
Input schema / properties / pmcidRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Pmcid" -} - removed
Input schema / properties / pmidRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Pmid" -} - changed
Input schema / properties / sections / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / sourceAdded value: +{ + "discriminator": { + "mapping": { + "doi": "#/$defs/DOISource", + "pmcid": "#/$defs/PMCIDSource", + "pmid": "#/$defs/PMIDSource" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/$defs/PMIDSource" + }, + { + "$ref": "#/$defs/PMCIDSource" + }, + { + "$ref": "#/$defs/DOISource" + } + ], + "title": "Source" +} - added
Input schema / requiredAdded value: +[ + "source" +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "get_fulltextOutput", - "type": "object" -}New value: +null
- Changed
get_gene_details7 fields changed- added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / gene_id / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "integer" - } -] - added
Input schema / properties / gene_id / maxLengthAdded value: +20 - added
Input schema / properties / gene_id / minLengthAdded value: +1 - added
Input schema / properties / gene_id / patternAdded value: +"^[1-9][0-9]{0,19}$" - added
Input schema / properties / gene_id / typeAdded value: +"string" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "get_gene_detailsOutput", - "type": "object" -}New value: +null
- Changed
get_gene_literature11 fields changed- added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / gene_id / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "integer" - } -] - added
Input schema / properties / gene_id / maxLengthAdded value: +20 - added
Input schema / properties / gene_id / minLengthAdded value: +1 - added
Input schema / properties / gene_id / patternAdded value: +"^[1-9][0-9]{0,19}$" - added
Input schema / properties / gene_id / typeAdded value: +"string" - removed
Input schema / properties / limit / anyOfRemoved value: -[ - { - "type": "integer" - }, - { - "type": "string" - } -] - added
Input schema / properties / limit / maximumAdded value: +100 - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / limit / typeAdded value: +"integer" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "get_gene_literatureOutput", - "type": "object" -}New value: +null
- Changed
get_institutional_link13 fields changed- added
Input schema / $defsAdded value: +{ + "DOISource": { + "additionalProperties": false, + "description": "An explicit DOI.", + "properties": { + "kind": { + "const": "doi", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 512, + "minLength": 7, + "pattern": "^10\\.[0-9]{4,9}/", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "DOISource", + "type": "object" + }, + "InstitutionalMetadataSource": { + "additionalProperties": false, + "description": "Bounded journal metadata used to construct an OpenURL.", + "properties": { + "issue": { + "anyOf": [ + { + "maxLength": 50, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Issue" + }, + "journal": { + "anyOf": [ + { + "maxLength": 300, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Journal" + }, + "kind": { + "const": "metadata", + "title": "Kind", + "type": "string" + }, + "pages": { + "anyOf": [ + { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pages" + }, + "title": { + "maxLength": 1000, + "minLength": 1, + "title": "Title", + "type": "string" + }, + "volume": { + "anyOf": [ + { + "maxLength": 50, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Volume" + }, + "year": { + "anyOf": [ + { + "maximum": 9999, + "minimum": 1000, + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Year" + } + }, + "required": [ + "kind", + "title" + ], + "title": "InstitutionalMetadataSource", + "type": "object" + }, + "PMIDSource": { + "additionalProperties": false, + "description": "An explicit PubMed identifier.", + "properties": { + "kind": { + "const": "pmid", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 20, + "pattern": "^[1-9][0-9]{0,19}$", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "PMIDSource", + "type": "object" + } +} - added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / doiRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Doi" -} - removed
Input schema / properties / issueRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Issue" -} - removed
Input schema / properties / journalRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Journal" -} - removed
Input schema / properties / pagesRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Pages" -} - removed
Input schema / properties / pmidRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Pmid" -} - added
Input schema / properties / sourceAdded value: +{ + "discriminator": { + "mapping": { + "doi": "#/$defs/DOISource", + "metadata": "#/$defs/InstitutionalMetadataSource", + "pmid": "#/$defs/PMIDSource" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/$defs/PMIDSource" + }, + { + "$ref": "#/$defs/DOISource" + }, + { + "$ref": "#/$defs/InstitutionalMetadataSource" + } + ], + "title": "Source" +} - removed
Input schema / properties / titleRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Title" -} - removed
Input schema / properties / volumeRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Volume" -} - removed
Input schema / properties / yearRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Year" -} - added
Input schema / requiredAdded value: +[ + "source" +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "get_institutional_linkOutput", - "type": "object" -}New value: +null
- Changed
get_pipeline_history7 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / limit / maximumAdded value: +100 - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / name / maxLengthAdded value: +64 - added
Input schema / properties / name / minLengthAdded value: +1 - added
Input schema / properties / name / patternAdded value: +"^[a-z0-9](?:[a-z0-9_-]{0,63})$" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "get_pipeline_historyOutput", - "type": "object" -}New value: +null
- Removed
get_session_log - Removed
get_session_pmids - Removed
get_session_summary - Changed
get_text_mined_terms8 fields changed- added
Input schema / $defsAdded value: +{ + "PMCIDSource": { + "additionalProperties": false, + "description": "An explicit PubMed Central identifier.", + "properties": { + "kind": { + "const": "pmcid", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 23, + "pattern": "^PMC[1-9][0-9]{0,19}$", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "PMCIDSource", + "type": "object" + }, + "PMIDSource": { + "additionalProperties": false, + "description": "An explicit PubMed identifier.", + "properties": { + "kind": { + "const": "pmid", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 20, + "pattern": "^[1-9][0-9]{0,19}$", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "PMIDSource", + "type": "object" + } +} - added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / pmcidRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Pmcid" -} - removed
Input schema / properties / pmidRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Pmid" -} - changed
Input schema / properties / semantic_type / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "GENE_PROTEIN", + "DISEASE", + "CHEMICAL", + "ORGANISM", + "GO_TERM", + "EFO" + ], + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / sourceAdded value: +{ + "discriminator": { + "mapping": { + "pmcid": "#/$defs/PMCIDSource", + "pmid": "#/$defs/PMIDSource" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/$defs/PMIDSource" + }, + { + "$ref": "#/$defs/PMCIDSource" + } + ], + "title": "Source" +} - added
Input schema / requiredAdded value: +[ + "source" +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "get_text_mined_termsOutput", - "type": "object" -}New value: +null
- Changed
list_pipelines4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / scope / enumAdded value: +[ + "", + "workspace", + "global" +] - added
Input schema / properties / tag / maxLengthAdded value: +100 - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "list_pipelinesOutput", - "type": "object" -}New value: +null
- Changed
list_resolver_presets2 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "list_resolver_presetsOutput", - "type": "object" -}New value: +null
- Changed
load_pipeline4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / source / maxLengthAdded value: +4096 - added
Input schema / properties / source / minLengthAdded value: +1 - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "load_pipelineOutput", - "type": "object" -}New value: +null
- Removed
manage_pipeline - Removed
parse_pico - Changed
prepare_export5 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / format / enumAdded value: +[ + "ris", + "medline", + "csl", + "bibtex", + "csv", + "json" +] - changed
Input schema / properties / pmids / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "integer" - } -]New value: +[ + { + "maxLength": 100000, + "minLength": 1, + "type": "string" + }, + { + "items": { + "maxLength": 512, + "minLength": 1, + "type": "string" + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + } +] - added
Input schema / properties / source / enumAdded value: +[ + "official", + "local" +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "prepare_exportOutput", - "type": "object" -}New value: +null
- Added
prepare_figure_search - Added
read_research_chronicle - Changed
read_session21 fields changed- added
Input schema / $defsAdded value: +{ + "ArtifactIdLocator": { + "additionalProperties": false, + "properties": { + "kind": { + "const": "artifact_id", + "title": "Kind", + "type": "string" + }, + "session_id": { + "anyOf": [ + { + "maxLength": 80, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,79}$", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "value": { + "maxLength": 512, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,511}$", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "ArtifactIdLocator", + "type": "object" + }, + "ArtifactUriLocator": { + "additionalProperties": false, + "properties": { + "kind": { + "const": "artifact_uri", + "title": "Kind", + "type": "string" + }, + "value": { + "maxLength": 605, + "minLength": 13, + "pattern": "^artifact://[A-Za-z0-9][A-Za-z0-9_.-]{0,79}/[A-Za-z0-9][A-Za-z0-9_.-]{0,511}$", + "title": "Value", + "type": "string" + } + }, + "required": [ + "kind", + "value" + ], + "title": "ArtifactUriLocator", + "type": "object" + }, + "SessionArticleRequest": { + "additionalProperties": false, + "properties": { + "action": { + "const": "article", + "title": "Action", + "type": "string" + }, + "pmid": { + "maxLength": 20, + "pattern": "^[1-9][0-9]{0,19}$", + "title": "Pmid", + "type": "string" + } + }, + "required": [ + "action", + "pmid" + ], + "title": "SessionArticleRequest", + "type": "object" + }, + "SessionArtifactRequest": { + "additionalProperties": false, + "properties": { + "action": { + "const": "artifact", + "title": "Action", + "type": "string" + }, + "artifact_file": { + "anyOf": [ + { + "maxLength": 512, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,511}$", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Artifact File" + }, + "include_local_paths": { + "default": false, + "title": "Include Local Paths", + "type": "boolean" + }, + "locator": { + "discriminator": { + "mapping": { + "artifact_id": "#/$defs/ArtifactIdLocator", + "artifact_uri": "#/$defs/ArtifactUriLocator" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/$defs/ArtifactIdLocator" + }, + { + "$ref": "#/$defs/ArtifactUriLocator" + } + ], + "title": "Locator" + }, + "max_chars": { + "default": 200000, + "maximum": 200000, + "minimum": 1, + "title": "Max Chars", + "type": "integer" + }, + "offset": { + "default": 0, + "maximum": 2000000000, + "minimum": 0, + "title": "Offset", + "type": "integer" + } + }, + "required": [ + "action", + "locator" + ], + "title": "SessionArtifactRequest", + "type": "object" + }, + "SessionListArtifactsRequest": { + "additionalProperties": false, + "properties": { + "action": { + "const": "list_artifacts", + "title": "Action", + "type": "string" + }, + "include_local_paths": { + "default": false, + "title": "Include Local Paths", + "type": "boolean" + }, + "kind": { + "anyOf": [ + { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Kind" + }, + "limit": { + "default": 10, + "maximum": 100, + "minimum": 1, + "title": "Limit", + "type": "integer" + }, + "session_id": { + "anyOf": [ + { + "maxLength": 80, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,79}$", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "tool": { + "anyOf": [ + { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool" + } + }, + "required": [ + "action" + ], + "title": "SessionListArtifactsRequest", + "type": "object" + }, + "SessionLogRequest": { + "additionalProperties": false, + "properties": { + "action": { + "const": "log", + "title": "Action", + "type": "string" + }, + "event_limit": { + "default": 50, + "maximum": 500, + "minimum": 1, + "title": "Event Limit", + "type": "integer" + }, + "history_limit": { + "default": 10, + "maximum": 100, + "minimum": 1, + "title": "History Limit", + "type": "integer" + }, + "include_history": { + "default": true, + "title": "Include History", + "type": "boolean" + }, + "kind": { + "anyOf": [ + { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Kind" + } + }, + "required": [ + "action" + ], + "title": "SessionLogRequest", + "type": "object" + }, + "SessionPmidsRequest": { + "additionalProperties": false, + "properties": { + "action": { + "const": "pmids", + "title": "Action", + "type": "string" + }, + "query_filter": { + "anyOf": [ + { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Query Filter" + }, + "search_index": { + "default": -1, + "maximum": 100000, + "minimum": -100000, + "title": "Search Index", + "type": "integer" + } + }, + "required": [ + "action" + ], + "title": "SessionPmidsRequest", + "type": "object" + }, + "SessionReplaySearchRequest": { + "additionalProperties": false, + "properties": { + "action": { + "const": "replay_search", + "title": "Action", + "type": "string" + }, + "run_id": { + "maxLength": 512, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,511}$", + "title": "Run Id", + "type": "string" + }, + "session_id": { + "anyOf": [ + { + "maxLength": 80, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,79}$", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + } + }, + "required": [ + "action", + "run_id" + ], + "title": "SessionReplaySearchRequest", + "type": "object" + }, + "SessionSearchRunRequest": { + "additionalProperties": false, + "properties": { + "action": { + "const": "search_run", + "title": "Action", + "type": "string" + }, + "run_id": { + "maxLength": 512, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,511}$", + "title": "Run Id", + "type": "string" + }, + "session_id": { + "anyOf": [ + { + "maxLength": 80, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,79}$", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + } + }, + "required": [ + "action", + "run_id" + ], + "title": "SessionSearchRunRequest", + "type": "object" + }, + "SessionSearchRunsRequest": { + "additionalProperties": false, + "properties": { + "action": { + "const": "search_runs", + "title": "Action", + "type": "string" + }, + "limit": { + "default": 10, + "maximum": 100, + "minimum": 1, + "title": "Limit", + "type": "integer" + }, + "session_id": { + "anyOf": [ + { + "maxLength": 80, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,79}$", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "status": { + "anyOf": [ + { + "enum": [ + "started", + "planned", + "running", + "completed", + "partial", + "failed", + "cancelled", + "interrupted" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + } + }, + "required": [ + "action" + ], + "title": "SessionSearchRunsRequest", + "type": "object" + }, + "SessionSummaryRequest": { + "additionalProperties": false, + "properties": { + "action": { + "const": "summary", + "title": "Action", + "type": "string" + }, + "history_limit": { + "default": 10, + "maximum": 100, + "minimum": 1, + "title": "History Limit", + "type": "integer" + }, + "include_history": { + "default": false, + "title": "Include History", + "type": "boolean" + } + }, + "required": [ + "action" + ], + "title": "SessionSummaryRequest", + "type": "object" + } +} - added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / actionRemoved value: -{ - "default": "summary", - "title": "Action", - "type": "string" -} - removed
Input schema / properties / artifact_fileRemoved value: -{ - "default": "", - "title": "Artifact File", - "type": "string" -} - removed
Input schema / properties / artifact_idRemoved value: -{ - "default": "", - "title": "Artifact Id", - "type": "string" -} - removed
Input schema / properties / artifact_kindRemoved value: -{ - "default": "", - "title": "Artifact Kind", - "type": "string" -} - removed
Input schema / properties / artifact_toolRemoved value: -{ - "default": "", - "title": "Artifact Tool", - "type": "string" -} - removed
Input schema / properties / artifact_uriRemoved value: -{ - "default": "", - "title": "Artifact Uri", - "type": "string" -} - removed
Input schema / properties / event_limitRemoved value: -{ - "default": 50, - "title": "Event Limit", - "type": "integer" -} - removed
Input schema / properties / history_limitRemoved value: -{ - "default": 10, - "title": "History Limit", - "type": "integer" -} - removed
Input schema / properties / include_historyRemoved value: -{ - "default": false, - "title": "Include History", - "type": "boolean" -} - removed
Input schema / properties / include_local_pathsRemoved value: -{ - "default": false, - "title": "Include Local Paths", - "type": "boolean" -} - removed
Input schema / properties / max_charsRemoved value: -{ - "default": 200000, - "title": "Max Chars", - "type": "integer" -} - removed
Input schema / properties / offsetRemoved value: -{ - "default": 0, - "title": "Offset", - "type": "integer" -} - removed
Input schema / properties / pmidRemoved value: -{ - "default": "", - "title": "Pmid", - "type": "string" -} - removed
Input schema / properties / query_filterRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Query Filter" -} - added
Input schema / properties / requestAdded value: +{ + "discriminator": { + "mapping": { + "article": "#/$defs/SessionArticleRequest", + "artifact": "#/$defs/SessionArtifactRequest", + "list_artifacts": "#/$defs/SessionListArtifactsRequest", + "log": "#/$defs/SessionLogRequest", + "pmids": "#/$defs/SessionPmidsRequest", + "replay_search": "#/$defs/SessionReplaySearchRequest", + "search_run": "#/$defs/SessionSearchRunRequest", + "search_runs": "#/$defs/SessionSearchRunsRequest", + "summary": "#/$defs/SessionSummaryRequest" + }, + "propertyName": "action" + }, + "oneOf": [ + { + "$ref": "#/$defs/SessionPmidsRequest" + }, + { + "$ref": "#/$defs/SessionArticleRequest" + }, + { + "$ref": "#/$defs/SessionSummaryRequest" + }, + { + "$ref": "#/$defs/SessionLogRequest" + }, + { + "$ref": "#/$defs/SessionListArtifactsRequest" + }, + { + "$ref": "#/$defs/SessionArtifactRequest" + }, + { + "$ref": "#/$defs/SessionSearchRunsRequest" + }, + { + "$ref": "#/$defs/SessionSearchRunRequest" + }, + { + "$ref": "#/$defs/SessionReplaySearchRequest" + } + ], + "title": "Request" +} - removed
Input schema / properties / search_indexRemoved value: -{ - "default": -1, - "title": "Search Index", - "type": "integer" -} - removed
Input schema / properties / session_idRemoved value: -{ - "default": "", - "title": "Session Id", - "type": "string" -} - added
Input schema / requiredAdded value: +[ + "request" +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "read_sessionOutput", - "type": "object" -}New value: +null
- Changed
save_literature_notes7 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / collection_name / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / note_format / enumAdded value: +[ + "wiki", + "foam", + "markdown", + "medpaper" +] - changed
Input schema / properties / output_dir / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / properties / pmids / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "integer" - } -]New value: +[ + { + "maxLength": 100000, + "minLength": 1, + "type": "string" + }, + { + "items": { + "maxLength": 512, + "minLength": 1, + "type": "string" + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + } +] - changed
Input schema / properties / template_file / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "save_literature_notesOutput", - "type": "object" -}New value: +null
- Changed
save_pipeline12 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / config / maxLengthAdded value: +100000 - added
Input schema / properties / config / minLengthAdded value: +1 - added
Input schema / properties / description / maxLengthAdded value: +2000 - added
Input schema / properties / name / maxLengthAdded value: +64 - added
Input schema / properties / name / minLengthAdded value: +1 - added
Input schema / properties / name / patternAdded value: +"^[a-z0-9](?:[a-z0-9_-]{0,63})$" - added
Input schema / properties / scope / enumAdded value: +[ + "auto", + "workspace", + "global" +] - added
Input schema / properties / tags / anyOfAdded value: +[ + { + "items": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9](?:[A-Za-z0-9_.-]{0,63})$", + "type": "string" + }, + "maxItems": 20, + "type": "array" + }, + { + "type": "null" + } +] - changed
Input schema / properties / tags / defaultPrevious value: -""New value: +null - removed
Input schema / properties / tags / typeRemoved value: -"string" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "save_pipelineOutput", - "type": "object" -}New value: +null
- Changed
schedule_pipeline9 fields changed- added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / cron / defaultRemoved value: -"" - added
Input schema / properties / cron / maxLengthAdded value: +200 - added
Input schema / properties / cron / minLengthAdded value: +1 - added
Input schema / properties / name / maxLengthAdded value: +64 - added
Input schema / properties / name / minLengthAdded value: +1 - added
Input schema / properties / name / patternAdded value: +"^[a-z0-9](?:[a-z0-9_-]{0,63})$" - changed
Input schema / requiredPrevious value: -[ - "name" -]New value: +[ + "name", + "cron" +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "schedule_pipelineOutput", - "type": "object" -}New value: +null
- Changed
search_biomedical_images21 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / article_type / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "ab", + "bk", + "bf", + "cr", + "dp", + "di", + "ed", + "ib", + "in", + "lt", + "mr", + "ma", + "ne", + "ob", + "pr", + "or", + "re", + "ra", + "rw", + "sr", + "rr", + "os", + "hs", + "ot" + ], + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / properties / collection / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "pmc", + "cxr", + "usc", + "hmd", + "mpx" + ], + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / hmp_typeAdded value: +{ + "anyOf": [ + { + "enum": [ + "ad", + "ar", + "at", + "bi", + "br", + "cr", + "ca", + "ch", + "cg", + "cd", + "dr", + "ep", + "ex", + "hr", + "hu", + "lt", + "mp", + "nw", + "pn", + "ph", + "pi", + "po", + "pt", + "pc", + "ps" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Hmp Type" +} - changed
Input schema / properties / image_type / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "xg", + "xm", + "x", + "u", + "ph", + "p", + "mc", + "m", + "g", + "c" + ], + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / properties / license_type / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "by", + "bync", + "byncnd", + "byncsa" + ], + "type": "string" + }, + { + "type": "null" + } +] - removed
Input schema / properties / limit / anyOfRemoved value: -[ - { - "type": "integer" - }, - { - "type": "string" - } -] - added
Input schema / properties / limit / maximumAdded value: +50 - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / limit / typeAdded value: +"integer" - removed
Input schema / properties / open_access_onlyRemoved value: -{ - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "string" - } - ], - "default": true, - "title": "Open Access Only" -} - added
Input schema / properties / query / maxLengthAdded value: +500 - added
Input schema / properties / query / minLengthAdded value: +1 - changed
Input schema / properties / search_fields / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "t", + "m", + "ab", + "msh", + "c", + "a" + ], + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / properties / sort_by / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "r", + "o", + "d", + "e", + "g", + "oc", + "pr", + "pg", + "t" + ], + "type": "string" + }, + { + "type": "null" + } +] - removed
Input schema / properties / sourcesRemoved value: -{ - "default": "auto", - "title": "Sources", - "type": "string" -} - changed
Input schema / properties / specialty / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "b", + "bc", + "c", + "ca", + "cc", + "d", + "de", + "dt", + "e", + "en", + "f", + "eh", + "g", + "ge", + "gr", + "gy", + "h", + "i", + "id", + "im", + "n", + "ne", + "nu", + "o", + "or", + "ot", + "p", + "py", + "pu", + "r", + "s", + "t", + "u", + "v", + "vi" + ], + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / properties / subset / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "b", + "c", + "e", + "s", + "x" + ], + "type": "string" + }, + { + "type": "null" + } +] - removed
Input schema / properties / video_only / anyOfRemoved value: -[ - { - "type": "boolean" - }, - { - "type": "string" - } -] - added
Input schema / properties / video_only / typeAdded value: +"boolean" - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "search_biomedical_imagesOutput", - "type": "object" -}New value: +null
- Changed
search_clinvar8 fields changed- added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / limit / anyOfRemoved value: -[ - { - "type": "integer" - }, - { - "type": "string" - } -] - added
Input schema / properties / limit / maximumAdded value: +50 - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / limit / typeAdded value: +"integer" - added
Input schema / properties / query / maxLengthAdded value: +500 - added
Input schema / properties / query / minLengthAdded value: +1 - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "search_clinvarOutput", - "type": "object" -}New value: +null
- Changed
search_compound8 fields changed- added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / limit / anyOfRemoved value: -[ - { - "type": "integer" - }, - { - "type": "string" - } -] - added
Input schema / properties / limit / maximumAdded value: +50 - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / limit / typeAdded value: +"integer" - added
Input schema / properties / query / maxLengthAdded value: +500 - added
Input schema / properties / query / minLengthAdded value: +1 - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "search_compoundOutput", - "type": "object" -}New value: +null
- Changed
search_gene9 fields changed- added
Input schema / additionalPropertiesAdded value: +false - removed
Input schema / properties / limit / anyOfRemoved value: -[ - { - "type": "integer" - }, - { - "type": "string" - } -] - added
Input schema / properties / limit / maximumAdded value: +50 - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / limit / typeAdded value: +"integer" - changed
Input schema / properties / organism / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / query / maxLengthAdded value: +500 - added
Input schema / properties / query / minLengthAdded value: +1 - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "search_geneOutput", - "type": "object" -}New value: +null
- Changed
test_institutional_access4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / pmid / maxLengthAdded value: +32 - added
Input schema / properties / pmid / minLengthAdded value: +1 - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "test_institutional_accessOutput", - "type": "object" -}New value: +null
- Changed
unified_search14 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / filters / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 4096, + "type": "string" + }, + { + "type": "null" + } +] - removed
Input schema / properties / limit / anyOfRemoved value: -[ - { - "type": "integer" - }, - { - "type": "string" - } -] - added
Input schema / properties / limit / maximumAdded value: +100 - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / limit / typeAdded value: +"integer" - changed
Input schema / properties / options / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 2048, + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / properties / pipeline / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 100000, + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / query / defaultAdded value: +"" - added
Input schema / properties / query / maxLengthAdded value: +4096 - changed
Input schema / properties / sources / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 1024, + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / stop_at / maxLengthAdded value: +200 - removed
Input schema / requiredRemoved value: -[ - "query" -] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "unified_searchOutput", - "type": "object" -}New value: +null
- Added
unschedule_pipeline - Added
validate_pico_plan - Changed
verify_reference_list7 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / max_references / maximumAdded value: +200 - added
Input schema / properties / max_references / minimumAdded value: +1 - added
Input schema / properties / reference_text / maxLengthAdded value: +200000 - added
Input schema / properties / reference_text / minLengthAdded value: +1 - added
Input schema / properties / source_name / maxLengthAdded value: +255 - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "verify_reference_listOutput", - "type": "object" -}New value: +null
46 tool updates
v0.5.16- First observed
analyze_figure_for_search - First observed
analyze_search_query - First observed
analyze_timeline_milestones - First observed
build_citation_tree - First observed
build_research_timeline - First observed
compare_timelines - First observed
configure_institutional_access - First observed
convert_icd_mesh - First observed
delete_pipeline - First observed
diagnose_institutional_access - First observed
fetch_article_details - First observed
find_citing_articles - First observed
find_related_articles - First observed
generate_search_queries - First observed
get_article_figures - First observed
get_article_references - First observed
get_cached_article - First observed
get_citation_metrics - First observed
get_compound_details - First observed
get_compound_literature - First observed
get_fulltext - First observed
get_gene_details - First observed
get_gene_literature - First observed
get_institutional_link - First observed
get_pipeline_history - First observed
get_session_log - First observed
get_session_pmids - First observed
get_session_summary - First observed
get_text_mined_terms - First observed
list_pipelines - First observed
list_resolver_presets - First observed
load_pipeline - First observed
manage_pipeline - First observed
parse_pico - First observed
prepare_export - First observed
read_session - First observed
save_literature_notes - First observed
save_pipeline - First observed
schedule_pipeline - First observed
search_biomedical_images - First observed
search_clinvar - First observed
search_compound - First observed
search_gene - First observed
test_institutional_access - First observed
unified_search - First observed
verify_reference_list
TDQS
Scored across 41 tools
Most tools are clearly distinct, but there are multiple near-overlaps: build_citation_tree duplicates forward/backward citation functionality also covered by find_citing_articles and get_article_references, and unified_search vs analyze_search_query vs read_session vs read_research_chronicle can blur boundaries. Detailed descriptions help, but with 41 tools, misselection is still plausible.
Tool names are predominantly verb_noun and consistently snake_case (search_gene, get_gene_details, save_pipeline, delete_pipeline). Minor inconsistencies like 'unified_search' lacking a separate verb and the interchangeable use of get/fetch/find weaken the pattern slightly, but the overall convention is predictable.
41 tools far exceeds the 25+ threshold and feels overloaded for a server named pubmed-search-mcp. The server bundles search, citations, fulltext, genes/compounds, pipelines, chronicles, and institutional access into one surface, making the tool set heavy even though each tool has a clear role.
The tool surface covers the full research workflow: query analysis, unified search, article details, citation/reference exploration, metrics, fulltext, export, notes, and pipeline scheduling. It even adds gene/compound/ClinVar lookup and institutional access diagnostics, so most biomedical literature workflows have no critical dead ends.
Maintenance
Related MCP Connectors
Academic research MCP server for paper search, citation checks, graphs, and deep research.
MCP server for building and testing AI agents with multi-model experimentation and insights.
Open scientific and engineering knowledge for AI agents: search, evidence, document publishing.
AI agent registry — search, discover, register, and connect agents via MCP.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server enabling AI agents to search and retrieve scientific papers, citations, and author profiles from Crossref, OpenAlex, and Semantic Scholar with no API keys required.514 PyPI3MIT
- AlicenseNot gradedqualityCmaintenanceAn MCP server that enables coding agents to search academic papers, ingest full-text PDFs, extract structured details, and manage citations in literature research workflows.27MIT
- FlicenseAqualityDmaintenanceAI-powered research assistant MCP server for searching academic papers and answering research questions with DOI citations.3-
- FlicenseNot gradedqualityDmaintenanceAn advanced scholarly research MCP server that enables AI assistants to discover, fetch, process, and manage academic papers across multiple sources like arXiv, PubMed, and Semantic Scholar, with capabilities for summarization, citation analysis, and concept relationship extraction.2-