apaper-mcp 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,137 @@
1
+ name: Release and Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ tag:
10
+ description: "Tag to publish (e.g. v0.2.1)"
11
+ required: true
12
+ type: string
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ jobs:
18
+ build:
19
+ runs-on: ubuntu-latest
20
+
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+ with:
24
+ ref: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref }}
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@v6
28
+ with:
29
+ enable-cache: true
30
+
31
+ - name: Set up Python
32
+ uses: actions/setup-python@v5
33
+ with:
34
+ python-version: "3.12"
35
+
36
+ - name: Resolve tag name
37
+ id: tag
38
+ run: |
39
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
40
+ echo "tag_name=${{ github.event.inputs.tag }}" >> "$GITHUB_OUTPUT"
41
+ else
42
+ echo "tag_name=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
43
+ fi
44
+
45
+ - name: Verify project version matches tag
46
+ run: |
47
+ PROJECT_VERSION=$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
48
+ TAG_NAME="${{ steps.tag.outputs.tag_name }}"
49
+ EXPECTED_TAG="v${PROJECT_VERSION}"
50
+
51
+ if [ "$TAG_NAME" != "$EXPECTED_TAG" ]; then
52
+ echo "Tag ${TAG_NAME} does not match project version ${PROJECT_VERSION}"
53
+ exit 1
54
+ fi
55
+
56
+ - name: Run tests
57
+ run: uv run pytest
58
+
59
+ - name: Build package
60
+ run: uv build
61
+
62
+ - name: Upload package artifacts
63
+ uses: actions/upload-artifact@v4
64
+ with:
65
+ name: python-package
66
+ path: dist/*
67
+
68
+ publish:
69
+ needs: build
70
+ runs-on: ubuntu-latest
71
+ permissions:
72
+ contents: read
73
+ id-token: write
74
+
75
+ steps:
76
+ - name: Download package artifacts
77
+ uses: actions/download-artifact@v4
78
+ with:
79
+ name: python-package
80
+ path: dist/
81
+
82
+ - name: Publish package to PyPI
83
+ uses: pypa/gh-action-pypi-publish@release/v1
84
+ with:
85
+ packages-dir: dist/
86
+
87
+ create-release:
88
+ needs: publish
89
+ runs-on: ubuntu-latest
90
+ permissions:
91
+ contents: write
92
+
93
+ steps:
94
+ - uses: actions/checkout@v4
95
+ with:
96
+ ref: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref }}
97
+
98
+ - name: Download package artifacts
99
+ uses: actions/download-artifact@v4
100
+ with:
101
+ name: python-package
102
+ path: dist/
103
+
104
+ - name: Resolve tag name
105
+ id: tag
106
+ run: |
107
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
108
+ echo "tag_name=${{ github.event.inputs.tag }}" >> "$GITHUB_OUTPUT"
109
+ else
110
+ echo "tag_name=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
111
+ fi
112
+
113
+ - name: Extract release notes from changelog
114
+ run: |
115
+ TAG_NAME="${{ steps.tag.outputs.tag_name }}"
116
+ VERSION="${TAG_NAME#v}"
117
+
118
+ awk -v version="$VERSION" '
119
+ $0 ~ "^## \\[" version "\\]" { in_section = 1; next }
120
+ in_section && /^## \[/ { exit }
121
+ in_section { print }
122
+ ' CHANGELOG.md > RELEASE_NOTES.md
123
+
124
+ if [ ! -s RELEASE_NOTES.md ]; then
125
+ echo "Release notes for ${TAG_NAME} were not found in CHANGELOG.md" > RELEASE_NOTES.md
126
+ fi
127
+
128
+ - name: Create GitHub Release
129
+ uses: softprops/action-gh-release@v2
130
+ with:
131
+ tag_name: ${{ steps.tag.outputs.tag_name }}
132
+ name: Release ${{ steps.tag.outputs.tag_name }}
133
+ draft: false
134
+ prerelease: false
135
+ body_path: RELEASE_NOTES.md
136
+ files: |
137
+ dist/*
@@ -0,0 +1,10 @@
1
+ .DS_Store
2
+ node_modules/
3
+ *.log
4
+ .idea/
5
+ .vscode/
6
+ __pycache__/
7
+ .pytest_cache/
8
+ .venv/
9
+ /downloads
10
+ /.claude/worktrees
@@ -0,0 +1,85 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on Keep a Changelog, and this project follows Semantic Versioning.
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.3.0] - 2026-07-28
10
+
11
+ ### Added
12
+
13
+ - Python 3.12+ package with `uv` project management and an `apaper-mcp` console entry point. (@isomoes)
14
+ - PyPI publishing workflow with GitHub Actions Trusted Publishing support. (@isomoes)
15
+ - MIT license and complete package metadata for distribution on PyPI. (@isomoes)
16
+
17
+ ### Removed
18
+
19
+ - Legacy TypeScript, Bun, and npm implementation and release artifacts. (@isomoes)
20
+
21
+ ## [0.2.0] - 2026-06-26
22
+
23
+ ### Added
24
+
25
+ - `SPIDER_PROXY` env var routes outbound requests (arXiv, IACR, DBLP, Google Scholar, and PDF downloads) through a proxy. CNKI is excluded because it authenticates by institutional IP. Accepts `socks5`/`socks4`/`http`/`https` URLs in both the standard `scheme://user:pass@host:port` form and the colon-delimited `scheme://host:port:user:pass` form (e.g. Kookeey), on both the Node and Bun runtimes (under Bun, SOCKS is tunnelled via a local HTTP→SOCKS bridge). Idempotent requests are retried on transient proxy connection failures, and if the proxy is set but invalid or can't be initialised, requests are blocked rather than sent direct so the real IP never leaks. (#2, @isomoes)
26
+ - IACR per-request timeouts are configurable via `IACR_TIMEOUT_MS` (default `30000`) and `IACR_DOWNLOAD_TIMEOUT_MS` (default `60000`), raised from the previous fixed 15s/30s to tolerate slow proxies. (#2, @isomoes)
27
+
28
+ ### Fixed
29
+
30
+ - IACR requests now detect Cloudflare's bot challenge (which intermittently blocks downloads/searches) and report it with an actionable message and the URL to open in a browser, instead of an opaque `HTTP 403` — and never save a challenge HTML page as a `.pdf`. Requests also send browser-like headers (full User-Agent, `Accept`, `Referer`). (#2, @isomoes)
31
+
32
+ ## [0.1.5] - 2026-06-08
33
+
34
+ ### Added
35
+
36
+ - arXiv requests are throttled and retried on HTTP 429 / 5xx with exponential backoff honouring `Retry-After`; a persistent block reports the throttled IP and wait time. Tunable via `ARXIV_MIN_INTERVAL_MS`, `ARXIV_MAX_RETRIES`, `ARXIV_BACKOFF_BASE_MS`, `ARXIV_BACKOFF_MAX_MS`, `ARXIV_BACKOFF_JITTER_MS`, and `ARXIV_IP_ECHO_URL`. (#1, @isomoes)
37
+
38
+ ### Fixed
39
+
40
+ - arXiv tools no longer fail on the first HTTP 429, and the search tool description no longer claims rate-limiting that was not implemented. (#1, @isomoes)
41
+
42
+ ## [0.1.4] - 2026-05-17
43
+
44
+ ### Added
45
+
46
+ - arXiv search support via the `search_arxiv_papers` tool, with category, date-range, and sort options. (@isomoes)
47
+ - arXiv PDF download support via the `download_arxiv_paper` tool. (@isomoes)
48
+ - `ARXIV_SEARCH_URL`, `ARXIV_ADVANCED_URL`, and `ARXIV_PDF_BASE` env overrides for routing arXiv traffic through a reachable mirror. (@isomoes)
49
+
50
+ ### Changed
51
+
52
+ - arXiv search scrapes the `arxiv.org/search/` HTML page instead of `export.arxiv.org/api/query` so it works on networks where the Atom API endpoint is blocked or aggressively rate-limited. (@isomoes)
53
+
54
+ ## [0.1.3] - 2026-05-16
55
+
56
+ ### Added
57
+
58
+ - CNKI (中国知网) search support via the `search_cnki_papers` tool. (@isomoes)
59
+ - CNKI PDF download support via the `download_cnki_paper` tool. (@isomoes)
60
+ - Automatic IP-based CNKI session login on whitelisted institutional networks; no manual cookie management required. (@isomoes)
61
+
62
+ ## [0.1.2] - 2026-03-26
63
+
64
+ ### Added
65
+
66
+ - Test release to verify tag-triggered GitHub Actions publishing now that the workflow is active. (@isomoes)
67
+
68
+ ## [0.1.1] - 2026-03-26
69
+
70
+ ### Added
71
+
72
+ - npm packaging for `@ai4paper/apaper-mcp`, including the `apaper-mcp` CLI entrypoint. (@isomoes)
73
+ - Tag-driven GitHub Actions release publishing and changelog-backed release notes. (@isomoes)
74
+ - README updates covering npm installation and local release verification workflow. (@isomoes)
75
+
76
+ ## [0.1.0] - 2026-03-26
77
+
78
+ ### Added
79
+
80
+ - Initial Bun + TypeScript MCP server for academic paper research. (@isomoes)
81
+ - IACR ePrint search support with optional detail fetching and year filters. (@isomoes)
82
+ - IACR PDF download support. (@isomoes)
83
+ - DBLP search support with year filtering, venue filtering, and optional BibTeX output. (@isomoes)
84
+ - Google Scholar search support with year filtering. (@isomoes)
85
+ - Text formatters for MCP tool responses and stdio server startup entrypoint. (@isomoes)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 isomoes
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,176 @@
1
+ Metadata-Version: 2.4
2
+ Name: apaper-mcp
3
+ Version: 0.3.0
4
+ Summary: Academic paper research MCP server
5
+ Project-URL: Homepage, https://github.com/ai4paper/apaper-mcp
6
+ Project-URL: Repository, https://github.com/ai4paper/apaper-mcp
7
+ Project-URL: Issues, https://github.com/ai4paper/apaper-mcp/issues
8
+ Author: isomoes
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: academic research,mcp,papers
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
17
+ Requires-Python: >=3.12
18
+ Requires-Dist: beautifulsoup4>=4.12
19
+ Requires-Dist: httpx[socks]>=0.27
20
+ Requires-Dist: mcp>=1.12
21
+ Description-Content-Type: text/markdown
22
+
23
+ # apaper-mcp
24
+
25
+ An MCP (Model Context Protocol) server that gives AI assistants direct access to academic paper databases. It exposes a unified set of tools for searching and downloading papers across arXiv, IACR ePrint, DBLP, Google Scholar, and CNKI (中国知网), so an MCP-compatible client (Claude Code, Claude Desktop, or any other) can run literature searches, pull BibTeX entries, and fetch PDFs without leaving the chat.
26
+
27
+ ## Tools
28
+
29
+ | Tool | Source | Description |
30
+ | --- | --- | --- |
31
+ | `search_arxiv_papers` | arXiv | Search with category, date-range, and sort options |
32
+ | `download_arxiv_paper` | arXiv | Download a PDF |
33
+ | `search_iacr_papers` | IACR ePrint | Search the ePrint archive |
34
+ | `download_iacr_paper` | IACR ePrint | Download a PDF |
35
+ | `search_dblp_papers` | DBLP | Search, optionally with BibTeX |
36
+ | `search_google_scholar_papers` | Google Scholar | Search |
37
+ | `search_cnki_papers` | CNKI (中国知网) | Search |
38
+ | `download_cnki_paper` | CNKI (中国知网) | Download a PDF |
39
+
40
+ arXiv tools scrape the public `arxiv.org/search/` HTML page, which works on
41
+ networks where the `export.arxiv.org` Atom API is blocked or rate-limited. If
42
+ you need to route through a mirror, set `ARXIV_SEARCH_URL`,
43
+ `ARXIV_ADVANCED_URL`, and/or `ARXIV_PDF_BASE`.
44
+
45
+ The arXiv tools throttle themselves and retry HTTP 429 / 5xx with exponential
46
+ backoff, honouring `Retry-After`; on a persistent block the error names the
47
+ throttled IP and wait time. Tune with `ARXIV_MIN_INTERVAL_MS` (`3000`),
48
+ `ARXIV_MAX_RETRIES` (`3`), `ARXIV_BACKOFF_BASE_MS` (`3000`),
49
+ `ARXIV_BACKOFF_MAX_MS` (`60000`), `ARXIV_BACKOFF_JITTER_MS` (`500`), and
50
+ `ARXIV_IP_ECHO_URL` (`""` to disable the IP lookup).
51
+
52
+ CNKI tools require institutional access. On IP-based networks the session
53
+ cookie is obtained automatically on first use — no manual login needed.
54
+
55
+ IACR ePrint sits behind Cloudflare, which intermittently serves a JS bot
56
+ challenge that automated HTTP clients can't solve — most often on PDF downloads.
57
+ Search keeps working; when a download is challenged the tool reports it clearly
58
+ (rather than saving the challenge page) and gives you the URL to fetch in a
59
+ browser. This is server-side and unrelated to any proxy.
60
+
61
+ ## Proxy
62
+
63
+ Set `SPIDER_PROXY` to route outbound requests — arXiv, IACR, DBLP, Google
64
+ Scholar, and their PDF downloads — through a proxy. CNKI is excluded on purpose:
65
+ it authenticates by institutional IP and always uses this host's real address.
66
+ Both a standard URL and the colon-delimited form some mobile-proxy providers
67
+ hand out are accepted:
68
+
69
+ ```bash
70
+ SPIDER_PROXY="socks5://user:pass@host:1086" # standard
71
+ SPIDER_PROXY="socks5://host:1086:user:pass" # host:port:user:pass (e.g. Kookeey)
72
+ SPIDER_PROXY="http://user:pass@host:8080" # HTTP CONNECT proxy
73
+ ```
74
+
75
+ `socks5`, `socks4`, `http`, and `https` schemes are supported (the scheme
76
+ defaults to `http` when omitted) by the Python runtime. The scheme must match
77
+ the proxy's port — a SOCKS port won't accept `http://` and vice versa. If
78
+ `SPIDER_PROXY` is set but invalid or can't be initialised, requests are blocked
79
+ rather than sent direct, so a misconfigured proxy never leaks this host's real
80
+ IP.
81
+
82
+ Flaky residential/mobile proxies routinely drop or refuse connections;
83
+ idempotent (GET) requests through the proxy are retried automatically on such
84
+ transient failures. IACR fires the most requests per search (a detail fetch per
85
+ result), so its per-request timeouts default high for slow proxies — tune with
86
+ `IACR_TIMEOUT_MS` (`30000`) and `IACR_DOWNLOAD_TIMEOUT_MS` (`60000`).
87
+
88
+ ## Install from PyPI
89
+
90
+ The maintained runtime requires Python 3.12+. Run the published package
91
+ directly with `uvx`:
92
+
93
+ ```bash
94
+ uvx apaper-mcp
95
+ ```
96
+
97
+ To install the command for repeated use:
98
+
99
+ ```bash
100
+ uv tool install apaper-mcp
101
+ apaper-mcp
102
+ ```
103
+
104
+ For an MCP client, use the published package as the local stdio command:
105
+
106
+ ```json
107
+ {
108
+ "mcp": {
109
+ "apaper-mcp": {
110
+ "type": "local",
111
+ "command": ["uvx", "apaper-mcp"],
112
+ "enabled": true
113
+ }
114
+ }
115
+ }
116
+ ```
117
+
118
+ ## Development
119
+
120
+ Clone the repository and install its development dependencies with `uv`:
121
+
122
+ ```bash
123
+ uv sync
124
+ uv run apaper-mcp
125
+ ```
126
+
127
+ Run tests with `uv run pytest`.
128
+
129
+ The Python source uses a standard `src` package layout. Platform-specific
130
+ clients live under `src/apaper_mcp/platforms/`, while shared server, proxy,
131
+ formatter, and model code stays in `src/apaper_mcp/`.
132
+
133
+ ### Local MCP testing
134
+
135
+ Start the MCP Inspector against the Python stdio server:
136
+
137
+ ```bash
138
+ npx @modelcontextprotocol/inspector uv run --directory . apaper-mcp
139
+ ```
140
+
141
+ The equivalent module command is:
142
+
143
+ ```bash
144
+ npx @modelcontextprotocol/inspector \
145
+ uv run --directory . python -m apaper_mcp
146
+ ```
147
+
148
+ To pass the proxy to the inspected server:
149
+
150
+ ```bash
151
+ npx @modelcontextprotocol/inspector \
152
+ -e SPIDER_PROXY="$SPIDER_PROXY" \
153
+ uv run --directory . apaper-mcp
154
+ ```
155
+
156
+ The Inspector opens a local web UI for listing tools, inspecting schemas, and
157
+ calling tools.
158
+
159
+ ### Tool schemas
160
+
161
+ - `search_arxiv_papers`
162
+ - input: `{ "query": string, "max_results"?: number, "date_from"?: string, "date_to"?: string, "categories"?: string[], "sort_by"?: "relevance" | "date" }`
163
+ - `download_arxiv_paper`
164
+ - input: `{ "paper_id": string, "save_path"?: string }` (paper_id like `2103.12345` or `2103.12345v2`)
165
+ - `search_iacr_papers`
166
+ - input: `{ "query": string, "max_results"?: number, "fetch_details"?: boolean, "year_min"?: number | string, "year_max"?: number | string }`
167
+ - `download_iacr_paper`
168
+ - input: `{ "paper_id": string, "save_path"?: string }`
169
+ - `search_dblp_papers`
170
+ - input: `{ "query": string, "max_results"?: number, "year_from"?: number | string, "year_to"?: number | string, "venue_filter"?: string, "include_bibtex"?: boolean }`
171
+ - `search_google_scholar_papers`
172
+ - input: `{ "query": string, "max_results"?: number, "year_low"?: number | string, "year_high"?: number | string }`
173
+ - `search_cnki_papers`
174
+ - input: `{ "query": string, "page_num"?: number, "page_size"?: number }`
175
+ - `download_cnki_paper`
176
+ - input: `{ "href": string, "save_path"?: string }` (use an `href` from `search_cnki_papers`)
@@ -0,0 +1,154 @@
1
+ # apaper-mcp
2
+
3
+ An MCP (Model Context Protocol) server that gives AI assistants direct access to academic paper databases. It exposes a unified set of tools for searching and downloading papers across arXiv, IACR ePrint, DBLP, Google Scholar, and CNKI (中国知网), so an MCP-compatible client (Claude Code, Claude Desktop, or any other) can run literature searches, pull BibTeX entries, and fetch PDFs without leaving the chat.
4
+
5
+ ## Tools
6
+
7
+ | Tool | Source | Description |
8
+ | --- | --- | --- |
9
+ | `search_arxiv_papers` | arXiv | Search with category, date-range, and sort options |
10
+ | `download_arxiv_paper` | arXiv | Download a PDF |
11
+ | `search_iacr_papers` | IACR ePrint | Search the ePrint archive |
12
+ | `download_iacr_paper` | IACR ePrint | Download a PDF |
13
+ | `search_dblp_papers` | DBLP | Search, optionally with BibTeX |
14
+ | `search_google_scholar_papers` | Google Scholar | Search |
15
+ | `search_cnki_papers` | CNKI (中国知网) | Search |
16
+ | `download_cnki_paper` | CNKI (中国知网) | Download a PDF |
17
+
18
+ arXiv tools scrape the public `arxiv.org/search/` HTML page, which works on
19
+ networks where the `export.arxiv.org` Atom API is blocked or rate-limited. If
20
+ you need to route through a mirror, set `ARXIV_SEARCH_URL`,
21
+ `ARXIV_ADVANCED_URL`, and/or `ARXIV_PDF_BASE`.
22
+
23
+ The arXiv tools throttle themselves and retry HTTP 429 / 5xx with exponential
24
+ backoff, honouring `Retry-After`; on a persistent block the error names the
25
+ throttled IP and wait time. Tune with `ARXIV_MIN_INTERVAL_MS` (`3000`),
26
+ `ARXIV_MAX_RETRIES` (`3`), `ARXIV_BACKOFF_BASE_MS` (`3000`),
27
+ `ARXIV_BACKOFF_MAX_MS` (`60000`), `ARXIV_BACKOFF_JITTER_MS` (`500`), and
28
+ `ARXIV_IP_ECHO_URL` (`""` to disable the IP lookup).
29
+
30
+ CNKI tools require institutional access. On IP-based networks the session
31
+ cookie is obtained automatically on first use — no manual login needed.
32
+
33
+ IACR ePrint sits behind Cloudflare, which intermittently serves a JS bot
34
+ challenge that automated HTTP clients can't solve — most often on PDF downloads.
35
+ Search keeps working; when a download is challenged the tool reports it clearly
36
+ (rather than saving the challenge page) and gives you the URL to fetch in a
37
+ browser. This is server-side and unrelated to any proxy.
38
+
39
+ ## Proxy
40
+
41
+ Set `SPIDER_PROXY` to route outbound requests — arXiv, IACR, DBLP, Google
42
+ Scholar, and their PDF downloads — through a proxy. CNKI is excluded on purpose:
43
+ it authenticates by institutional IP and always uses this host's real address.
44
+ Both a standard URL and the colon-delimited form some mobile-proxy providers
45
+ hand out are accepted:
46
+
47
+ ```bash
48
+ SPIDER_PROXY="socks5://user:pass@host:1086" # standard
49
+ SPIDER_PROXY="socks5://host:1086:user:pass" # host:port:user:pass (e.g. Kookeey)
50
+ SPIDER_PROXY="http://user:pass@host:8080" # HTTP CONNECT proxy
51
+ ```
52
+
53
+ `socks5`, `socks4`, `http`, and `https` schemes are supported (the scheme
54
+ defaults to `http` when omitted) by the Python runtime. The scheme must match
55
+ the proxy's port — a SOCKS port won't accept `http://` and vice versa. If
56
+ `SPIDER_PROXY` is set but invalid or can't be initialised, requests are blocked
57
+ rather than sent direct, so a misconfigured proxy never leaks this host's real
58
+ IP.
59
+
60
+ Flaky residential/mobile proxies routinely drop or refuse connections;
61
+ idempotent (GET) requests through the proxy are retried automatically on such
62
+ transient failures. IACR fires the most requests per search (a detail fetch per
63
+ result), so its per-request timeouts default high for slow proxies — tune with
64
+ `IACR_TIMEOUT_MS` (`30000`) and `IACR_DOWNLOAD_TIMEOUT_MS` (`60000`).
65
+
66
+ ## Install from PyPI
67
+
68
+ The maintained runtime requires Python 3.12+. Run the published package
69
+ directly with `uvx`:
70
+
71
+ ```bash
72
+ uvx apaper-mcp
73
+ ```
74
+
75
+ To install the command for repeated use:
76
+
77
+ ```bash
78
+ uv tool install apaper-mcp
79
+ apaper-mcp
80
+ ```
81
+
82
+ For an MCP client, use the published package as the local stdio command:
83
+
84
+ ```json
85
+ {
86
+ "mcp": {
87
+ "apaper-mcp": {
88
+ "type": "local",
89
+ "command": ["uvx", "apaper-mcp"],
90
+ "enabled": true
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## Development
97
+
98
+ Clone the repository and install its development dependencies with `uv`:
99
+
100
+ ```bash
101
+ uv sync
102
+ uv run apaper-mcp
103
+ ```
104
+
105
+ Run tests with `uv run pytest`.
106
+
107
+ The Python source uses a standard `src` package layout. Platform-specific
108
+ clients live under `src/apaper_mcp/platforms/`, while shared server, proxy,
109
+ formatter, and model code stays in `src/apaper_mcp/`.
110
+
111
+ ### Local MCP testing
112
+
113
+ Start the MCP Inspector against the Python stdio server:
114
+
115
+ ```bash
116
+ npx @modelcontextprotocol/inspector uv run --directory . apaper-mcp
117
+ ```
118
+
119
+ The equivalent module command is:
120
+
121
+ ```bash
122
+ npx @modelcontextprotocol/inspector \
123
+ uv run --directory . python -m apaper_mcp
124
+ ```
125
+
126
+ To pass the proxy to the inspected server:
127
+
128
+ ```bash
129
+ npx @modelcontextprotocol/inspector \
130
+ -e SPIDER_PROXY="$SPIDER_PROXY" \
131
+ uv run --directory . apaper-mcp
132
+ ```
133
+
134
+ The Inspector opens a local web UI for listing tools, inspecting schemas, and
135
+ calling tools.
136
+
137
+ ### Tool schemas
138
+
139
+ - `search_arxiv_papers`
140
+ - input: `{ "query": string, "max_results"?: number, "date_from"?: string, "date_to"?: string, "categories"?: string[], "sort_by"?: "relevance" | "date" }`
141
+ - `download_arxiv_paper`
142
+ - input: `{ "paper_id": string, "save_path"?: string }` (paper_id like `2103.12345` or `2103.12345v2`)
143
+ - `search_iacr_papers`
144
+ - input: `{ "query": string, "max_results"?: number, "fetch_details"?: boolean, "year_min"?: number | string, "year_max"?: number | string }`
145
+ - `download_iacr_paper`
146
+ - input: `{ "paper_id": string, "save_path"?: string }`
147
+ - `search_dblp_papers`
148
+ - input: `{ "query": string, "max_results"?: number, "year_from"?: number | string, "year_to"?: number | string, "venue_filter"?: string, "include_bibtex"?: boolean }`
149
+ - `search_google_scholar_papers`
150
+ - input: `{ "query": string, "max_results"?: number, "year_low"?: number | string, "year_high"?: number | string }`
151
+ - `search_cnki_papers`
152
+ - input: `{ "query": string, "page_num"?: number, "page_size"?: number }`
153
+ - `download_cnki_paper`
154
+ - input: `{ "href": string, "save_path"?: string }` (use an `href` from `search_cnki_papers`)
@@ -0,0 +1,83 @@
1
+ # Introducing apaper-mcp
2
+
3
+ `apaper-mcp` is an MCP server for one very practical job: supporting paper work inside the conversation. Today that starts with paper discovery, but the larger direction is a more complete academic writing server where an AI client can search literature, collect references, organize source material, and assist with drafting around the same workflow. Instead of wiring separate scripts to different research sites, this project packages focused research tools behind a single Model Context Protocol interface.
4
+
5
+ The project is built with **Python** and the official **Model Context Protocol SDK**. It runs over stdio, which makes it easy to plug into MCP-compatible clients and local inspection tools. The current implementation supports **arXiv**, **IACR ePrint**, **DBLP**, **Google Scholar**, and **CNKI**.
6
+
7
+ ## Why this project exists
8
+
9
+ Research and writing workflows often break into too many manual steps. You search one index for cryptography preprints, another for publication metadata, and another for broad citation discovery, then move that material into notes, citations, and draft sections. `apaper-mcp` narrows that gap by turning the research side of that process into MCP tools that an assistant can call directly.
10
+
11
+ That design is especially useful when the goal is not just to find one paper, but to support iterative paper-writing tasks such as:
12
+
13
+ - narrowing a topic by year range
14
+ - comparing results across multiple sources
15
+ - pulling BibTeX-ready metadata from DBLP
16
+ - downloading an IACR PDF for closer reading
17
+ - building a cleaner literature base before outlining or drafting
18
+
19
+ ## What the server exposes
20
+
21
+ At the moment, the server registers four tools:
22
+
23
+ - `search_iacr_papers` for querying the IACR ePrint archive, with optional detail fetching and year filters
24
+ - `download_iacr_paper` for saving an IACR paper PDF locally
25
+ - `search_dblp_papers` for publication lookup in DBLP, including venue filtering and optional BibTeX output
26
+ - `search_google_scholar_papers` for broader paper discovery through Google Scholar with year bounds
27
+
28
+ Each tool returns formatted text responses so MCP clients can display results cleanly without extra response shaping. That keeps the server simple while still making it useful in real workflows.
29
+
30
+ ## Using it in an MCP client
31
+
32
+ One simple local configuration looks like this:
33
+
34
+ ```json
35
+ {
36
+ "mcp": {
37
+ "apaper-mcp": {
38
+ "type": "local",
39
+ "command": ["uv", "run", "--directory", "/path/to/apaper-mcp", "apaper-mcp"],
40
+ "enabled": true
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ With that setup, an MCP-compatible client can start the server locally and call its tools during a research session.
47
+
48
+ ## Example use cases
49
+
50
+ In practice, that means an assistant can use `apaper-mcp` to:
51
+
52
+ - search papers on a topic across multiple sources
53
+ - collect metadata and BibTeX for references
54
+ - download an IACR paper for closer reading
55
+ - prepare source material before outlining or drafting a paper
56
+
57
+ ## How it is put together
58
+
59
+ The codebase keeps the implementation intentionally direct. The MCP entrypoint lives in `src/apaper_mcp/server.py`, where each tool is registered with the Python MCP SDK. Platform-specific fetching and parsing live in separate modules under `src/apaper_mcp/`, which keeps the transport layer and the scraping/API logic from bleeding into each other.
60
+
61
+ That split also reflects the nature of the supported sources:
62
+
63
+ - **IACR** and **Google Scholar** are handled by fetching and parsing HTML
64
+ - **DBLP** uses its JSON API and can optionally fetch BibTeX records
65
+
66
+ This is not trying to be a full academic knowledge graph or a large orchestration framework. It is a compact MCP server with a clear surface area, aimed at making paper search easier to automate and easier to integrate into AI-assisted research and writing sessions.
67
+
68
+ ## Future directions
69
+
70
+ Today, `apaper-mcp` focuses on search and retrieval. The next step is to extend it into a more complete paper-writing server.
71
+
72
+ - reference management tools for collecting, deduplicating, and exporting citations across sources
73
+ - PDF processing tools for extracting metadata, section text, figures, or notes from downloaded papers
74
+ - literature review helpers for clustering papers by topic, method, or publication venue
75
+ - outlining and drafting support for turning research notes into section plans, related-work summaries, or first-pass prose
76
+ - revision tools for checking consistency between claims, citations, and bibliography entries
77
+ - submission-oriented utilities for format checks, metadata cleanup, and venue-specific packaging
78
+
79
+ Those additions would move the project from paper search into a broader research-writing workspace.
80
+
81
+ ## Closing thought
82
+
83
+ `apaper-mcp` is a focused example of what MCP is good at: exposing useful capabilities in a form that AI clients can call reliably. Right now, that means less context switching, less glue code, and a cleaner path from a research question to a usable set of papers. With the right extensions, it can grow into a practical MCP server for the full paper-writing workflow rather than only the search stage.