Atlas / MCP servers / u9401066 / PubMed Search

PubMed SearchBLOCK

mcp/u9401066/pubmed-search-2

MCP SDK v2 server for PubMed and multi-source biomedical research, with resilient search, full text, citations, and tenant-safe deployment.

Verdict
BLOCK
Grade
F
Trust score
42 /100
Exposed tools
38 34r · 2w · 2d
Transport
streamable-http
License
NOASSERTION
Stars
28
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

[](https://badge.fury.io/py/pubmed-search-mcp) [](https://www.python.org/downloads/) [](https://opensource.org/licenses/Apache-2.0) [](https://modelcontextprotocol.io/) [](https://github.com/u9401066/pubmed-search-mcp/actions/workflows/ci.yml)

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
Read from source at commit b043d5b88d5cOBSERVED · 2026-10-09
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add pubmed-search-mcp --env BROWSER_FETCH_BROKER_TOKEN=${BROWSER_FETCH_BROKER_TOKEN} --env BROWSER_FETCH_TOKEN=${BROWSER_FETCH_TOKEN} --env KEY=${KEY} --env NCBI_API_KEY=${NCBI_API_KEY} -- uvx pubmed-search-mcp
claude-desktop
{
  "mcpServers": {
    "pubmed-search-mcp": {
      "command": "uvx",
      "args": [
        "pubmed-search-mcp"
      ],
      "env": {
        "BROWSER_FETCH_BROKER_TOKEN": "${BROWSER_FETCH_BROKER_TOKEN}",
        "BROWSER_FETCH_TOKEN": "${BROWSER_FETCH_TOKEN}",
        "KEY": "${KEY}",
        "NCBI_API_KEY": "${NCBI_API_KEY}"
      }
    }
  }
}
03

Exposed tools (38)

34 read · 2 write · 2 destructive. Blast radius: 2 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
analyze_search_queryread
build_citation_treeread
build_research_chronicleread
convert_icd_meshreadQuery the curated ICD/MeSH crosswalk in one explicit direction.
delete_pipelinedestructivePermanently delete a saved pipeline configuration and execution history.
diagnose_institutional_accessread
fetch_article_detailsread
find_citing_articlesread
find_related_articlesread
generate_search_queriesread
get_article_figuresreadGet structured figure metadata (label, caption, image URL) and PDF links from a PMC Open Access article.
get_article_referencesread
get_citation_metricsread
get_compound_detailsread
get_compound_literatureread
get_fulltextread
get_gene_detailsread
get_gene_literatureread
get_institutional_linkread
get_pipeline_historyreadGet execution history for a saved pipeline.
get_text_mined_termsread
list_resolver_presetsread
load_pipelinereadLoad a pipeline configuration for review or editing.
prepare_exportread
readreadRead corpus records using numeric transport IDs returned by search.
read_research_chronicleread
read_sessionreadRead session data through one schema-exact discriminated request.
save_literature_noteswrite
schedule_pipelinewriteSchedule a saved pipeline for periodic execution.
searchreadSearch title/abstract text with plain lexical terms. Supports iterative queries.
search_biomedical_imagesread
search_clinvarread
search_compoundread
search_generead
test_institutional_accessread
unschedule_pipelinedestructiveRemove the active schedule for a saved pipeline.
validate_pico_planreadValidate agent-provided P/I/C/O and return a runnable PICO pipeline.
verify_reference_listreadVerify a plain-text reference list against PubMed evidence.
04

Trust audit

BLOCKgrade F · trust 42/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (5 observation(s))
Network
declared (12 observation(s))
Shell
declared (1 observation(s))
Dependencies
pinned
Secrets in source
found

Findings (25)

HIGHCode injection · code.deserialize · CWE-78, CWE-94, CWE-95
src/pubmed_search/application/pipeline/config_parser.py:112
parsed = yaml.load(text, Loader=_BoundedSafeLoader)  # noqa: S506  # nosec B506
Why it matters. deserialises untrusted bytes into live objects
Fix. use json or yaml.safe_load
HIGHNetwork egress · net.metadata_ip · CWE-200, CWE-319
src/pubmed_search/infrastructure/http/safe_outbound.py:38
"metadata.google.internal",
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
docker-compose.yml:31
PUBMED_ALLOWED_ORIGINS: http://localhost:${PUBMED_LOCAL_PORT:-8765},http://127.0.0.1:${PUBMED_LOCAL_PORT:-8765}
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/test_browser_fetch_broker_security.py:57
token = "local-dev-token-0123456789abcdefgh"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/test_cache_substrate.py:80
secret = "PRIVATE_CACHE_KEY_AND_EXCEPTION_DETAIL"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/test_clinicalkey_ai.py:486
secret = "oauth-client-secret-sentinel"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/test_copilot_hook_integration.py:396
secret = "PRIVATE_ERROR_DETAIL_MUST_NOT_PERSIST"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/test_input_normalizer.py:177
secret = "TOPSECRET_RESPONSE_SENTINEL"
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
delete_pipeline, unschedule_pipeline
Why it matters. 2 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.hidden_file · CWE-1104
.bandit
.bandit
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.hidden_file · CWE-1104
.env.service.example
.env.service.example
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.hidden_file · CWE-1104
.instruction_drift_fingerprint
.instruction_drift_fingerprint
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.hidden_file · CWE-1104
.ngrok.env
.ngrok.env
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.hidden_file · CWE-1104
.pre-commit-config.yaml
.pre-commit-config.yaml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
src/pubmed_search/application/session/manager.py:882
session_id = hashlib.md5(  # nosec B324
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
scripts/build_docs_site.py:119
"](../images/": "](../../../../docs/images/",
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
scripts/build_docs_site.py:127
"](../images/": "](../../../../docs/images/",
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/test_docs_site_sync.py:365
"[README section](../../README.md#-configuration)",
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/test_docs_site_sync.py:373
"[Deployment check](../../DEPLOYMENT.md#10-驗證清單)",
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/test_docs_site_sync.py:392
"[Stale deployment check](../../DEPLOYMENT.md#9-驗證清單)",
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
tests/test_fulltext_phases.py:188
"http://169.254.169.254/latest/meta-data.pdf",
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
tests/test_safe_outbound_http.py:36
"http://169.254.169.254/latest/meta-data/",
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.md:213
"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\",\"*.jamanetw
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.zh-TW.md:197
"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\",\"*.jamanetw
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/guides/INTEGRATIONS.md:350
| `BROWSER_FETCH_BROKER_URL` | No | Local broker endpoint, e.g. `http://127.0.0.1:8766/fetch` | — |

Gates applied: no_behavioural_pass.

Audited 2026-10-09 · audit v0.4.1 · source sha b043d5b88d5cfull audit observations/trust-audit/mcp-server/u9401066__pubmed-search-2.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-09b043d5b88d5cBLOCKF42first audit
06

Questions

What is the PubMed Search MCP server?

MCP SDK v2 server for PubMed and multi-source biomedical research, with resilient search, full text, citations, and tenant-safe deployment.

What tools does PubMed Search expose?

38 in total: 34 read-only, 2 that write, and 2 that can delete or overwrite (delete_pipeline, unschedule_pipeline). Every one is listed on this page with its risk.

Is PubMed Search safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (42/100) and found 2 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 2 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does PubMed Search need?

It reads BROWSER_FETCH_BROKER_TOKEN, BROWSER_FETCH_TOKEN, KEY, NCBI_API_KEY and PUBMED_BEARER_TOKEN from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does PubMed Search run?

It speaks streamable-http, so it runs as a service you connect to over the network. It is published on PyPI as pubmed-search-mcp.

How current is this page?

The grade is for one exact copy of the source (b043d5b88d5c), read on 2026-10-09. The repository is watched and re-audited when it changes.

Advertisement