Search and retrieve bioRxiv and medRxiv preprints — by DOI, date interval, or keyword — via MCP.
One address for any MCP client. No sign-in needed on this server.
7 read
Grouped by tool name. At most: only reads or looks up information.
Odel charges nothing per call. The publisher may charge for its own service.
Search and retrieve bioRxiv and medRxiv preprints — by DOI, date interval, or keyword — via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://biorxiv.caseyjhand.com/mcp
bioRxiv and medRxiv preprints, metadata and full text. Search by keyword and author, browse a date interval (optionally by subject), fetch any preprint by DOI, and see which preprints went on to journal publication.
| Tool | Description |
|---|---|
biorxiv_get_preprint | Fetch full metadata, abstract, revision history, and journal crosswalk for one or more preprints by DOI |
biorxiv_list_recent | List preprints posted or updated within a date interval, with optional server, category, and funder filters |
biorxiv_search_preprints | Search preprints by keyword and/or author via EuropePMC for relevance ranking, enriched with bioRxiv/medRxiv metadata |
biorxiv_get_published_version | Resolve a preprint DOI to its journal publication record (journal DOI, name, published date), or a journal article's DOI to the preprint it was posted as |
biorxiv_list_published_versions | List preprints that appeared as journal articles within a journal publication-date interval, whenever they were posted, optionally from one publisher |
biorxiv_get_fulltext | Retrieve a preprint's full text as best-effort Markdown extracted from its rendered HTML article page |
biorxiv_list_categories | List valid subject category strings for bioRxiv and medRxiv |
biorxiv_get_preprint toolhttps://doi.org/…, doi:…, a biorxiv.org/medrxiv.org article URL, a vN or .full suffix), scoped to biorxiv, medrxiv, or both (default both)unprocessed[] to pass in another call. A repeated DOI is looked up once, and every list keeps input orderrevisions[] — title, authors, category, license, awards, jatsxmlUrl, publishedJournalDoi once accepted, and the server it was found on (biorxiv or medrxiv, ready to pass back as server). Funder names are omitted because the upstream API misattributes thembiorxiv_get_fulltext with versionfailed[] with a reason (not_found, invalid_doi_format, upstream_unavailable, rate_limited) and a retryable flag; not_found only when every attempted server answeredbiorxiv_list_recent toolstart_date/end_date interval, server (default both), and optional category (a value from biorxiv_list_categories) and bioRxiv-only funder (a ROR ID) filters; a filter that cannot be applied raises invalid_category or invalid_fundercursor, tracked per server ({ biorxiv: { cursor, total }, medrxiv: { cursor, total } }); a cursor past the last page is marked exhausted: true, and a server that did not answer is named in failed[]include_abstract: true adds them. Each is the preprint's latest-revision abstract, even on a row for an earlier revisionbiorxiv_search_preprints toolquery and/or author, optional date_from/date_to and server (default both); up to 100 results per page (default 25; a larger limit returns 100 with a notice), paged with cursor_markbiorxiv_get_preprint; a record left with EuropePMC metadata only carries enriched: false and an enrichment_error (service_error, rate_limited, not_found), with partial_results setinclude_abstract: false drops them for a response about a third the sizebiorxiv_get_published_version toolserver (default both): a preprint DOI (10.1101/, 10.64898/), or a journal article's DOI, which resolves to the preprint it was posted as (10.1016/j.cell.2020.01.001 → 10.1101/614172); 10.64898/ DOIs resolve through the preprint's own journal DOIserver that answered; if no server answers it raises a retryable upstream_unavailable or rate_limited, never doi_not_found10.1101/gr.…, gad.…, lm.…) share the preprint prefix and cannot be resolved by DOIbiorxiv_list_published_versions toolstart_date/end_date interval of journal publication dates and server (default both); each row matches the record biorxiv_get_published_version returns, and may be a preprint posted years earlierlimit rows per server (default 25, up to the API's 100-row page) from an integer cursor, continued at each server's nextCursor; a cursor past the last row is marked exhausted: true, and a server that did not answer is named in failed[]publisher, a journal DOI prefix (10.7554 for eLife), lists only the bioRxiv preprints published under it; server: "both" queries bioRxiv alone, and server: "medrxiv" or a prefix the API does not recognize raises invalid_publisher. These rows carry no journal name, authors, or abstractinclude_abstract: true adds thembiorxiv_get_fulltext toolserver (default both), and an optional version (or a vN suffix; the two must agree, and a version the preprint lacks raises version_not_found); returns Markdown extracted from the rendered HTML article page, naming the answering serveromittedTables names it with the URL that serves its cellsoffset/limit characters (default 20,000), reporting totalChars, remainingChars, hasMore, and wordCount; PDF-only preprints and blocked pages raise fulltext_unavailable, routing to biorxiv_get_preprintbiorxiv_list_categories toolcategory for biorxiv_list_recentBuilt on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
bioRxiv-specific:
BiorxivApiService wraps api.biorxiv.org (details, publications, and crosswalk endpoints) and EuropePmcService wraps EuropePMC search, both with retry and exponential backoffBiorxivFullTextService extracts Markdown from the article pages on www.biorxiv.org / www.medrxiv.orgbiorxiv and medrxiv in parallel when server="both", each result naming the server that answered; a lookup by DOI stops waiting once the server holding that DOI answersUser-Agent header including a mailto address (BIORXIV_MAILTO env var) per Cold Spring Harbor Lab API guidelinesAgent-friendly output:
failed[] with a typed reason and retryable flag instead of aborting the callreason: "rate_limited" with the parsed retryAfter wait, distinct from upstream_unavailablebiorxiv_search_preprints results carry enriched plus a typed enrichment_error (service_error / rate_limited / not_found){beta}, [≥]) are resolved to plain textA public instance is available at https://biorxiv.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"biorxiv-mcp-server": {
"type": "streamable-http",
"url": "https://biorxiv.caseyjhand.com/mcp"
}
}
}
Add the following to your MCP client configuration file.
{
"mcpServers": {
"biorxiv-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/biorxiv-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"BIORXIV_MAILTO": "your@email.com"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"biorxiv-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/biorxiv-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"BIORXIV_MAILTO": "your@email.com"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"biorxiv-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "-e", "BIORXIV_MAILTO=your@email.com", "ghcr.io/cyanheads/biorxiv-mcp-server:latest"]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 BIORXIV_MAILTO=your@email.com bun run start:http
# Server listens at http://localhost:3010/mcp
git clone https://github.com/cyanheads/biorxiv-mcp-server.git
cd biorxiv-mcp-server
bun install
cp .env.example .env
# optionally set BIORXIV_MAILTO for polite API access
All configuration is validated at startup via Zod schemas in src/config/server-config.ts.
| Variable | Description | Default |
|---|---|---|
BIORXIV_MAILTO | Email address for the User-Agent header; optional but recommended. | — |
BIORXIV_API_BASE_URL | Override the bioRxiv API base URL. | https://api.biorxiv.org |
EUROPEPMC_API_BASE_URL | Override the EuropePMC base URL. | https://www.ebi.ac.uk/europepmc/webservices/rest |
BIORXIV_WEB_BASE_URL | Override the bioRxiv website base URL (full-text HTML source for biorxiv_get_fulltext). | https://www.biorxiv.org |
MEDRXIV_WEB_BASE_URL | Override the medRxiv website base URL (full-text HTML source for biorxiv_get_fulltext). | https://www.medrxiv.org |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_HTTP_ENDPOINT_PATH | HTTP endpoint path. | /mcp |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error, etc.). | info |
LOGS_DIR | Directory for log files (Node.js only). | <project-root>/logs |
LOG_TOOL_FAILURE_PAYLOADS | Log each failed tool call's arguments and result, redacted by key name and capped at LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES (default 16384). A secret inside a free-form value is not redacted. | false |
OTEL_ENABLED | Enable OpenTelemetry instrumentation. | false |
See .env.example for the full list of optional overrides.
Build and run:
# One-time build
bun run rebuild
# Run the built server
bun run start:stdio
# or
bun run start:http
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security
bun run test # Vitest test suite
bun run lint:mcp # Validate MCP definitions against spec
docker build -t biorxiv-mcp-server .
docker run --rm -e BIORXIV_MAILTO=your@email.com -p 3010:3010 biorxiv-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/biorxiv-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools and initializes services. |
src/config | Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools | Tool definitions (*.tool.ts). Seven tools across bioRxiv and medRxiv. |
src/services/biorxiv | BiorxivApiService — details, publications, and crosswalk endpoint wrappers with retry. |
src/services/biorxiv-fulltext | BiorxivFullTextService — rendered HTML article page fetch and Markdown extraction. |
src/services/europe-pmc | EuropePmcService — preprint keyword/author search endpoint wrapper. |
tests/ | Unit and integration tests mirroring the src/ structure. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagesrc/mcp-server/tools/definitions/index.tsIssues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.