Skip to main content
Glama
README.md
# arxivZH MCP

把 arXiv、DOI 或论文网页链接对应的 **LaTeX 源码**批量译为简体中文,并用 XeLaTeX 编译出中文 PDF。
固定使用 DeepSeek 官方 `deepseek-flash`;多篇论文并行处理,单篇内部串行,支持术语表、结构校验、断点续跑和编译 QA。

输出固定在 `<work_dir>/arxivZH/`:

```text
<work_dir>/arxivZH/
  <arxiv_id>v<version>/    # 中文 .tex 源码、glossary.json、manifest.json、编译日志与页面预览
  PDFzh/<arxiv_id>v<version>.zh.pdf
  .jobs/<job_id>.json     # 任务记录(进度、用量、逐篇结果)
```

无 TeX 源码的论文会跳过(回退查 arXiv),**不做 PDF 文本翻译**。

## 环境要求

- **macOS**(密钥存于 macOS Keychain,其他系统需改 `arxiv_zh/network.py` 中的密钥读取)
- Python >= 3.11、[uv](https://docs.astral.sh/uv/)、网络可访问 `api.deepseek.com`
- MacTeX(ctex / Fandol 字体 / XeLaTeX / latexmk)、Poppler(pdftoppm / pdftotext)
- 一个 DeepSeek API 密钥(仅查询模型列表不收费,翻译按 token 计费)

## 安装

### 方式一:一键安装(macOS + Codex CLI)

```bash
git clone https://github.com/FjkFjkFjk314/arxiv-zh-mcp.git
cd arxiv-zh-mcp
python3 install.py
```

`install.py` 会:复制运行时到 `~/.local/share/arxiv-zh-mcp/` 并 `uv sync`;
把 skill 装到 `~/.agents/skills/arxiv-zh/`;向 Codex 注册 MCP(不改动其他 MCP 配置)。
它**不读写任何 API 密钥**。

### 方式二:手动安装(任意 MCP 客户端)

```bash
git clone https://github.com/FjkFjkFjk314/arxiv-zh-mcp.git
cd arxiv-zh-mcp
uv sync                          # 创建 .venv 并安装依赖
chmod +x run.sh setup-keychain.command
```

然后按客户端注册 stdio MCP,启动命令为仓库内的 `run.sh` 绝对路径:

- **Codex**:`codex mcp add arxiv-zh -- /绝对路径/arxiv-zh-mcp/run.sh`
- **Claude Code**:`claude mcp add arxiv-zh /绝对路径/arxiv-zh-mcp/run.sh`
- **Claude Desktop / Cursor**(JSON 配置):

```json
{
  "mcpServers": {
    "arxiv-zh": {
      "command": "/绝对路径/arxiv-zh-mcp/run.sh"
    }
  }
}
```

注册后**新开一个会话**加载工具。

### 配置 API 密钥

macOS 上双击(或终端执行)安装目录里的 `setup-keychain.command`,
在隐藏输入中粘贴 DeepSeek 密钥,保存到 Keychain 的 `arxiv-zh-deepseek / api-key` 条目。
密钥不作为 CLI/MCP 参数,不写入任何配置或日志。配置前可先跑:

```bash
.venv/bin/python cli.py status            # 本机依赖与 Keychain 检查
.venv/bin/python cli.py status --check-api  # 附加查询模型权限(不产生翻译请求)
```

## MCP 工具

| 工具 | 说明 |
|---|---|
| `arxiv_zh_status(check_api=false)` | 检查依赖与密钥配置;`check_api=true` 查模型列表,不收费 |
| `translate_papers(links, work_dir, main_tex=null)` | 提交 1–50 个链接,后台并行翻译、排队编译,返回 `job_id`。**会产生 API 费用** |
| `get_translation(work_dir, job_id)` | 查询进度、逐篇结果、PDF 路径、编译日志、页面预览;不发起翻译 |
| `resume_translation(work_dir, job_id, main_tex=null)` | 续跑失败/中断任务,复用已验证译文缓存;可能产生新费用 |

关键约定(写进给 agent 的 skill,见 `skill/arxiv-zh/SKILL.md`):

- `work_dir` 必须显式传用户当前工作目录的**绝对路径**,不能用 MCP 安装目录。
- 提交后**每 15–30 秒轮询**同一 `job_id`;不因等待或超时而重新提交。
- 完成后要实际查看返回的 `qa.previews` 页面图像;`visual_review: pending` 不算版式验收。
- 失败先读错误与日志,再对同一 `job_id` 续跑;中断块可能重复计费,不要无上限重试。

### 给其他 agent 的一句话用法

> 翻译论文:先 `arxiv_zh_status()` 确认就绪,再 `translate_papers(links=[...], work_dir="<当前工作目录绝对路径>")`,
> 保存返回的 `job_id` 并每 15–30 秒调 `get_translation()` 轮询,完成后打开返回的 PDF 路径与预览图验收。

## 并行限制

- 按 2026-09-23 [官方并发定义](https://api-docs.deepseek.com/zh-cn/quick_start/rate_limit/),`deepseek-flash` 额度为 2500 个同时在途请求(不是 RPM),本机取 60%,即 **1500**。
- 同一系统用户的所有 arxivZH 工作目录共用 API 请求槽位;API 请求完成或异常退出会释放槽位,重试退避和等待编译不占用 API 槽位。其他程序或其他电脑使用同一账号的请求不在本机控制范围内。
- 每批最多 50 篇、每篇同时最多 1 个 API 请求,所以单批实际最多 50 路;同一工作目录仍只允许一个活动任务。上限不会预先发起空请求。
- 论文术语表、译文缓存和用量彼此独立;结果保持输入顺序,`progress.papers` 提供按输入序号区分的进度,`progress.finished` 提供已结束条目数。
- PDF 编译在本机串行排队,不占 API 槽位。模型额度为经核对的固定配置;不会自动抓取网页更改上限或更换模型。

可通过 `arxiv_zh_status().concurrency` 查看当前配置。一次提交全部待译论文即可启用论文级并行,无需逐篇创建任务。链接解析按输入顺序进行,已解析论文随即进入处理;arXiv 下载继续遵守跨任务约 3 秒的请求间隔。

**实测范围(2026-09-23)**:已用已安装运行时并行翻译两份短 TeX 样例,记录到真实 DeepSeek HTTP 请求重叠;6 次生成请求均返回 HTTP 200,两份中文 PDF 均编译成功并通过页面检查。此次验证了 **2 路实际并发**,未对 50 路或 1500 路进行线上满载测试。详见 [验证记录](VERIFICATION.md)。

## 使用 Skill

`skill/arxiv-zh/` 是完整的 agent skill(SKILL.md + agents 配置),按你的 agent 的 skill 机制放置即可:

- 通用约定:`cp -R skill/arxiv-zh ~/.agents/skills/arxiv-zh`(项目级则放 `<项目>/.agents/skills/`)
- Codex / Kimi Code 等识别 `~/.agents/skills/` 的客户端放这里即可

之后对 agent 说:

> 使用 arxiv-zh 翻译 https://arxiv.org/abs/1706.03762,放到当前工作目录。

## CLI(不依赖 MCP,推荐作为兜底通道)

MCP 工具未加载时可直接用 CLI,功能等价:

```bash
.venv/bin/python cli.py status [--check-api]
.venv/bin/python cli.py translate --work-dir /绝对/工作目录 <链接...> [--main-tex 相对路径]
.venv/bin/python cli.py get --work-dir /绝对/工作目录 <job_id>
.venv/bin/python cli.py resume --work-dir /绝对/工作目录 <job_id>
```

## 测试

```bash
uv sync --dev
.venv/bin/python -m pytest -q        # 离线测试
```

包含模拟 API 的真实 XeLaTeX 编译流水线、断点续跑、公式/引用保护、恶意压缩包防护、
DOI/标题匹配歧义、论文级并行、跨进程限流、异常退出后释放槽位和 MCP stdio 握手。
2026-09-23 共 **46 项测试通过**。离线测试不证明 DeepSeek 账户或翻译质量;
真实在线验证记录见 [VERIFICATION.md](VERIFICATION.md)。

## 行为与边界

- 官方模型固定为 `deepseek-flash`,Chat Completions 非思考模式。密钥未配置或模型不可用时明确报错,不替换模型。
- 术语表先行:按论文上下文采用国内学术界通行译名,全文一致;数学、代码、作者姓名、参考文献著录、专名与图片保持原样。数学环境和图片内的英文不翻译。自定义宏作为 TeX 代码整体保护。
- 不保留英文 TeX 或原始压缩包;完成的文件原位替换为中文,`.bib/.bbl/.sty/.cls` 和图片保留,无 `original/` 副本。
- 分块保护结构、公式、路径和引用,校验标记顺序与数值,失败最多重试一次;通过的块按内容哈希缓存,文件以哈希 + 原子写入记进度;检测到外部修改时停止覆盖。
- 网络断连不自动重复付费请求;手动续跑可能重做未确认的当前块。
- 一批最多 50 篇,论文之间并行,单篇内部的文件与分块串行;arXiv 请求跨任务间隔约 3 秒;单篇失败不阻塞其他篇;相同链接列表重复提交返回原任务。
- DOI 优先精确匹配 arXiv,标题回退要求高相似度并核对作者;歧义即跳过。普通 PDF 链接只尝试文献元数据解析,不做 PDF 文本翻译。
- 解包拒绝路径穿越、符号链接和超限文件;编译禁用 shell escape 与用户 latexmkrc,限制 TeX 文件读写。仍应使用可信论文源;本工具不是通用 TeX 沙箱。
- 成功 PDF 必须通过中文文本、缺字、未解析引用检查,并生成页面预览与溢出警告。

## 参考

- [DeepSeek Chat Completions](https://api-docs.deepseek.com/zh-cn/api/create-chat-completion/)
- [arXiv API](https://info.arxiv.org/help/api/user-manual.html)
- [Model Context Protocol](https://modelcontextprotocol.io/)

## 许可

MIT,见 [LICENSE](LICENSE)。