OpenAlex MCP
# OpenAlex MCP
A standalone [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server for scholarly search, paper metadata, citation graphs, author and venue resolution, candidate harvesting, API quota visibility, and guarded full-text downloads through OpenAlex.
It uses the official Python MCP SDK with stdio transport and works with any MCP client that can launch a local command. The server is independent of any note-taking application or agent workflow.
> This is a community project and is not affiliated with OpenAlex. Metadata and full-text content remain subject to the terms of OpenAlex and the original publishers.
## Features
| Tool | Purpose |
|---|---|
| `search_works` | Search titles and abstracts or full text, with date, venue, author, topic, OA, arXiv, citation, sorting, and pagination filters |
| `get_work` | Resolve a paper from an OpenAlex W-id, DOI, arXiv ID/URL, or exact title and return detailed metadata |
| `get_citing_works` | Find later works that cite a paper |
| `get_references` | Hydrate a paper's references and rank them by citation count |
| `search_authors` | Find authors by name or ORCID |
| `resolve_entity` | Resolve sources, topics, and institutions from names, ISSNs, or OpenAlex IDs |
| `harvest_candidates` | Run recent, backfill, topic, venue, citation, author, and slow-window retrieval, then exclude, deduplicate, and fuse results with RRF |
| `get_api_quota` | Show the official `/rate-limit` budget, remaining quota, reset time, and endpoint prices |
| `download_work_pdf` | Download OpenAlex-hosted PDF or GROBID XML with root-boundary, size, magic-byte, and atomic-write checks |
The current tool responses are in Chinese while paper titles and technical terms remain in their original language.
## Prerequisites
You need:
- Python 3.12 or newer
- [uv](https://docs.astral.sh/uv/)
- An [OpenAlex API key](https://openalex.org/settings/api)
- An MCP client that supports local stdio servers
You do not need to install Python separately when using most uv workflows: uv can install and manage a compatible Python interpreter for the project.
## 1. Install uv
Use one of the official installation methods below.
### macOS and Linux
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```
Homebrew is also supported:
```bash
brew install uv
```
### Windows
In PowerShell:
```powershell
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```
Or use WinGet:
```powershell
winget install --id=astral-sh.uv -e
```
Restart the terminal if the installer updated your `PATH`, then verify the installation:
```bash
uv --version
uv python install 3.12
```
See the [official uv installation guide](https://docs.astral.sh/uv/getting-started/installation/) for other package managers and uninstall instructions.
## 2. Get an OpenAlex API key
1. Open <https://openalex.org/settings/api>.
2. Sign in or create an OpenAlex account.
3. Create or reveal your API key in the API settings page.
4. Keep the key in a password manager until you add it to your local MCP client configuration.
The server reads the key only from `OPENALEX_API_KEY`. Never commit the key, paste it into an issue, or put a URL containing `api_key=...` in logs. OpenAlex quotas and prices can change; use `get_api_quota` after setup to see the current values for your account.
## 3. Choose an installation method
### Option A: Run directly from GitHub with uvx
This is the shortest installation:
```bash
uvx --from git+https://github.com/DeyangLiu123/openalex-mcp.git openalex-mcp
```
`uvx` creates an isolated environment and runs the command. For a reproducible deployment, pin the Git URL to a commit:
```bash
uvx --from git+https://github.com/DeyangLiu123/openalex-mcp.git@<commit-sha> openalex-mcp
```
The command appears to wait when launched in a terminal because it is a stdio MCP server. Normally your MCP client launches it and communicates over stdin/stdout.
### Option B: Install a persistent user-level command
```bash
uv tool install git+https://github.com/DeyangLiu123/openalex-mcp.git
openalex-mcp
```
Verify where the executable was installed:
```bash
uv tool list
```
To update a VCS installation later:
```bash
uv tool install --force git+https://github.com/DeyangLiu123/openalex-mcp.git
```
### Option C: Clone for development or auditing
```bash
git clone https://github.com/DeyangLiu123/openalex-mcp.git
cd openalex-mcp
uv sync --locked
uv run pytest -m "not live"
```
The local executable is created at:
```text
.venv/bin/openalex-mcp # macOS/Linux
.venv\Scripts\openalex-mcp.exe # Windows
```
## 4. Configure an MCP client
### Generic stdio configuration
Many desktop and editor clients accept a JSON configuration shaped like this:
```json
{
"mcpServers": {
"openalex": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/DeyangLiu123/openalex-mcp.git",
"openalex-mcp"
],
"env": {
"OPENALEX_API_KEY": "your-api-key"
}
}
}
}
```
The exact configuration filename and location depend on the client. Keep this file local and out of version control because it contains the API key.
For a cloned installation, replace `command` with the absolute path to `.venv/bin/openalex-mcp` on macOS/Linux or `.venv\\Scripts\\openalex-mcp.exe` on Windows, and set `args` to an empty array.
### Codex
Codex CLI, the Codex IDE extension, and the Codex desktop experience share the same MCP configuration in `~/.codex/config.toml`. Register the server once with the Codex CLI:
```bash
codex mcp add openalex \
--env OPENALEX_API_KEY=<your-api-key> \
-- uvx --from git+https://github.com/DeyangLiu123/openalex-mcp.git openalex-mcp
```
Verify the registration:
```bash
codex mcp list
codex mcp get openalex
```
Restart Codex or open a new session after changing MCP configuration. In an interactive Codex session, use `/mcp` to confirm that `openalex` is connected and that its nine tools are visible.
The equivalent `~/.codex/config.toml` entry is:
```toml
[mcp_servers.openalex]
command = "uvx"
args = [
"--from",
"git+https://github.com/DeyangLiu123/openalex-mcp.git",
"openalex-mcp",
]
env = { OPENALEX_API_KEY = "your-api-key" }
```
Keep `~/.codex/config.toml` private because this form stores the key locally. If you prefer to manage the secret outside Codex configuration, replace the `env` line with `env_vars = ["OPENALEX_API_KEY"]`, ensure the variable is present in the environment that launches Codex, and restart Codex.
For more detail, see the official [Codex MCP documentation](https://learn.chatgpt.com/docs/extend/mcp).
### Claude Code
With the `uvx` installation method:
```bash
claude mcp add --scope user openalex \
-e OPENALEX_API_KEY=<your-api-key> \
-- uvx --from git+https://github.com/DeyangLiu123/openalex-mcp.git openalex-mcp
```
Then verify that Claude Code sees the server:
```bash
claude mcp list
```
If you do not want the literal key in shell history, read it into a temporary environment variable first and use that variable in the registration command:
```bash
read -s OPENALEX_API_KEY
export OPENALEX_API_KEY
claude mcp add --scope user openalex \
-e OPENALEX_API_KEY="$OPENALEX_API_KEY" \
-- uvx --from git+https://github.com/DeyangLiu123/openalex-mcp.git openalex-mcp
unset OPENALEX_API_KEY
```
## Prompt-based deployment with Codex or Claude Code
Modern coding agents can inspect the repository, install the package, configure their own MCP client, and verify the result. Copy the prompt below into Codex or Claude Code as-is.
```text
Install the OpenAlex MCP server from https://github.com/DeyangLiu123/openalex-mcp.git for me.
Requirements:
1. Inspect the repository README and pyproject.toml before making changes.
2. Check whether Git and uv are installed. If uv is missing, explain the official installation command for my operating system and ask before running a network installer.
3. Use Python 3.12 or newer. Prefer `uvx --from git+https://github.com/DeyangLiu123/openalex-mcp.git openalex-mcp`; use a local clone only if my MCP client requires an absolute executable path.
4. Run the offline test suite if you clone the repository. Do not run live tests or paid download tests without asking me first.
5. Ask me for my OPENALEX_API_KEY only when you are ready to configure the MCP server. Store it only in my local MCP client environment configuration. Never write it into the repository, a tracked file, a chat response, or a log.
6. Configure this current Codex or Claude Code installation with a user-scoped stdio MCP server named `openalex`.
7. Leave OPENALEX_DOWNLOAD_ROOT unset unless I explicitly opt in to file downloads. If I opt in, set it to an absolute directory I approve.
8. Verify that the MCP server is registered and that its nine tools are visible. Then call get_api_quota and perform one low-cost search for three KV cache papers.
9. Report the installed command, configuration location, verification results, and any API cost incurred. Do not create a GitHub release or modify the OpenAlex MCP source repository.
```
Review an agent's proposed commands before approving them, especially network installers, client configuration changes, and any command that includes credentials.
## 5. Verify the setup
Start a fresh MCP client session after registration and try:
```text
Use OpenAlex to find three papers about KV cache. Then show the key references of the most-cited result.
```
You can also ask the client to call `get_api_quota`. A successful result should show the daily budget, usage, remaining quota, reset time, current endpoint prices, and the cost accumulated by this MCP server process.
## Configuration reference
| Environment variable | Default | Description |
|---|---|---|
| `OPENALEX_API_KEY` | unset | Required. The server can start without it, but tools return setup guidance |
| `OPENALEX_BASE_URL` | `https://api.openalex.org` | OpenAlex API base URL |
| `OPENALEX_CONTENT_BASE_URL` | `https://content.openalex.org` | OpenAlex content API base URL |
| `OPENALEX_TIMEOUT` | `30` | HTTP timeout in seconds |
| `OPENALEX_DOWNLOAD_ROOT` | unset | File downloads are disabled until this absolute root is configured |
| `OPENALEX_MAX_DOWNLOAD_BYTES` | `209715200` | Maximum downloaded file size, 200 MiB by default |
To enable content downloads, add an approved absolute directory to the MCP process environment:
```json
{
"OPENALEX_API_KEY": "your-api-key",
"OPENALEX_DOWNLOAD_ROOT": "/absolute/path/to/papers"
}
```
The `download_work_pdf` tool may write only to this root or its descendants.
## Usage notes
### Work search
`search_works` defaults to the more precise title-and-abstract search and supports:
- `from_date` / `to_date`, or a publication `year`
- `venue_ids`, `author_ids`, and `topic_ids`
- `oa_only`, `arxiv_only`, and `min_citations`
- `sort=relevance|date|citations`
- page or cursor pagination
OpenAlex often creates a separate source record for each conference year. To inspect one edition, first call `resolve_entity(entity_type="source", query="INFOCOM 2026")`, verify the canonical name and year, and pass the resulting source ID to `search_works(venue_ids=[...])`. Prefer ISSN resolution for journals.
### Identifiers and ambiguity
- OpenAlex W-ids and URLs are resolved directly.
- DOI and arXiv inputs use singleton lookups. A missing identifier is reported as not indexed instead of being silently replaced by fuzzy text search.
- A title is accepted automatically only when its normalized form matches exactly. Otherwise the server returns up to three candidates for the caller to choose from.
- Lists are deduplicated by normalized DOI first and normalized title second.
### Candidate harvesting
`harvest_candidates` is intended for literature alerts and recommendation workflows. Base queries use `{"line": "label", "q": "query"}` objects and may be combined with a temporary topic, venue IDs, citation seeds, authors, and JSONL exclusion files.
The output reports route counts, per-query coverage, adaptive backfill pages, exclusions, deduplication, RRF scores, and API cost. The free OpenAlex plan does not expose `from_created_date`, so the default strategy combines a recent window with an older publication-date backfill. It reduces losses from delayed indexing but cannot guarantee retrieval beyond the configured window or maximum page count.
## API cost and rate limits
Use `get_api_quota` as the runtime source of truth. OpenAlex quotas and endpoint prices may change. Typical current prices are:
- singleton lookup: free
- filter-only list request: about `$0.0001`
- search request: about `$0.001`
- OpenAlex content download: about `$0.01`
Every tool reports the cost of that call and the total accumulated by the current MCP process. A target file that already exists with `overwrite=false` is detected before the billable content request.
The client distinguishes invalid credentials, paid-plan restrictions, daily quota exhaustion, and short rate limits. It retries bounded network/server failures and short `Retry-After` responses. It also serializes unusually broad Boolean searches when required by the OpenAlex API.
## Download security boundary
`download_work_pdf` cannot write files until `OPENALEX_DOWNLOAD_ROOT` is explicitly configured. When enabled:
- `dest_dir` must resolve to the configured root or one of its descendants.
- `filename` must be a basename; absolute paths, `..`, slashes, backslashes, and NUL are rejected.
- Both `Content-Length` and the actual streamed byte count are bounded.
- PDF content must begin with `%PDF`; XML must have an XML declaration or a `<TEI` root.
- A random temporary file is validated and then atomically installed.
- Failures remove only the temporary file and do not overwrite an existing target.
- URLs containing the API key are redacted from logs and errors.
## Testing
Offline tests do not access the network:
```bash
uv run pytest -m "not live"
```
Live smoke tests make low-cost OpenAlex requests:
```bash
OPENALEX_API_KEY=... uv run pytest -m "live and not paid"
```
The free-plan canary is opt-in because it intentionally checks that a Premium filter is rejected:
```bash
OPENALEX_API_KEY=... OPENALEX_EXPECT_FREE_PLAN=1 \
uv run pytest tests/test_live.py::test_created_date_filter_remains_plan_gated
```
The content-download smoke test incurs an additional charge and requires a second explicit opt-in:
```bash
OPENALEX_API_KEY=... OPENALEX_RUN_PAID_TESTS=1 \
uv run pytest -m "live and paid"
```
Live tests monitor API syntax, quota payloads, title-and-abstract compatibility, Boolean queries, harvesting, and optional content downloads. Online API behavior and data can change, so these canaries require ongoing maintenance.
## Troubleshooting
### `uv` or `uvx` is not found
Restart the terminal after installation and run `uv --version`. If it is still missing, follow the PATH instructions printed by the uv installer or consult the official installation guide linked above.
### The server starts but prints nothing
That is normal for a stdio MCP server waiting for a client. Verify it through your MCP client's server list instead of running it interactively.
### Tools report a missing API key
Set `OPENALEX_API_KEY` in the environment of the MCP server entry, not only in an unrelated terminal session. Restart the MCP client after changing its configuration.
### HTTP 401, 403, or 429
- `401`: the key is missing or invalid.
- `403`, or a plan-related message: the requested feature requires a higher OpenAlex plan.
- Other `429`: the daily quota is exhausted or a request-rate limit was reached. Check `get_api_quota` and `Retry-After`.
### Downloads are rejected
Set `OPENALEX_DOWNLOAD_ROOT` to an absolute directory and keep `dest_dir` inside it. Downloads remain intentionally disabled when the variable is absent.
## Known compatibility note
OpenAlex has deprecated `filter=field.search:` but currently provides no equivalent non-deprecated title-and-abstract-only query. The top-level `search=` parameter also searches full text and can be substantially noisier. This project isolates the current behavior in `text_search_filter()` and monitors it with a live canary so a future migration is limited to one compatibility layer.
## Contributing and security
See [CONTRIBUTING.md](CONTRIBUTING.md) for development requirements and [SECURITY.md](SECURITY.md) for vulnerability reporting.
## License
[MIT](LICENSE)
TDQS
Scored across 9 tools
Most tools have distinct purposes, but there is potential overlap between `search_works` and `harvest_candidates` as both retrieve works. However, descriptions clarify that `harvest_candidates` uses multi-strategy recall, reducing ambiguity. Overall, tools are well-differentiated.
All tool names follow a consistent snake_case verb_noun pattern (e.g., `get_work`, `search_works`, `resolve_entity`). No mixed conventions or irregular formatting, making the set highly predictable.
With 9 tools, the server is well-scoped for a research database wrapper. Each tool serves a clear purpose without unnecessary clutter, and the count is appropriate for the domain.
Covers core workflows for works (search, fetch, references, citing, PDF download) and author search, but lacks direct access to institution/source details after entity resolution. Minor gaps that agents can work around.