npm @cyanheads/arxiv-mcp-serverstreamable-httpupdated 17d ago
@cyanheads/arxiv-mcp-server Search arXiv, fetch paper metadata, and read full-text content via MCP. STDIO or Streamable HTTP. 4 Tools • 2 Resources
¿Qué puedes hacer con arxiv mcp server?
Public Hosted Server: https://arxiv.caseyjhand.com/mcp
Tools
Four tools for searching and reading arXiv papers:
| Tool Name | Description |
|---|---|
arxiv_search |
Search arXiv papers by query with category and sort filters. |
arxiv_get_metadata |
Get full metadata for one or more arXiv papers by ID. |
arxiv_read_paper |
Fetch the full text content of an arXiv paper from its HTML rendering, or from the PDF when no render exists. |
arxiv_list_categories |
List arXiv category taxonomy, optionally filtered by group. |
arxiv_search
Search for papers using free-text queries with field prefixes and boolean operators.
- Field prefixes:
ti:(title),au:(author),abs:(abstract),cat:(category),all:(all fields) - Boolean operators:
AND,OR,ANDNOT - Optional category filter, sorting (relevance, submitted, updated), and pagination
- Category accepts a leaf code (
cs.CL) or a whole archive (astro-ph,cs,math) — a bare archive covers its subject classes plus the legacy flat papers filed before it was subdivided submitted_from/submitted_tobound the submission date (inclusive, UTCYYYY-MM-DD). Consecutive windows cover the matches with no gap — a paper submitted exactly at a midnight seam falls in both, so de-duplicate by ID — which is how to reach results past the 10,000 pagination ceiling- Echoes back the query as actually searched, with every filter folded in — replaying it reproduces the same result set
- Returns up to 50 results per request with full metadata including abstract
arxiv_get_metadata
Fetch full metadata for one or more papers by known arXiv ID.
- Batch fetch up to 10 papers in a single request
- Accepts both versioned (
2401.12345v2) and unversioned (2401.12345) IDs - Legacy ID format supported (
hep-th/9901001) - Reports not-found IDs separately from found papers
arxiv_read_paper
Read the full body of an arXiv paper.
- Tries native arXiv HTML first, then ar5iv, then text extracted from the PDF — the
sourcefield reports which one answered - Strips HTML head/boilerplate and collapses MathML to dollar-delimited LaTeX (
$…$inline,$$…$$block) so the character budget targets paper content - Returns raw HTML — no parsing or extraction; the LLM interprets content directly. PDF-extracted bodies are plain text: prose is reliable, but math, tables, and heading structure flatten
max_charactersdefaults to 100,000; passnullfor the whole paper in one call. Raw HTML can be 500KB-3MB+ for math-heavy papers, which is more than most clients accept in a single tool result — page withstartinstead
arxiv_list_categories
List arXiv category codes and names for discovery.
- ~155 categories across 8 top-level groups (cs, math, physics, q-bio, q-fin, stat, eess, econ)
- Optional group filter to narrow results
- Static data — always succeeds
Resources
| URI Pattern | Description |
|---|---|
arxiv://paper/{paperId} |
Paper metadata by arXiv ID. Percent-encode a legacy ID's slash — arxiv://paper/hep-th%2F9901001. |
arxiv://categories |
Full arXiv category taxonomy. |
Features
Built on @cyanheads/mcp-ts-core:
- Declarative tool definitions — single file per tool, framework handles registration and validation
- Unified error handling across all tools
- Pluggable auth (
none,jwt,oauth) - Structured logging with optional OpenTelemetry tracing
- Runs locally (stdio/HTTP) from the same codebase
arXiv-specific:
- Read-only, no authentication required — arXiv API is free, metadata is CC0
- Rate-limited request queue enforcing arXiv's 3-second crawl delay
- Adaptive cooldown on rate-limit (5s → 10s → 20s → 30s), honors
Retry-After - Retry with exponential backoff for transient failures
- Content fallback chain: native arXiv HTML → ar5iv → PDF text extraction (both HTML renders run LaTeXML, so they tend to fail together; the PDF is the artifact every paper has, and it also covers an ar5iv outage rather than letting one fail the read)
- Full arXiv category taxonomy embedded as static data
- Optional local OAI-PMH metadata mirror (SQLite + FTS5) — opt-in, eliminates rate-limit exposure for
arxiv_searchandarxiv_get_metadata. See Optional: Local Mirror.
Getting Started
Public Hosted Instance
A public instance is available at https://arxiv.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"arxiv-mcp-server": {
"type": "streamable-http",
"url": "https://arxiv.caseyjhand.com/mcp"
}
}
}
Self-Hosted / Local
Add to your MCP client config (e.g., claude_desktop_config.json):
{
"mcpServers": {
"arxiv-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/arxiv-mcp-server@latest"]
}
}
}
Prerequisites
- Bun v1.3.0 or higher.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/arxiv-mcp-server.git
- Navigate into the directory:
cd arxiv-mcp-server
- Install dependencies:
bun install
Configuration
All configuration is optional — the server works out of the box with sensible defaults.
| Variable | Description | Default |
|---|---|---|
ARXIV_API_BASE_URL |
arXiv API base URL. | https://export.arxiv.org/api |
ARXIV_REQUEST_DELAY_MS |
Minimum delay between arXiv API requests (ms). | 3000 |
ARXIV_CONTENT_TIMEOUT_MS |
Timeout for paper body fetches — HTML renders and PDF downloads (ms). | 30000 |
ARXIV_API_TIMEOUT_MS |
Timeout for API search/metadata requests (ms). | 15000 |
ARXIV_MIRROR_ENABLED |
Enable local OAI-PMH metadata mirror for search and metadata. | false |
ARXIV_MIRROR_PATH |
SQLite path for the mirror. | ./data/arxiv-mirror.db |
ARXIV_MIRROR_REFRESH_CRON |
UTC cron expression for in-process daily refresh (HTTP mode only). | unset |
ARXIV_MIRROR_FALLBACK_LIVE |
Fall through to live API on local ID-lookup miss. | true |
ARXIV_MIRROR_RECENT_DAYS_LIVE |
Route sortBy=submitted descending queries within this window to the live API. |
2 |
ARXIV_MIRROR_OAI_BASE_URL |
arXiv OAI-PMH endpoint base URL. | https://oaipmh.arxiv.org/oai |
ARXIV_MIRROR_OAI_REQUEST_DELAY_MS |
Minimum delay between OAI-PMH requests (ms). | 3000 |
ARXIV_MIRROR_REFRESH_TIMEOUT_MS |
Abort budget for one scheduled refresh subprocess (ms). | 7200000 |
MCP_TRANSPORT_TYPE |
Transport: stdio or http. |
stdio |
MCP_HTTP_PORT |
Port for HTTP server. | 3010 |
MCP_AUTH_MODE |
Auth mode: none, jwt, or oauth. |
none |
MCP_LOG_LEVEL |
Log level (RFC 5424). | info |
Running the Server
Local Development
-
Build and run:
bun run build bun run start:http # or start:stdio -
Run checks and tests:
bun run devcheck # Lint, format, typecheck, audit bun run test # Vitest
Optional: Local Mirror
For self-hosted deployments behind a single egress IP, arXiv's ~3-second per-IP crawl delay serializes concurrent users. An optional local mirror eliminates rate-limit exposure for arxiv_search and arxiv_get_metadata by serving from a SQLite + FTS5 store harvested via OAI-PMH. arxiv_read_paper continues to use the live API — full-content harvest is forbidden by arXiv's data policy.
Disabled by default. To enable:
# 1. Cold-start harvest (~4.4h sequential, resumable from checkpoint). One-time per installation.
bun run mirror:init
# 2. Enable the mirror.
export ARXIV_MIRROR_ENABLED=true
# 3. Start the server — reads switch to the mirror once the harvest completes.
bun run start:http
Daily incremental refresh (small delta; duration depends on arXiv's OAI-PMH page pacing) via:
bun run mirror:refresh # wire to cron / systemd timer / launchd, OR
# set ARXIV_MIRROR_REFRESH_CRON to schedule it in HTTP mode (spawned as a child process)
bun run mirror:verify # schema version + PRAGMA integrity_check / quick_check
Schema upgrades. The mirror records a schema version and migrates itself in place the first time a newer server opens it — never a re-harvest, and never a separate operator step. The upgrade that added comment and journal_ref to the full-text index (#37) rebuilds that index from the rows already stored, so co: and jr: searches resolve against a mirror harvested before it. The rebuild runs at startup, before the store answers its first read, and logs mirror migration v2→v3 (fts rebuild) progress lines throughout — on a full-corpus mirror, expect the first start after the upgrade to take noticeably longer than usual. An interrupted rebuild is repeated on the next open rather than left half-applied. bun run mirror:verify prints the schema version the file carries and exits non-zero if a migration never completed.
Behavior notes. Ranking divergence: FTS5 BM25 differs from arXiv's internal ranking, so sortBy=relevance against the mirror returns a different top-K than the live API. Queries sorted by submitted descending within ARXIV_MIRROR_RECENT_DAYS_LIVE days route to the live API to cover the nightly-update gap. Refresh resilience: after the initial cold harvest completes, an in-progress or failed daily refresh keeps serving the existing dataset from the mirror — arxiv_search and arxiv_get_metadata don't drop to the live API during the refresh window (#21). The scheduled HTTP-mode refresh runs in a child process, so the harvest's synchronous SQLite writes never block the request event loop — search and metadata stay responsive throughout (#22). The mirror stores the latest version only; per-version reads continue to use the live API. See #12 for the full design.
Docker
docker build -t arxiv-mcp-server .
docker run -p 3010:3010 arxiv-mcp-server
Project Structure
| Directory | Purpose |
|---|---|
src/mcp-server/tools/definitions/ |
Tool definitions (*.tool.ts). |
src/mcp-server/resources/definitions/ |
Resource definitions (*.resource.ts). |
src/services/arxiv/ |
ArxivService — live arXiv API client (search, metadata, HTML). |
src/services/arxiv/mirror/ |
Optional OAI-PMH mirror — harvester, SQLite + FTS5 store, query translator, runner. |
src/config/ |
Environment variable parsing and validation with Zod. |
scripts/arxiv-mirror-*.ts |
Mirror lifecycle scripts (init, refresh, verify). |
tests/ |
Unit and integration tests. |
docs/ |
Design document and directory structure. |
Development Guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor domain-specific logging - Rate limiting is managed by
ArxivService— don't add per-tool delays - arXiv API returns HTTP 200 for everything — check content-type and response body
Contributing
Issues and pull requests are welcome. Run checks before submitting:
bun run devcheck
bun test
License
Apache-2.0 — see LICENSE for details.
Instalación
Añade arxiv mcp server a tu cliente. Elige el que uses.
{
"servers": {
"arxiv-mcp-server": {
"type": "http",
"url": "https://arxiv.caseyjhand.com/mcp"
}
}
}Add to `.vscode/mcp.json` in your workspace.
claude mcp add arxiv-mcp-server -- npx -y @cyanheads/arxiv-mcp-servercodex mcp add arxiv-mcp-server -- npx -y @cyanheads/arxiv-mcp-serveramp mcp add arxiv-mcp-server -- npx -y @cyanheads/arxiv-mcp-server{
"mcpServers": {
"arxiv-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/arxiv-mcp-server"
]
}
}
}Add to `claude_desktop_config.json`, then restart Claude Desktop.
{
"mcpServers": {
"arxiv-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/arxiv-mcp-server"
]
}
}
}Add to `~/.cursor/mcp.json`, or `.cursor/mcp.json` for a single project.
{
"mcpServers": {
"arxiv-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/arxiv-mcp-server"
]
}
}
}Add to `~/.codeium/windsurf/mcp_config.json`.
{
"mcpServers": {
"arxiv-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/arxiv-mcp-server"
]
}
}
}Add to `cline_mcp_settings.json` via the MCP Servers panel.
{
"mcpServers": {
"arxiv-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/arxiv-mcp-server"
]
}
}
}Add to `~/.gemini/settings.json`.
{
"mcpServers": {
"arxiv-mcp-server": {
"type": "local",
"command": "npx",
"args": [
"-y",
"@cyanheads/arxiv-mcp-server"
],
"tools": [
"*"
]
}
}
}Add to `~/.copilot/mcp-config.json`, or run `/mcp add` inside the CLI.
{
"context_servers": {
"arxiv-mcp-server": {
"command": {
"path": "npx",
"args": [
"-y",
"@cyanheads/arxiv-mcp-server"
]
}
}
}
}Add to your Zed `settings.json`.
npx -y @cyanheads/arxiv-mcp-serverRun `goose configure`, choose **Add Extension → Command-line Extension**, and paste this command.
4 herramientas
arxiv mcp server expone 4 herramientas a un agente conectado.
- arxiv_search
- Search arXiv papers by query with category and sort filters.
- arxiv_get_metadata
- Get full metadata for one or more arXiv papers by ID.
- arxiv_read_paper
- Fetch the full text content of an arXiv paper from its HTML rendering, or from the PDF when no render exists.
- arxiv_list_categories
- List arXiv category taxonomy, optionally filtered by group.
Puntuación
80 / 100
Excelente
- Documentación25/25
- Mantenimiento25/25
- Confianza6/20
- Capacidad9/15
- Instalación15/15
- Documents what it does and how to connect
- Has a resolvable package or endpoint
- Exposes at least one tool, prompt or resource
- README has substantive content
- Includes a code example
- Documents its configuration
- Mentions credentials or security posture
- Last commit 9 days ago
- Has a release history
- Repository is not archived
- No licence detected
- Namespace verified in the official MCP registry
- Claimed by its owner
- Published under an organisation
- 4 tool(s) documented
- Provides prompt templates
- Provides resources
- 18 documented install method(s)
- Published to a package registry
- Offers a hosted endpoint — no local install
Historial de versiones
| Versiones | Publicada |
|---|---|
| 1.5.1Última | 22 ago 2026 |
| 1.5.0 | 27 jul 2026 |
| 1.4.0 | 27 jul 2026 |
| 1.3.1 | 27 jul 2026 |
| 1.3.0 | 26 jul 2026 |
| 1.2.16 | 26 jul 2026 |
| 1.2.15 | 20 jun 2026 |
| 1.2.14 | 15 jun 2026 |
| 1.2.13 | 2 jun 2026 |
| 1.2.12 | 2 jun 2026 |
| 1.2.11 | 31 may 2026 |
| 1.2.10 | 30 may 2026 |
| 1.2.9 | 29 may 2026 |
| 1.2.8 | 29 may 2026 |
| 1.2.7 | 27 may 2026 |
| 1.2.6 | 23 may 2026 |
| 1.2.5 | 22 may 2026 |
| 1.2.4 | 22 may 2026 |
| 1.2.3 | 22 may 2026 |
| 1.2.2 | 22 may 2026 |
| 1.2.1 | 22 may 2026 |
| 1.2.0 | 22 may 2026 |
| 0.1.19 | 18 may 2026 |
| 0.1.18 | 16 may 2026 |
| 0.1.17 | 8 may 2026 |
| 0.1.16 | 5 may 2026 |
| 0.1.15 | 30 abr 2026 |
| 0.1.14 | 30 abr 2026 |
| 0.1.13 | 27 abr 2026 |
| 0.1.12 | 24 abr 2026 |
| 0.1.11 | 24 abr 2026 |
| 0.1.10 | 24 abr 2026 |
| 0.1.9 | 21 abr 2026 |
| 0.1.8 | 19 abr 2026 |
| 0.1.7 | 30 mar 2026 |