Skip to main content
Glama
zlobste

arXiv MCP Server

by zlobste
README.md
# arXiv MCP Server

**arXiv**, meet the Model Context Protocol: search metadata, resolve IDs, and plug literature review into assistants without one-off scrapers or ad hoc APIs. The implementation is deliberately small-built on the official Python SDK's `FastMCP`, tuned for clarity and predictable behavior.

Use **stdio** when the server runs beside your client, or **Streamable HTTP** when you want a network-facing endpoint (MCP's current transport story-no SSE). Queries hit arXiv's public Atom API at `export.arxiv.org/api/query`, with gentle rate limiting so traffic stays neighborly.

The full surface area-tools, resources, prompts, Docker-is laid out under **Features** next.

## Features

### Tools

- `search_papers`
  - Run a raw arXiv query such as `cat:cs.AI AND all:"large language models"`
- `find_papers`
  - Structured search using separate fields such as title, author, category, and abstract terms
- `get_paper`
  - Fetch a single paper by arXiv ID
- `list_recent_papers`
  - Get recent papers for a category, sorted by last updated date
- `build_pdf_url`
  - Return the PDF URL for an arXiv paper ID

### Resources

- `arxiv://query-syntax`
  - Quick reference for arXiv query syntax
- `arxiv://categories/common`
  - Common categories for ML, AI, math, stats, physics, and economics
- `arxiv://server-info`
  - Runtime and behavior notes for this MCP server

### Prompts

- `literature_review`
  - A reusable prompt that guides an LLM to search, shortlist, compare, and summarize arXiv papers

## Quick start

### Option 1, local Python

```bash
python -m venv .venv
source .venv/bin/activate
pip install -e .
```

Run in stdio mode:

```bash
arxiv-mcp-stdio
```

Run in HTTP mode:

```bash
ARXIV_MCP_HOST=0.0.0.0 ARXIV_MCP_PORT=8080 arxiv-mcp-http
```

The MCP endpoint will be available at:

```text
http://localhost:8080/mcp
```

Health endpoint:

```text
http://localhost:8080/healthz
```

### Option 2, Docker Compose

```bash
docker compose up --build
```

That starts the HTTP server on port `8080`.

## Configuration

Environment variables:

| Variable | Default | Description |
|---|---:|---|
| `ARXIV_API_BASE_URL` | `https://export.arxiv.org/api/query` | arXiv API query endpoint |
| `ARXIV_API_USER_AGENT` | `arxiv-mcp-server/0.1.0` | User-Agent for upstream requests |
| `ARXIV_API_TIMEOUT_SECONDS` | `30` | HTTP timeout |
| `ARXIV_API_MIN_INTERVAL_SECONDS` | `3.0` | Minimum delay between consecutive upstream requests |
| `ARXIV_DEFAULT_MAX_RESULTS` | `5` | Default result size |
| `ARXIV_MAX_ALLOWED_RESULTS` | `25` | Hard cap to avoid oversized tool payloads |
| `ARXIV_MCP_HOST` | `0.0.0.0` | HTTP bind host |
| `ARXIV_MCP_PORT` | `8080` | HTTP bind port |
| `ARXIV_MCP_ALLOW_ORIGINS` | `*` | CORS allow-origins |

## Example MCP client configuration

### Stdio client example

```json
{
  "mcpServers": {
    "arxiv": {
      "command": "arxiv-mcp-stdio"
    }
  }
}
```

### HTTP client example

Point your MCP client to:

```text
http://localhost:8080/mcp
```

## Example tool calls

### Raw arXiv query

```json
{
  "name": "search_papers",
  "arguments": {
    "query": "cat:cs.AI AND all:\"large language models\"",
    "max_results": 5,
    "sort_by": "relevance",
    "sort_order": "descending"
  }
}
```

### Structured search

```json
{
  "name": "find_papers",
  "arguments": {
    "title": "retrieval augmented generation",
    "category": "cs.IR",
    "max_results": 5
  }
}
```

### Paper by ID

```json
{
  "name": "get_paper",
  "arguments": {
    "arxiv_id": "2401.00001"
  }
}
```

## Development

Install dev dependencies:

```bash
pip install -e .[dev]
```

Run tests:

```bash
pytest
```

Lint:

```bash
ruff check .
```

## Limitations

- This server uses the public arXiv API and does not download or parse PDFs.
- The arXiv API returns Atom XML, not JSON, so parsing is intentionally centralized.
- To stay polite with the public API, this server rate-limits upstream requests.
- For very large or bulk ingestion workloads, use arXiv's separate bulk metadata options instead of this MCP server.

## License

[MIT](LICENSE)