eutils-mcp-server
This server exposes NCBI Entrez E-utilities as 11 read-only tools, letting you search biomedical literature, fetch sequences and records, and link across databases.
Search Entrez databases (PubMed, Gene, Protein, etc.) with ESearch, getting UIDs, counts, translated queries, and History handles for paging.
Fetch summaries with ESummary: titles, authors, journals, dates.
Fetch full records with EFetch: PubMed abstracts, MEDLINE, FASTA sequences, GenBank, XML, and more.
Link across databases with ELink, e.g., PubMed to PMC, Gene to Protein.
Count matches across databases at once with EGQuery (with fallback to a 12-database subset if NCBI's EGQuery is unreachable).
Get spelling suggestions with ESpell for misspelled queries.
Resolve citations to PMIDs with ECitmatch for bibliography conversion.
Upload UID lists to the NCBI History server with EPost for reuse.
Run combined workflows: search-then-fetch and link-then-fetch to go from a query or UID list straight to downloaded records.
Control output as markdown or JSON for every tool, with built-in rate limiting, batching, size caps, and read-only safety.
Provides read-only access to PubMed (and other NCBI Entrez databases) through the E-utilities, letting a model search biomedical literature, translate queries, retrieve UIDs, fetch abstracts and full records, follow links between Entrez databases, and use the History server for batched retrieval.
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., "@eutils-mcp-server find papers about CRISPR delivery in 2024 and show me the abstracts"
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.
eutils-mcp-server
中文 · English
MCP server exposing the nine NCBI Entrez E-utilities as eleven read-only tools.
It gives a language model the E-utilities directly, so it can search biomedical
literature, fetch sequences, and follow links between Entrez databases without a browser
and without scraping. The repository folder is named E-utilities after the API it
wraps. The package, the server name, and the GitHub repository are all
eutils-mcp-server.
Use it when you want an answer, not a dataset. A question such as "find papers about CRISPR delivery in 2024 and show me the abstracts" is the intended shape. Do not use it for bulk download: NCBI asks that bulk data mining use the local PubMed copy instead, and this server obeys NCBI's rate limit, so a large job takes days. Do not use it to change anything, because it is read-only and NCBI exposes no write path through these utilities.
Table of Contents
Related MCP server: Entrez MCP Server
Background
The Entrez Programming Utilities are a set of nine server-side programs at the National Center for Biotechnology Information. They share one URL syntax and cover 38 databases, including PubMed, PMC, Protein, Nucleotide, Gene, SNP, Structure, and Taxonomy. NCBI documents them in the E-utilities manual.
That interface is stable but awkward for a model to drive directly. Every request needs the same credentials, the same encoding, and the same knowledge of which endpoints accept which output formats. Batch retrieval needs the History server, which carries state across calls. NCBI blocks an IP that exceeds its rate limit.
This server puts those details in code. One client builds every URL, paces every request, follows redirects within an allowlist, caps response size, and redacts the API key. Each tool then maps one operation to one E-utilities call and returns a result the model can read.
Two upstream facts shaped the design. EGQuery is unreachable from the public internet, and the ESummary JSON limit is 500 records rather than the 10,000 the manual states. Both are recorded, with evidence, in docs/upstream-issues.md.
Install
git clone https://github.com/iwinoid/eutils-mcp-server.git
cd eutils-mcp-server
npm install
npm run buildDependencies
Node.js 22 or newer. The version is pinned in .nvmrc.
The server has three runtime dependencies: @modelcontextprotocol/server,
fast-xml-parser, and zod. The lockfile is committed. There is no installer script and
no native build step.
Usage
Register the server with your MCP host. Add this to the host configuration, for example
claude_desktop_config.json:
{
"mcpServers": {
"eutils": {
"command": "node",
"args": ["/absolute/path/to/E-utilities/dist/index.js"],
"env": {
"NCBI_API_KEY": "your-key",
"NCBI_EMAIL": "you@example.com",
"NCBI_TOOL": "eutils-mcp-server"
}
}
}
}To keep the key out of the host configuration, read it from .env instead:
{
"mcpServers": {
"eutils": {
"command": "node",
"args": [
"--env-file-if-exists=/absolute/path/to/E-utilities/.env",
"/absolute/path/to/E-utilities/dist/index.js"
]
}
}
}Then ask the model to search. You can also call a tool directly:
npm run call eutils_esearch '{"db":"pubmed","term":"CRISPR delivery AND 2024[pdat]","retmax":3}'The server answers with a count, a UID list, the translated query, and a History handle:
# ESearch: `CRISPR delivery AND 2024[pdat]`
Database **pubmed** matched **412** records. Showing 3 starting at 0.
## UIDs
40123456, 40123457, 40123458
## History handle
{"db":"pubmed","web_env":"MCID_6aa2...","query_key":"1"}The count changes as PubMed grows. Confirm that you see a count and three UIDs.
Configuration
Every variable is optional. NCBI asks automated clients to identify themselves, and an API key raises the rate limit.
Variable | Default | Purpose |
| unset | Raises the ceiling from 3 to 10 requests per second. Get one from the Settings page of your NCBI account. |
| unset | Contact address sent with every request. NCBI uses it to warn you before an IP block. |
|
| Name that identifies this software in the NCBI logs. |
Supply the values in the env block of your host configuration, or keep them in a .env
file at the project root and launch the server with --env-file-if-exists. npm start
and npm run dev pass that flag for you. When the file is absent, Node prints
not found. Continuing without it. and the launch continues, so a missing .env cannot
break startup. The path resolves against the working directory. Give an absolute path when
your host launches the server from elsewhere.
.gitignore excludes .env. It does not exclude a host configuration file. Check that
file before you commit it.
Set NCBI_EMAIL and NCBI_TOOL, then register both with NCBI by mail to
eutilities@ncbi.nlm.nih.gov. A request that carries the values without prior
registration does not satisfy the NCBI usage policy.
Subscribe to the Entrez Utilities announcement list at the same address. It is the only NCBI channel that reports known bugs. The NCBI Insights blog reports planned changes only, and the release notes inside the E-utilities manual stop at 2015.
Rate limits
NCBI blocks an IP that exceeds its limit. All requests, including internal batches, pass through one token bucket.
3 requests per second without an API key
10 requests per second with one
NCBI asks that large jobs run at a weekend. On a weekday, run them between 21:00 and 05:00 US Eastern time.
Limits
Entrez only. The server reads what Entrez indexes. Data that lives outside Entrez is not reachable.
retmaxceilings.eutils_esearchaccepts up to 10,000.eutils_esummaryandeutils_efetchaccept up to 500 per call. A larger UID list is split into batches of 500, and the response reportsbatches.PubMed and PMC caps. ESearch reaches only the first 10,000 records of a PubMed or PMC result set. Add date filters to segment a larger set.
Truncation. The server cuts a response over 25,000 characters. The message says how to page or narrow the query. A single record larger than the limit keeps its head and tail with an omission marker, because
retstartpages between records, not within one.Response ceiling. The client abandons a response body over 5 MB.
stdio only. No HTTP transport. To add one, bind
127.0.0.1and validate theOriginandHostheaders.EGQuery coverage. EGQuery itself is unreachable, so
eutils_egquerycovers 12 databases instead of 38. See below.
Known upstream issue: EGQuery
NCBI's egquery.fcgi answers with an HTTP 301 to
ext-http-eutils.linkerd.ncbi.nlm.nih.gov. That host is not published in public DNS.
Two independent DNSSEC-validating resolvers, Cloudflare and Google, both return NXDOMAIN
for the name. A control query for eutils.ncbi.nlm.nih.gov resolves normally.
Every parameter combination tried redirects: GET and POST, with and without retmode,
retmax, tool, email, a browser User-Agent, and HTTP/1.0.
An API key does not help. With a valid key, esearch returns 200 while egquery still
returns 301 in the same session. A syntactically invalid key makes egquery return
400 API key invalid instead. That result shows NCBI validates the key before it routes
the request, so the redirect is not a credentials or rate-limit decision.
Run npm run doctor to reproduce the finding on your own network. The full evidence
chain, and the other upstream defects found while building this server, are in
docs/upstream-issues.md.
eutils_egquery tries the real EGQuery first. Only a network failure starts the fallback,
and then the server counts matches with ESearch over 12 commonly used databases. The
result carries degraded: true, a reason, and a note. Read that marker as "this covers a
subset, not all 38 databases". A validation error never starts the fallback, so a bad
query cannot cost 12 extra requests.
The fallback is lazy. If NCBI repairs the endpoint, the real EGQuery returns and no code changes.
Security
The server is read-only and holds no listener. It never writes to disk. There is no port for an attacker to connect to: the only network traffic is outbound HTTPS from the server to NCBI.
Threat | Control |
Prompt injection carried by record text | The server fences NCBI record text between |
Parameter injection | The server validates |
API key leakage | The server masks |
SSRF | The base URL is a constant, not an environment setting. The client follows redirects manually, at most three hops, and every hop must end with |
Resource exhaustion | A token bucket, per-endpoint |
Malicious XML | Entity processing is off. The client strips DOCTYPE declarations and caps the body size before parsing. |
Supply chain | Three runtime dependencies. The lockfile is committed. |
Report a vulnerability through the issue tracker.
API
Eleven tools. Every tool accepts response_format of "markdown" or "json", and
defaults to markdown. Every tool reports readOnlyHint: true and
destructiveHint: false, and declares an outputSchema that its own result satisfies.
Tool | Purpose |
| List databases, or describe one database: searchable fields, links, record count |
| Search a database. Returns UIDs and a History handle |
| Upload a UID list to the NCBI History server |
| Compact summaries for a UID set: title, authors, journal, date |
| Full records: PubMed abstracts, FASTA sequences, other formats |
| Follow links between databases, for example pubmed to pmc, or gene to protein |
| Count matches across many databases at once |
| Spelling suggestion for a query |
| Resolve formatted citations to PMIDs |
| Search and download in one call |
| Follow links and download the target records in one call |
Each tool takes one of the nine E-utilities as its subject. The tool name carries the
E-utilities name after the eutils_ prefix, so eutils_esearch calls esearch.fcgi.
Parameter names follow the API, so the manual applies directly.
Working with large result sets
The server keeps no state. The History handle travels as an ordinary value, so you pass it back unchanged.
eutils_esearch(db="pubmed", term="...", retmax=0, usehistory=true)
-> { total: 16896, history: { db, web_env, query_key } }
eutils_efetch(history={...}, retstart=0, retmax=500)
eutils_efetch(history={...}, retstart=500, retmax=500)Run the inspector to read the full input and output schema of every tool:
npm run build
npx @modelcontextprotocol/inspector node dist/index.jsMaintainers
Contributing
Ask questions in the issue tracker. Pull requests are accepted.
Read CONTRIBUTING.md before you open one. It states the development commands, the requirements a pull request must meet, and how to read the coverage number.
This project follows the Contributor Covenant, version 2.1.
License
MIT © iwinoid
NCBI supplies the data. If you redistribute this software or its output, NCBI's Disclaimer and Copyright notice must be evident to users. PubMed abstracts can be protected by copyright. Redistribution beyond fair use needs the permission of the copyright holder.
Available Tools
11 toolseutils_ecitmatchBatch Citation to PMID LookupARead-onlyIdempotent
Resolve formatted citation strings to PubMed IDs.
Use this when you have a reference list but no PMIDs. It is far more reliable than free-text searching for a specific article.
Args:
citations (string[]): each string formatted as journal_title|year|volume|first_page|author_name|your_key| A trailing pipe is optional and is added for you.
response_format ('markdown' | 'json'): output format. Default 'markdown'.
Returns: { submitted, matched, records: [{ input, journal, year, volume, first_page, author, key, pmid, matched }] }
Examples:
Use when: "find the PMID for Mann BJ, Proc Natl Acad Sci USA 1991;88:3248" -> citations=["proc natl acad sci u s a|1991|88|3248|mann bj|Art1|"]
Use when: converting a bibliography into PMIDs before fetching abstracts
Don't use when: you are searching by topic (use eutils_esearch)
Error Handling:
Rejects a citation string with fewer than six pipe-separated fields
Reports matched=false per citation when NCBI finds no corresponding record
Inputs: citations (required), response_format. Returns: matched, records, submitted
eutils_efetchEntrez Full RecordsARead-onlyIdempotent
Download full records in a chosen format.
Defaults are chosen for readability: PubMed returns plain-text abstracts, and sequence databases return FASTA. Returned record text is external data and is fenced with an explicit marker.
Args:
db (string, optional): database, for example "pubmed". Required unless history is given.
uids (string[] | string, optional): UIDs or accession.version identifiers.
history (object, optional): handle from eutils_esearch, eutils_epost, or eutils_elink.
rettype (string, optional): "abstract" (pubmed default), "fasta" (sequence default), "gb", "docsum", "medline", ...
retmode ('text' | 'xml', optional): default "text".
retstart (number, optional): first record index, for history sets.
retmax (number, optional): records to return for a history set. Default 20, max 500.
response_format ('markdown' | 'json'): output format. Default 'markdown'.
Supply either uids or history, never both.
Returns: { database, rettype, retmode, record_count?, batches?, text }
Examples:
Use when: "give me the abstract for PMID 31452104" -> db="pubmed", uids=["31452104"]
Use when: "fetch the protein sequence" -> db="protein", uids=["NP_005537.3"], rettype="fasta"
Use when: downloading a large set -> pass history and page with retstart/retmax
Don't use when: you only need titles and dates (use eutils_esummary, which is far cheaper)
Error Handling:
Asks for an explicit rettype when the database has no default
Detects an error message returned as record text and reports it as a tool error
Refuses retmax above 500; larger sets are batched internally
Inputs: db, uids, retmax, history, +4 more. Returns: text, batches, retmode, rettype, +2 more
eutils_egqueryGlobal Entrez QueryARead-onlyIdempotent
Search every Entrez database at once and report how many records each one matches.
Use this to find which database holds data for a topic before committing to a search. It returns counts only, never records.
Args:
term (string): Entrez text query, for example "CRISPR base editing".
response_format ('markdown' | 'json'): output format. Default 'markdown'.
Returns: { term, databases_searched, databases_with_hits, hits: [{ db, menu, count, status }] (sorted by count, descending), empty_databases: string[] }
Examples:
Use when: "which database has information about BRCA1 variants?" -> term="BRCA1 variants"
Don't use when: you already know the database (use eutils_esearch instead)
Error Handling:
Returns "The search term was empty" when term is blank
NCBI EGQuery redirects to an internal host that is not published in public DNS, for every client including ones with a valid API key. When the real EGQuery is unreachable this tool falls back to per-database ESearch counts over 12 commonly used databases, and says so in a "degraded" field. Counts are then a subset, not all 38.
The fallback triggers only on a network failure, never on a validation error.
Inputs: term (required), response_format. Returns: hits, term, degraded, degraded_reason, +3 more
eutils_einfoEntrez Database InfoARead-onlyIdempotent
List Entrez databases, or describe one database's searchable fields and links.
Call with no arguments to list all Entrez databases. Call with db to get that database's record count, last update time, searchable field names, and the links available to other databases.
Args:
db (string, optional): database to describe, for example "pubmed". Omit to list all.
response_format ('markdown' | 'json'): output format. Default 'markdown'.
Returns: Without db: { count, databases: string[] } With db: { database, menu_name, description, record_count, last_update, build, field_count, fields: [{ name, fullname, description, termcount? }], link_count, links: [{ name, dbto, menu }] }
Examples:
Use when: "what fields can I search in PubMed?" -> db="pubmed"
Use when: "which Entrez databases exist?" -> no arguments
Use when: "what databases link from a gene record?" -> db="gene"
Don't use when: you want record counts for a query (use eutils_egquery instead)
Error Handling:
Rejects a database name that is not one of the known Entrez databases, and lists samples
Returns a parse error if NCBI changes the response shape
Inputs: db, response_format. Returns: count, links, fields, database, +4 more
eutils_elinkEntrez Cross-Database LinksARead-only
Find records linked to a set of UIDs, either in another database or within the same one.
This is how you move between databases: gene to protein, pubmed to pmc, nucleotide to snp, and so on. With cmd="neighbor_history" the linked set is stored on the NCBI History server and returned as a handle you can feed straight into eutils_efetch.
Args:
dbfrom (string): source database, for example "pubmed".
db (string, optional): target database, for example "pmc". Omit for same-database links.
uids (string[] | string, optional): source UIDs.
history (object, optional): handle whose db matches dbfrom.
cmd (string, optional): "neighbor" (default), "neighbor_score", "neighbor_history", "acheck", "ncheck", "lcheck", "llinks", "prlinks".
linkname (string, optional): a specific link, for example "pubmed_pmc". Use eutils_einfo to list them.
response_format ('markdown' | 'json'): output format. Default 'markdown'.
Supply either uids or history, never both.
Returns: { dbfrom, dbto?, command, groups_found, total_linked, groups: [{ dbto, linkname, count, ids[], query_key? }], histories? }
Examples:
Use when: "which PMC articles correspond to these PMIDs?" -> dbfrom="pubmed", db="pmc"
Use when: "find proteins for these gene IDs" -> dbfrom="gene", db="protein"
Use when: chaining a download -> cmd="neighbor_history", then pass histories to eutils_efetch
Don't use when: you want records, not UID lists (use eutils_link_then_fetch)
Error Handling:
Rejects a history whose db does not match dbfrom
Returns an empty result with a hint to list valid link names via eutils_einfo
Inputs: dbfrom (required), db, cmd, uids, +3 more. Returns: dbto, dbfrom, groups, command, +3 more
eutils_epostUpload UIDs to Entrez HistoryARead-only
Upload a list of UIDs to the NCBI History server and get a reusable handle.
Use this when you already have UIDs from somewhere other than an ESearch, or when you want to combine several sets. Many thousands of UIDs fit in one call.
Args:
db (string): database the UIDs belong to, for example "gene".
uids (string[] | string): UIDs or accessions, as an array or comma-separated string.
response_format ('markdown' | 'json'): output format. Default 'markdown'.
Returns: { database, uploaded, history: { db, web_env, query_key } }
Examples:
Use when: "fetch these five gene IDs" -> db="gene", uids=["7173","22018","54314"]
Use when: combining UID lists from two sources before one download
Don't use when: you are about to search; ESearch with usehistory already posts its own results
Error Handling:
Rejects UIDs containing URL metacharacters
Reports an upstream error if NCBI returns no History handle
Inputs: db (required), uids (required), response_format. Returns: history, database, uploaded
eutils_esearchEntrez Text SearchARead-only
Search an Entrez database and return matching UIDs.
This is the entry point for a retrieval pipeline. It returns UIDs, never records. By default it also stores the result set on the NCBI History server and returns a history handle, so later calls can page through the whole set without re-searching.
Entrez field tags go in square brackets: gene[tiab], 2008[pdat], mouse[orgn]. Boolean operators AND, OR, NOT must be uppercase.
Args:
db (string): database to search, for example "pubmed".
term (string): Entrez query, for example "breast cancer AND 2008[pdat]".
retmax (number, optional): UIDs to return, 0-10000. Default 20. Use 0 for count only.
retstart (number, optional): index of the first UID. Default 0.
sort (string, optional): "pub_date", "relevance", "first_author", ...
datetype ('pdat' | 'edat' | 'mdat', optional): date field for mindate/maxdate.
mindate, maxdate (string, optional): YYYY, YYYY/MM, or YYYY/MM/DD.
usehistory (boolean, optional): return a History handle. Default true.
response_format ('markdown' | 'json'): output format. Default 'markdown'.
Returns: { database, term, total, count, offset, has_more, next_offset, uids: string[], query_translation, term_translations: [{ from, to }], history? }
Examples:
Use when: "find papers about CRISPR in Nature" -> db="pubmed", term="CRISPR AND nature[journal]"
Use when: "how many records mention this gene?" -> retmax=0
Don't use when: you already have UIDs (use eutils_esummary or eutils_efetch)
Don't use when: you don't know which database (use eutils_egquery first)
Error Handling:
Rejects retmax above 10000 with advice to use the History server
Rejects an unknown database and lists valid ones
Returns an empty result with spelling advice rather than an error
Inputs: db (required), term (required), sort, retmax, +6 more. Returns: term, uids, count, total, +7 more
eutils_espellSpelling SuggestionARead-onlyIdempotent
Get NCBI's spelling suggestion for a query in one database.
Args:
db (string): database to check against, for example "pubmed".
term (string): query to check, for example "breast cancr".
response_format ('markdown' | 'json'): output format. Default 'markdown'.
Returns: { database, query, corrected_query, changed }
Examples:
Use when: a search returned no results and you suspect a typo
Use when: "did you mean" for a query -> term="diabetis"
Don't use when: the query is a structured field search; ESpell works on plain terms
Error Handling:
Reports changed=false when NCBI has no correction, rather than an error
Inputs: db (required), term (required), response_format. Returns: query, changed, database, corrected_query
eutils_esummaryEntrez Document SummariesARead-onlyIdempotent
Fetch compact summaries (DocSums) for a set of UIDs.
Use this to screen records by title, authors, journal, and date before paying the cost of downloading full records.
Args:
db (string, optional): database, for example "pubmed". Required unless history is given.
uids (string[] | string, optional): UIDs or accessions.
history (object, optional): handle from eutils_esearch, eutils_epost, or eutils_elink.
retstart (number, optional): first record index, for history sets. Default 0.
retmax (number, optional): records to return for a history set. Default 20, max 500.
response_format ('markdown' | 'json'): output format. Default 'markdown'.
Supply either uids or history, never both.
Returns: { database, total, count, offset, has_more, next_offset?, batches?, records: [{ uid, title, authors[], journal, source, pubdate, volume, issue, pages, doi?, pmcid?, pubtype[], lang[] }] }
Non-PubMed databases return whichever scalar fields the DocSum carries.
Examples:
Use when: "show me the titles of these PMIDs" -> db="pubmed", uids=["31452104"]
Use when: screening a large result set -> pass history from eutils_esearch
Don't use when: you need the full abstract or sequence (use eutils_efetch)
Error Handling:
Refuses more than 500 UIDs per call and batches larger lists internally
Refuses to combine uids and history in one call
Rejects retmax above 500 rather than silently truncating
Inputs: db, uids, retmax, history, +2 more. Returns: count, total, offset, batches, +4 more
eutils_link_then_fetchLink and Fetch Across DatabasesARead-onlyIdempotent
Follow links from one database to another and download the target records in one call.
Typical uses: gene IDs to protein sequences, PMIDs to PMC full text, nucleotide records to SNPs. Give it either a query or a UID list in the source database, and it returns records from the target database.
Args:
dbfrom (string): source database, for example "gene".
db (string): target database to download from, for example "protein".
term (string, optional): query in dbfrom. Pass exactly one of term or uids.
uids (string[] | string, optional): source UIDs in dbfrom.
linkname (string, optional): specific link to follow.
retmax (number, optional): target records to download. Default 20, max 500.
rettype (string, optional): record format for the target database.
response_format ('markdown' | 'json'): output format. Default 'markdown'.
Returns: { dbfrom, dbto, source_total, retrieved, rettype, source_history, history, text }
Examples:
Use when: "get the protein sequences for these gene IDs" -> dbfrom="gene", db="protein", uids=[...]
Use when: "find PMC full text for papers about X" -> dbfrom="pubmed", db="pmc", term="..."
Don't use when: you only need the linked UIDs (use eutils_elink, which is cheaper)
Error Handling:
Rejects passing both term and uids, or neither
Returns an empty result with a hint to list link names when no links exist
Refuses retmax above 500
Inputs: db (required), dbfrom (required), term, uids, +4 more. Returns: dbto, text, dbfrom, history, +4 more
eutils_search_then_fetchSearch and FetchARead-onlyIdempotent
Search a database and download the matching records in one call.
This is the shortcut for the common "find me the papers about X" request. It runs ESearch with a History handle, then EFetch, saving a round trip. Use the individual tools when you want to screen titles before downloading.
Args:
db (string): database to search, for example "pubmed".
term (string): Entrez query.
retmax (number, optional): records to download. Default 20, max 500.
rettype (string, optional): "abstract" (pubmed default), "fasta" (sequence default), ...
retmode ('text' | 'xml', optional): default "text".
response_format ('markdown' | 'json'): output format. Default 'markdown'.
Returns: { database, term, total, retrieved, rettype, retmode, history, text }
Examples:
Use when: "summarize recent papers on CRISPR delivery" -> db="pubmed", term="CRISPR delivery AND 2024[pdat]"
Use when: "get the sequences for these gene records" -> db="nuccore", term="..."
Don't use when: you want to inspect titles first (use eutils_esearch then eutils_esummary)
Don't use when: the result set is huge; search with retmax=0 first to see the count
Error Handling:
Returns a friendly empty result, with spelling advice, when nothing matches
Refuses retmax above 500
Reports the ESearch count so you can judge whether to page
Inputs: db (required), term (required), retmax, retmode, +2 more. Returns: term, text, total, history, +4 more
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 11 tools
Each tool maps to a distinct E-utilities operation (search, fetch, summary, link, post, spell, cite-match, database listing, cross-db counts), and descriptions include explicit 'Don't use when' cross-references. The two composite tools (search_then_fetch, link_then_fetch) could overlap with manual chains, but the descriptions clearly state when to prefer each, e.g. use esummary first to screen titles.
All tools share the eutils_ prefix and mostly follow the NCBI API names (esearch, efetch, elink), giving a predictable pattern. The two convenience tools use snake_case (search_then_fetch, link_then_fetch), which is readable but a slight deviation from the concatenated style.
11 tools is well-scoped, essentially covering the standard NCBI E-utilities suite plus two pragmatic shortcuts. Each tool earns its place with no redundant entries.
The surface covers the full E-utilities lifecycle: discovery (einfo, egquery), searching (esearch), history management (epost), retrieval (esummary, efetch), linking (elink), and utilities (espell, ecitmatch), plus end-to-end combos. No obvious dead ends for the domain.
Maintenance
Related MCP Connectors
Search biomedical literature, get article details, find related articles, and explore MeSH terms
Search biomedical papers, inspect publication records, and traverse citation or semantic graphs.
PubMed MCP — wraps the NCBI E-utilities API (biomedical literature, free, no auth)
Search PubMed/Europe PMC, fetch articles and full text (PMC/EPMC/Unpaywall), citations, MeSH terms.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceProvides access to NCBI's scientific databases including E-utilities, PubChem, and PMC APIs for biomedical literature search, molecular data retrieval, and research through natural language queries.3-
- FlicenseNot gradedqualityDmaintenanceProvides access to NCBI's E-utilities, PubChem, and PMC APIs for searching and retrieving biomedical literature, chemical, and genomic data.-
- AlicenseAqualityBmaintenanceEnables biomedical literature research with 17 tools for searching and retrieving publications, full texts, MeSH terms, citations, clinical trials, drug safety data, and more from multiple sources without requiring API keys.17MIT
- AlicenseNot gradedqualityAmaintenanceEnables searching PubMed, PubMed Central, and Europe PMC and fetching article metadata, full text, citations, related works, MeSH terms, and identifier conversions. Runs over STDIO or Streamable HTTP and exposes 11 tools, a database info resource, and a research-planning prompt.9 npmMIT