paper-search-rs
A native Rust MCP server for academic paper metadata search. It targets MCP 2025-11-25, runs over
stdio, and returns schema-defined structured results.
The Python implementation is preserved on the v0 branch. PDF downloading, full-text reading, RAG,
and reference management are intentionally out of scope.
Features
- Four providers: arXiv, Semantic Scholar, Scopus, and Web of Science
- Bounded async fan-out with provider failure isolation
- Typed
inputSchema,outputSchema, andstructuredContent - JSON
TextContentcompatibility copy for every tool result - DOI/title deduplication, sorting, and normalized post-search filters
- Rate limiting, retry/backoff, caching, timeouts, and HTTP/HTTPS/SOCKS proxy support
- JCR/Impact Factor, CAS quartile, CCF rank, and warning-list enrichment
- Native ShowJCR updates without a system
gitor SQLite dependency
Build
Requires Rust 1.95.0 (pinned in rust-toolchain.toml).
cargo build --release --locked
./target/release/paper-search-rs --version
To install the current checkout into Cargo's binary directory:
cargo install --path . --locked
The native binary can also be distributed through npm and PyPI without compiling Rust locally.
After the packages are published, run the same native stdio server through either package manager:
npx --yes paper-search-rs
uvx paper-search-rs
Both commands select a prebuilt binary. They do not download source code or require a Rust toolchain on the user's machine.
MCP Client Configuration
The server supports stdio only. Use an absolute binary path:
{
"mcpServers": {
"paper-search": {
"command": "/absolute/path/to/paper-search-rs",
"env": {
"PAPER_SEARCH_DEFAULT_PLATFORMS": "arxiv,semantic_scholar"
}
}
}
}
Using the npm package:
{
"mcpServers": {
"paper-search": {
"command": "npx",
"args": ["--yes", "paper-search-rs"],
"env": {
"PAPER_SEARCH_DEFAULT_PLATFORMS": "arxiv,semantic_scholar"
}
}
}
}
Using the PyPI wheel through uvx:
{
"mcpServers": {
"paper-search": {
"command": "uvx",
"args": ["paper-search-rs"],
"env": {
"PAPER_SEARCH_DEFAULT_PLATFORMS": "arxiv,semantic_scholar"
}
}
}
}
Example with credentialed providers and JCR:
{
"mcpServers": {
"paper-search": {
"command": "/absolute/path/to/paper-search-rs",
"env": {
"PAPER_SEARCH_DEFAULT_PLATFORMS": "arxiv,semantic_scholar,scopus,webofscience",
"SCOPUS_API_KEY": "your-scopus-key",
"WOS_API_KEY": "your-wos-key",
"PAPER_SEARCH_JCR_ENABLED": "true"
}
}
}
}
MCP Tools
paper_search
Always registered. If platforms is omitted, all providers listed in
PAPER_SEARCH_DEFAULT_PLATFORMS are searched.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query |
string | yes | - | Search query, 1-500 characters |
platforms |
string[] | no | enabled defaults | Target enabled providers |
max_results |
integer | no | 10 |
Result cap per provider, 1-100 |
year_from / year_to |
integer | no | - | Inclusive publication years |
sort_by |
string | no | relevance |
relevance, date, or citations |
author |
string | no | - | Normalized author filter |
journal |
string | no | - | Normalized journal/source filter |
min_citations |
integer | no | - | Minimum citation count |
min_if |
number | no | - | Minimum JCR Impact Factor |
jcr_quartile |
string | no | - | Comma-separated Q1-Q4 |
cas_quartile |
string | no | - | Comma-separated 1-4 |
ccf_rank |
string | no | - | Comma-separated A-C |
exclude_warning |
boolean | no | false |
Exclude warning-list journals |
wos_options |
object | no | - | WoS-only doi, issn, document_type, page |
Example:
{
"query": "construction safety",
"platforms": ["webofscience"],
"year_from": 2021,
"year_to": 2025,
"wos_options": {
"document_type": "Article",
"page": 1
}
}
The result envelope contains papers, failures, optional diagnostics, and an optional global
error. Partial provider failures do not discard successful results. A complete provider failure
returns the same structured envelope with MCP isError=true.
jcr_lookup
Registered only when PAPER_SEARCH_JCR_ENABLED=true. Accepts journal, issn, or both. Results
include Impact Factor, JCR rank/quartile/category, CAS fields, CCF fields, and warning status.
{
"journal": "Nature"
}
Configuration
Configuration is environment-only. Invalid values fail startup with a redacted stderr message.
Core
| Variable | Default | Description |
|---|---|---|
PAPER_SEARCH_DEFAULT_PLATFORMS |
arxiv,semantic_scholar |
Sole provider enable switch |
PAPER_SEARCH_MAX_RESULTS_PER_PLATFORM |
10 |
Common per-provider fallback cap |
PAPER_SEARCH_MAX_CONCURRENT_SEARCHES |
5 |
Fan-out concurrency limit |
PAPER_SEARCH_TIMEOUT_SECONDS |
30 |
Upstream request timeout |
PAPER_SEARCH_CACHE_MAX_SIZE |
100 |
Successful GET cache capacity |
PAPER_SEARCH_CACHE_TTL_SECONDS |
3600 |
Cache TTL |
PAPER_SEARCH_RETRY_MAX_RETRIES |
3 |
Retry count |
PAPER_SEARCH_RETRY_INITIAL_DELAY_SECONDS |
1.0 |
Initial backoff |
PAPER_SEARCH_RETRY_MAX_DELAY_SECONDS |
30.0 |
Maximum backoff/Retry-After wait |
PAPER_SEARCH_DEBUG |
false |
Include redacted provider diagnostics |
PAPER_SEARCH_DEFAULT_PLATFORMS is explicit: configuring an API key does not silently enable its
provider. Supported values are arxiv, semantic_scholar, scopus, and webofscience.
Provider settings
Per-provider overrides use PAPER_SEARCH_PLATFORM_<PLATFORM>_<FIELD>:
..._MAX_RESULTS..._RATE_LIMIT_RPS..._PROXY
Credential variables:
| Variable | Requirement |
|---|---|
SEMANTIC_SCHOLAR_API_KEY |
optional; increases available quota |
SCOPUS_API_KEY |
required when Scopus is enabled |
WOS_API_KEY |
required when Web of Science is enabled |
Proxy URLs are read from HTTP_PROXY, HTTPS_PROXY, and SOCKS_PROXY. A search provider uses the
configured proxy only when its ..._PROXY=true; native JCR updates use the global proxy settings.
JCR
| Variable | Default | Description |
|---|---|---|
PAPER_SEARCH_JCR_ENABLED |
false |
Enable enrichment, filters, and jcr_lookup |
PAPER_SEARCH_JCR_DATA_DIR |
~/.paper-search-rs/jcr |
Local data root |
PAPER_SEARCH_JCR_AUTO_UPDATE_DAYS |
7 |
Runtime revision-check interval; 0 disables auto download/check |
PAPER_SEARCH_JCR_MAX_AGE_DAYS |
30 |
Manual update freshness interval |
Manual update:
paper-search-rs update-jcr
paper-search-rs update-jcr --force
Updates fetch an exact ShowJCR revision over HTTPS, extract to a staging directory, validate the index, and atomically publish it. Existing usable data remains active if an update fails.
Development
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets --all-features
cargo build --release --locked
npm --prefix npm test
node scripts/smoke-npm-local.mjs
scripts/smoke-uvx-local.sh
Live smoke tests are opt-in. The public-provider test needs no credentials:
cargo test --test live_smoke searches_public_providers -- --ignored --nocapture
With the corresponding environment credentials loaded, run Scopus and Web of Science separately:
cargo test --test live_smoke searches_scopus_with_credentials -- --ignored --nocapture
cargo test --test live_smoke searches_web_of_science_with_credentials -- --ignored --nocapture
The ShowJCR smoke downloads into an automatically removed temporary directory:
cargo test --test live_smoke updates_and_queries_live_jcr -- --ignored --nocapture
Native Targets
aarch64-apple-darwinx86_64-apple-darwinx86_64-unknown-linux-gnuaarch64-unknown-linux-gnux86_64-pc-windows-msvc
License
Apache-2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file paper_search_rs-0.2.0-py3-none-win_amd64.whl.
File metadata
- Download URL: paper_search_rs-0.2.0-py3-none-win_amd64.whl
- Upload date:
- Size: 4.8 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1bbf09f8b36da244cecbaca014d6272d94613b38702719d2b3b2a3535b3ecac
|
|
| MD5 |
2e3d54a672b3ce419920d9914db09847
|
|
| BLAKE2b-256 |
27b9276361db56cbd52e930ad8e481551d7ee2267d008462e2b6289797745cb9
|
File details
Details for the file paper_search_rs-0.2.0-py3-none-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: paper_search_rs-0.2.0-py3-none-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 5.2 MB
- Tags: Python 3, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a766aa88fcee824e4203397d2ed7e9308586b16d85d6c2227e3c1aa3f70312e
|
|
| MD5 |
03aad41875323fe564aa2044ac0325fb
|
|
| BLAKE2b-256 |
e3f2e0f934953835beb1b3e1d092779931b2f3b9ece6f673f78e9106eb978478
|
File details
Details for the file paper_search_rs-0.2.0-py3-none-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: paper_search_rs-0.2.0-py3-none-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 4.8 MB
- Tags: Python 3, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
952d60fc9c5a9cd30919708664f6c49d0ea0a1ae1b4e8e7efc077bae15cd6fd9
|
|
| MD5 |
013cefdcb56fce3daedd3a0e82de2b7e
|
|
| BLAKE2b-256 |
0c7b5eb02ee32a92be7a5b577a9fd718f364169acf90f72ef4ab3a089de3954c
|
File details
Details for the file paper_search_rs-0.2.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: paper_search_rs-0.2.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 4.7 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b3c09da83a11267e6a7add5b76354d63474b5d1a082b0fd05710106aed35464
|
|
| MD5 |
ec3b95b0aa25ad30b7d9068c35e35f30
|
|
| BLAKE2b-256 |
85858207f7cedc047f4a44c91085611609515c1043b52db374cbbbcc2cf8dd87
|
File details
Details for the file paper_search_rs-0.2.0-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: paper_search_rs-0.2.0-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 5.0 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a34ea954f5e1863f5a58568f5516c81bee190a3d89ea1c6e3d4d4e71fd0d2107
|
|
| MD5 |
ffa8122c3e1307f9ddda0545e56e64d5
|
|
| BLAKE2b-256 |
088736ba40a91cb482a086e12945ec3e59df0ebbc027c22b951e4de714104c86
|