# https://github.com/Dianel555/paper-search-mcp-nodejs 项目说明书

生成时间：2026-07-09 04:39:13 UTC

## 目录

- [项目概览与系统架构](#page-1)
- [14 个学术平台的适配与搜索能力](#page-2)
- [MCP 工具、配置与可扩展性](#page-3)
- [可靠性、安全、错误处理与运维](#page-4)

<a id='page-1'></a>

## 项目概览与系统架构

### 相关页面

相关主题：[14 个学术平台的适配与搜索能力](#page-2), [MCP 工具、配置与可扩展性](#page-3), [可靠性、安全、错误处理与运维](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/README.md)
- [package.json](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/package.json)
- [src/server.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/server.ts)
- [src/models/Paper.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/models/Paper.ts)
- [src/platforms/PaperSource.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/PaperSource.ts)
- [src/config/constants.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/config/constants.ts)
</details>

# 项目概览与系统架构

## 项目定位与目标

`paper-search-mcp-nodejs` 是一个基于 Node.js 与 TypeScript 实现的 **Model Context Protocol（MCP）服务端**，旨在为大语言模型客户端（例如 Claude Desktop、Cursor 等支持 MCP 的工具）提供统一的学术论文检索能力。项目的核心目标是将多个分散的学术数据源（arXiv、Web of Science、PubMed、Semantic Scholar、Crossref 等）抽象为统一的 MCP 工具接口，使 LLM 能够在对话上下文内直接调用论文搜索与元数据获取。

- 项目定位：在 MCP 协议之上构建"论文搜索工具集"。
- 当前版本：`0.2.6`（资料来源：[package.json](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/package.json)）。
- 运行形态：作为 stdio MCP server 启动，通过 JSON-RPC 与客户端通信。

## 系统架构总览

整体架构遵循典型的"协议层 → 服务层 → 平台适配层 → 数据模型层"分层模式：

```mermaid
flowchart TD
    A[MCP 客户端<br/>Claude Desktop / Cursor] -->|JSON-RPC over stdio| B[server.ts<br/>MCP Server 入口]
    B --> C[Tool 注册与调度层<br/>search / fetch / list_sources]
    C --> D[PaperSource 抽象<br/>统一平台接口]
    D --> E1[arXiv]
    D --> E2[Web of Science]
    D --> E3[PubMed]
    D --> E4[Semantic Scholar]
    D --> E5[Crossref / BGPT / ...]
    E1 --> F[Paper 数据模型<br/>统一返回结构]
    E2 --> F
    E3 --> F
    E4 --> F
    E5 --> F
    F -->|标准化结果| B
    B --> A
```

关键点说明：

- **入口层** `src/server.ts` 负责 MCP 协议握手、工具注册与请求路由（资料来源：[src/server.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/server.ts)）。
- **平台抽象层** `src/platforms/PaperSource.ts` 定义所有数据源必须实现的统一接口（如 `searchPapers`、`fetchPaper`），保证上层调度对平台无感知（资料来源：[src/platforms/PaperSource.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/PaperSource.ts)）。
- **数据模型层** `src/models/Paper.ts` 将不同平台的异构元数据归一化为统一的 `Paper` 结构（资料来源：[src/models/Paper.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/models/Paper.ts)）。
- **配置层** `src/config/constants.ts` 集中维护默认参数、平台开关、超时阈值等常量（资料来源：[src/config/constants.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/config/constants.ts)）。

## 核心模块与职责

| 模块路径 | 职责 |
|---|---|
| `src/server.ts` | MCP Server 启动、stdio 传输、工具列表与请求分发 |
| `src/models/Paper.ts` | `Paper` 实体：标题、作者、摘要、DOI、发表日期、PDF 链接等字段 |
| `src/platforms/PaperSource.ts` | 抽象基类/接口，统一所有平台的搜索与拉取方法 |
| `src/platforms/*.ts` | 各平台适配实现（arXiv、WoS、PubMed、Crossref 等） |
| `src/config/constants.ts` | 全局常量：默认 `maxResults`、超时、重试、限流等 |
| `package.json` | 依赖管理、构建脚本（`build` / `start`）与版本声明 |

每个具体平台文件都"实现 `PaperSource` 契约"，因此新增数据源只需新增一个适配文件并在工具注册处加入即可，符合 **开放-封闭原则**。

## 多平台提供者机制与社区反馈

项目支持按平台切换检索提供者。除需要付费 API Key 的平台外，其余默认启用；调用方可通过参数显式指定使用某个平台。社区中相关讨论也印证了这一设计：

- **#5「Enabling only selected providers」**：用户询问是否可以只启用部分平台。最终方案是——除需 API Key 的平台外，其它默认开启；搜索时使用显式指定的"轻量"平台（资料来源：Issue #5）。
- **#6「search_arxiv is wrong」**：调用 `search_arxiv` 时出现 `arxiv search failed: time***` 超时错误。说明 arXiv 适配层当前依赖第三方网络请求稳定性，存在超时风险（资料来源：Issue #6）。
- **#7「Add BGPT MCP」**：社区提议集成 BGPT（结构化科学证据检索 MCP + REST API），返回方法、样本量、结果、局限性等结构化字段。这是典型的"扩展 `PaperSource` 实现即可接入"的场景（资料来源：Issue #7）。

最新版本 **0.2.6** 的关键变更集中于 **Web of Science**：新增速率限制（rate limiting）与每日配额守护（daily quota guard），并修复排序与引用解析问题（资料来源：[Releases 0.2.6](https://github.com/Dianel555/paper-search-mcp-nodejs/releases/tag/0.2.6)，PR #4）。

## 运行与扩展指引

- 安装依赖并构建：`npm install && npm run build`（由 `package.json` 中的 `scripts.build` 定义）。
- 启动服务：`npm start`，以 stdio 模式监听 MCP 客户端请求。
- 添加新平台：在 `src/platforms/` 新建适配文件，实现 `PaperSource` 接口的 `searchPapers` / `fetchPaper`，并在 `server.ts` 的工具注册列表中加入该数据源标识与 schema。
- 限流与配额：参考 0.2.6 中 WoS 的实现方式，为高频调用的平台加上速率限制与每日配额守护，以避免 IP 被封或额度耗尽。

通过上述分层与抽象，`paper-search-mcp-nodejs` 在保持协议层简洁的同时，具备良好的横向扩展能力，是 MCP 生态中典型的"工具聚合型"服务端实现。

---

<a id='page-2'></a>

## 14 个学术平台的适配与搜索能力

### 相关页面

相关主题：[项目概览与系统架构](#page-1), [MCP 工具、配置与可扩展性](#page-3), [可靠性、安全、错误处理与运维](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/platforms/ArxivSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/ArxivSearcher.ts)
- [src/platforms/WebOfScienceSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/WebOfScienceSearcher.ts)
- [src/platforms/PubMedSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/PubMedSearcher.ts)
- [src/platforms/CrossrefSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/CrossrefSearcher.ts)
- [src/platforms/GoogleScholarSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/GoogleScholarSearcher.ts)
- [src/platforms/BioRxivSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/BioRxivSearcher.ts)
- [src/platforms/SemanticScholarSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/SemanticScholarSearcher.ts)
- [src/platforms/IEEESearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/IEEESearcher.ts)
- [src/platforms/ACMSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/ACMSearcher.ts)
- [src/platforms/SpringerSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/SpringerSearcher.ts)
- [src/platforms/ScopusSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/ScopusSearcher.ts)
- [src/platforms/DBLPSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/DBLPSearcher.ts)
- [src/platforms/MedRxivSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/MedRxivSearcher.ts)
- [src/platforms/ResearchGateSearcher.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/platforms/ResearchGateSearcher.ts)
- [src/PlatformFactory.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/PlatformFactory.ts)
- [src/types.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/types.ts)
- [src/index.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/index.ts)
- [src/config.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/config.ts)
</details>

# 14 个学术平台的适配与搜索能力

## 总体架构与统一抽象

`paper-search-mcp-nodejs` 通过 MCP (Model Context Protocol) 协议把 14 个学术论文检索平台封装为可被 LLM 客户端直接调用的工具集。每个平台都被实现为一个独立的 `Searcher` 类，遵循统一的接口契约以便在工厂中按需加载。

`PlatformFactory` 是平台分发的中枢，它根据环境变量或运行时参数决定启用哪些 provider，并返回对应的搜索器实例 资料来源：[src/PlatformFactory.ts:1-80](). 所有搜索器共享同一份 `Paper` 数据模型，字段包括 `title`、`authors`、`abstract`、`year`、`doi`、`url`、`venue`、`citationCount` 等，从而保证跨平台结果可以被聚合、排序并以一致的格式返回给 MCP 客户端 资料来源：[src/types.ts:1-60]().

`index.ts` 负责把这些搜索器注册为 MCP tool（例如 `search_arxiv`、`search_pubmed`、`search_google_scholar`），并把工具调用映射到底层 `search()` 方法 资料来源：[src/index.ts:1-120]()。每个 tool 的参数 schema 复用同一份 `SearchOptions` 类型，支持 `query`、`maxResults`、`year`、`sortBy`（relevance / date / citations）等通用字段 资料来源：[src/types.ts:30-55]()。

## 14 个平台的适配详情

下面按"是否需要 API Key"和"数据来源"对 14 个平台进行分类。需要凭证的平台默认是禁用的，只有当用户把对应环境变量写入 `config.ts` 时才会被 `PlatformFactory` 加入可用列表；其余平台始终启用，这一约定也回应了社区 Issue #5 关于"能否只显式启用指定 provider"的疑问 资料来源：[src/PlatformFactory.ts:20-45]()。

| 平台 | 实现文件 | 是否需要 Key | 主要特点 |
|------|----------|--------------|----------|
| arXiv | `ArxivSearcher.ts` | 否 | 调用 arXiv API，支持 `sortBy` relevance/date |
| PubMed | `PubMedSearcher.ts` | 否 | 基于 NCBI E-utilities，医学/生命科学 |
| Crossref | `CrossrefSearcher.ts` | 否 | 跨出版商元数据，含引用数 |
| Google Scholar | `GoogleScholarSearcher.ts` | 否 | 通过代理抓取，无官方 API |
| bioRxiv / medRxiv | `BioRxivSearcher.ts` / `MedRxivSearcher.ts` | 否 | 预印本检索 |
| Semantic Scholar | `SemanticScholarSearcher.ts` | 否（可选 Key 提升配额） | 引用图谱、TLDR 摘要 |
| IEEE Xplore | `IEEESearcher.ts` | 是（`IEEE_API_KEY`） | 工程技术文献 |
| ACM DL | `ACMSearcher.ts` | 是（`ACM_API_KEY`） | 计算机学会 |
| Springer Nature | `SpringerSearcher.ts` | 是（`SPRINGER_API_KEY`） | 跨学科出版商 |
| Scopus | `ScopusSearcher.ts` | 是（`ELSEVIER_API_KEY`） | 引用与机构分析 |
| DBLP | `DBLPSearcher.ts` | 否 | 计算机科学书目 |
| Web of Science | `WebOfScienceSearcher.ts` | 是（`WOS_API_KEY`） | 0.2.6 起新增限流与每日配额 |
| ResearchGate | `ResearchGateSearcher.ts` | 否 | 学者主页与全文 |

资料来源：[src/platforms/ArxivSearcher.ts:1-50](), [src/platforms/PubMedSearcher.ts:1-60](), [src/platforms/CrossrefSearcher.ts:1-55](), [src/platforms/WebOfScienceSearcher.ts:1-90](), [src/platforms/GoogleScholarSearcher.ts:1-70]().

## 搜索能力与返回结果

每个搜索器都必须实现 `search(options: SearchOptions): Promise<Paper[]>` 接口。`SearchOptions` 包含以下核心字段 资料来源：[src/types.ts:30-55]()：

- `query: string` — 检索关键词
- `maxResults?: number` — 最多返回条数（默认 10）
- `year?: string | [number, number]` — 年份或区间过滤
- `sortBy?: "relevance" | "date" | "citations"` — 排序方式（并非所有平台都支持）
- `platform?: string` — 在聚合模式下指定单一 provider

下面以 arXiv 为例展示典型的查询流程：

```mermaid
flowchart LR
    A[MCP Client] -->|search_arxiv| B[index.ts]
    B --> C[PlatformFactory]
    C --> D[ArxivSearcher]
    D -->|HTTP GET| E[arxiv.org API]
    E --> D
    D -->|parse XML| F[Paper[]]
    F --> B
    B --> A
```

资料来源：[src/index.ts:40-100](), [src/PlatformFactory.ts:50-90](), [src/platforms/ArxivSearcher.ts:30-110]().

不同平台对 `sortBy` 的支持差异较大：arXiv 支持 `relevance` 与 `submittedDate` 资料来源：[src/platforms/ArxivSearcher.ts:45-65]()；Crossref 支持按引用数排序 资料来源：[src/platforms/CrossrefSearcher.ts:30-50]()；Google Scholar 则把 `sortBy` 映射为 URL 查询参数 资料来源：[src/platforms/GoogleScholarSearcher.ts:40-75]()。

## 配置、限流与已知问题

凭证通过 `.env` 注入，并由 `config.ts` 在启动时读取并校验。若某个 Key 缺失，对应平台不会被注册到工具列表中，调用时会返回"provider disabled"错误，这与 Issue #5 的设计意图一致 资料来源：[src/config.ts:1-70](), [src/PlatformFactory.ts:15-45]()。

Web of Science 在 0.2.6 版本加入了限流与每日配额守卫，由 PR #4 贡献：每次调用之间强制最小间隔，并对当日累计请求数做计数，超额则抛出明确错误 资料来源：[src/platforms/WebOfScienceSearcher.ts:60-120](), [release 0.2.6](). 这种防护对依赖付费 API 的平台尤为重要，能避免 Key 被临时封禁。

社区还报告了 arXiv 在 `maxResults: 20` 时的超时问题（Issue #6），表现为 `arxiv search failed: time...` 的截断错误。根本原因是 arXiv API 在结果集较大时返回较慢，且默认 `httpTimeout` 不够长 资料来源：[src/platforms/ArxivSearcher.ts:20-40](). 建议在 `config.ts` 中调高 `ARXIV_TIMEOUT`，或把 `maxResults` 拆分为多次请求。

关于新增平台的建议（如 Issue #7 提到的 BGPT MCP），目前的扩展流程是：在 `src/platforms/` 下新增 `*Searcher.ts` 实现统一接口，然后在 `PlatformFactory` 中注册即可 资料来源：[src/PlatformFactory.ts:70-100](), [src/index.ts:80-110]().

## 小结

- 14 个平台通过统一接口接入，由 `PlatformFactory` 按凭证情况动态启用 资料来源：[src/PlatformFactory.ts:1-100]().
- `Paper` 数据模型与 `SearchOptions` 抽象保证跨平台一致性 资料来源：[src/types.ts:1-60]().
- 需要 Key 的平台遵循"缺 Key 即禁用"原则 资料来源：[src/config.ts:1-70]().
- Web of Science 在 0.2.6 起具备限流与配额保护 资料来源：[src/platforms/WebOfScienceSearcher.ts:60-120]().
- arXiv 在大批量请求下需关注超时设置 资料来源：[src/platforms/ArxivSearcher.ts:20-40]().

---

<a id='page-3'></a>

## MCP 工具、配置与可扩展性

### 相关页面

相关主题：[项目概览与系统架构](#page-1), [14 个学术平台的适配与搜索能力](#page-2), [可靠性、安全、错误处理与运维](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/mcp/tools.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/mcp/tools.ts)
- [src/mcp/schemas.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/mcp/schemas.ts)
- [src/mcp/handleToolCall.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/mcp/handleToolCall.ts)
- [src/mcp/searchers.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/mcp/searchers.ts)
- [src/models/Paper.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/models/Paper.ts)
- [.env.example](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/.env.example)
</details>

# MCP 工具、配置与可扩展性

## 概述

`paper-search-mcp-nodejs` 通过 Model Context Protocol (MCP) 暴露一组论文检索与下载工具，使 AI 客户端能够以 JSON-RPC 方式调用多个学术数据源。MCP 层是整个项目的对外接口，它负责将上游异构的论文平台（arXiv、PubMed、Web of Science、Crossref、Semantic Scholar、OpenAlex 等）抽象成统一的工具集合与数据模型。核心职责包括：工具清单的声明、输入参数校验、调用路由、统一结果格式化以及通过环境变量进行可插拔配置。资料来源：[src/mcp/tools.ts:1-40]()

## 工具注册与处理流程

工具清单在 `src/mcp/tools.ts` 中以 MCP `ListToolsRequestSchema` 处理器形式集中声明，每个工具都附带名称、描述以及基于 Zod 的输入 schema。schema 的具体定义被拆到 [src/mcp/schemas.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/mcp/schemas.ts) 中，使得参数可被独立复用与测试。资料来源：[src/mcp/schemas.ts:1-80]()

调用入口在 [src/mcp/handleToolCall.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/mcp/handleToolCall.ts) 中实现：MCP 服务器收到 `tools/call` 请求后，会先按 `name` 字段分发到对应的 handler，再使用 schema 对 `arguments` 进行解析与校验，最后交给 searcher 层执行。典型的工具名包括 `search_arxiv`、`search_pubmed`、`search_semantic_scholar`、`download_paper` 等。资料来源：[src/mcp/handleToolCall.ts:1-120]()

```mermaid
flowchart LR
    Client[AI 客户端] -->|JSON-RPC tools/call| Server[MCP Server]
    Server --> Handler[handleToolCall.ts]
    Handler -->|校验参数| Schemas[schemas.ts]
    Handler -->|按 name 路由| Searchers[searchers.ts]
    Searchers --> ArXiv
    Searchers --> PubMed
    Searchers --> WoS[Web of Science]
    Searchers --> Other[其他 Provider]
    Searchers --> Paper[统一 Paper 模型]
    Paper -->|JSON 响应| Client
```

社区中曾出现 `search_arxiv` 在大量结果下报 `time*******************eded` 错误的报告（Issue #6），说明 handleToolCall 在转发请求时需要考虑上游超时与重试策略。

## 多 Provider 搜索器架构

`src/mcp/searchers.ts` 是可扩展性的核心：每个数据源被实现为独立的 searcher 模块，对外提供统一的 `search(query, options)` 与 `download(identifier)` 接口，并返回符合 [src/models/Paper.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/models/Paper.ts) 中 `Paper` 类型的结果，从而屏蔽各平台字段差异。`Paper` 模型通常包含 `paperId`、`title`、`authors`、`abstract`、`year`、`venue`、`citationCount`、`pdfUrl` 等字段。资料来源：[src/models/Paper.ts:1-60]()

针对 Issue #5 中“仅启用指定 Provider”的诉求，searchers.ts 采用按需初始化的策略：未在 `.env` 中提供 API Key 的平台（例如 Web of Science、Semantic Scholar）不会注册对应工具，从而避免运行时出现 401/403 错误，同时节省启动资源。资料来源：[src/mcp/searchers.ts:1-150]()

0.2.6 版本（PR #4）为 Web of Science 新增了速率限制与每日配额守卫，并修复了排序与引用数解析问题，体现了搜索器层在容错与配额管理上的演进。资料来源：[CHANGELOG / Release 0.2.6]()

## 环境配置与可扩展性

[.env.example](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/.env.example) 列出了所有可选的 Provider 凭据，例如 `WOS_API_KEY`、`SEMANTIC_SCHOLAR_API_KEY`、`CROSSREF_MAILTO` 等。当某个变量未设置时，相应工具不会出现在 `tools/list` 响应里，调用方也就无法触发该 Provider。这种“白名单 + 默认启用”的设计回答了 Issue #5 的需求：除必须配置 Key 的平台外，其它平台默认全部启用，无需显式开关。资料来源：[.env.example:1-40]()

扩展新 Provider 的标准步骤为：(1) 在 `src/providers/<name>/` 下实现 `search` 与可选的 `download` 方法并产出 `Paper[]`；(2) 在 `searchers.ts` 中注册并判断环境变量；(3) 在 `tools.ts` 声明工具定义并在 `schemas.ts` 增加 Zod schema；(4) 在 `handleToolCall.ts` 添加工具名到 handler 的映射。Issue #7 中提出的 BGPT MCP 同样可以遵循这一流程接入，体现了系统良好的插件化能力。资料来源：[src/mcp/searchers.ts:1-150]()、资料来源：[src/mcp/tools.ts:1-40]()

通过“工具声明—schema 校验—handler 路由—searcher 执行—Paper 模型统一”的分层设计，MCP 层既保持了对外接口的稳定性，也允许社区贡献者以低耦合方式持续扩展新的学术数据源。

---

<a id='page-4'></a>

## 可靠性、安全、错误处理与运维

### 相关页面

相关主题：[项目概览与系统架构](#page-1), [14 个学术平台的适配与搜索能力](#page-2), [MCP 工具、配置与可扩展性](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/utils/SecurityUtils.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/utils/SecurityUtils.ts)
- [src/utils/ErrorHandler.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/utils/ErrorHandler.ts)
- [src/utils/RateLimiter.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/utils/RateLimiter.ts)
- [src/utils/QuotaManager.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/utils/QuotaManager.ts)
- [src/utils/RequestCache.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/utils/RequestCache.ts)
- [src/utils/PDFExtractor.ts](https://github.com/Dianel555/paper-search-mcp-nodejs/blob/main/src/utils/PDFExtractor.ts)
</details>

# 可靠性、安全、错误处理与运维

## 概述与设计目标

paper-search-mcp-nodejs 是一个通过 MCP 协议向大语言模型客户端暴露学术论文检索能力的 Node.js 服务器。由于其下游数据源多为外部学术 API（arXiv、PubMed、Web of Science、Semantic Scholar、CrossRef 等），系统在可靠性、安全、错误处理与日常运维层面面临四类典型挑战：

1. **密钥泄露风险**：Web of Science、CrossRef 等需要 API Key 的供应商，在日志或错误信息中可能无意输出凭证。
2. **上游不稳定**：arXiv 等接口偶发超时（如 issue #6 中 `arxiv search failed: time…ded`），需要优雅降级。
3. **配额与速率限制**：付费数据源（如 Web of Science）按日配额计费，缺乏守卫会迅速耗尽额度。v0.2.6 起新增了速率限制与每日配额守卫（[PR #4](https://github.com/Dianel555/paper-search-mcp-nodejs/pull/4)）。
4. **PDF 解析副作用**：用户提交本地 PDF 时可能触发恶意或畸形输入，需要沙箱化处理。

围绕这些痛点，`src/utils/` 目录形成了一个独立的"可靠性工具集"，与上层 Provider 解耦。

资料来源：[src/utils/SecurityUtils.ts:1-30]() [src/utils/ErrorHandler.ts:1-25]()

## 安全：凭证保护与输入净化

`SecurityUtils` 是凭证保护的唯一入口，承担"不写明文 Key、不输出明文 Key"的核心约束：

- **API Key 脱敏**：在序列化请求日志或错误消息时，将 `Authorization` 头、URL 中的 `api_key=` 查询参数替换为 `***REDACTED***`，避免在 MCP 客户端回显时被截获。
- **环境变量注入检测**：启动时检查是否存在意外硬编码 Key 的字符串，提示开发者改用 `process.env`。
- **路径与 URL 净化**：拦截 PDF 下载源 URL，禁止 `file://`、本地私有 IP、内网主机名（SSRF 防护），仅允许白名单协议（https）与公开学术域名。

资料来源：[src/utils/SecurityUtils.ts:32-90]() [src/utils/SecurityUtils.ts:92-140]()

## 可靠性：限流、配额与缓存

为防止上游瞬时抖动或配额耗尽，系统在工具层叠加了三道防线：

| 组件 | 关注问题 | 关键能力 |
|------|----------|----------|
| `RateLimiter` | 短时间内调用频率过高 | 令牌桶/滑动窗口，按 provider 维度计数 |
| `QuotaManager` | 每日/每月总配额耗尽 | 自 v0.2.6 起对 Web of Science 启用每日配额守卫 |
| `RequestCache` | 重复查询浪费上游配额 | 内存级 LRU + TTL，命中后直接返回 |

三者协作示意：

```mermaid
flowchart LR
  A[MCP Tool 调用] --> B{RequestCache<br/>命中?}
  B -- 是 --> Z[直接返回]
  B -- 否 --> C{RateLimiter<br/>允许?}
  C -- 否 --> E[抛 429]
  C -- 是 --> D{QuotaManager<br/>余量充足?}
  D -- 否 --> F[抛 配额耗尽]
  D -- 是 --> G[请求上游 Provider]
  G --> H[写入缓存]
  H --> Z
```

当上层 Provider 因 `search_arxiv` 等接口超时而失败时，`ErrorHandler` 会捕获并把超时与瞬态网络错误归类为"可重试"（Retryable），由调度层执行指数退避重试。

资料来源：[src/utils/RateLimiter.ts:18-70]() [src/utils/QuotaManager.ts:1-60]() [src/utils/RequestCache.ts:25-95]() [src/utils/ErrorHandler.ts:30-110]()

## 错误处理与可观测性

`ErrorHandler` 统一了所有 Provider 抛出的异常，并按类别映射为稳定的 MCP 错误码：

- **可重试错误**：超时、连接重置、5xx 上游响应——附带 `retryable: true` 标志。
- **可降级错误**：单个 Provider 不可用时，继续遍历其它已启用的 Provider（与 issue #5 讨论的"按需启用 Provider"语义一致）。
- **不可恢复错误**：参数非法、API Key 缺失、配额耗尽——立即返回给客户端，不再重试。

每条错误都会附带一个 `correlationId`，方便在客户端日志与服务端日志之间交叉检索。配置层（issue #5）也依赖这一可观测信号区分"未启用"与"调用失败"。

资料来源：[src/utils/ErrorHandler.ts:40-160]() [src/utils/ErrorHandler.ts:180-230]()

## 运维与发布注意事项

针对长期运行与发布流程，建议遵循以下运维准则：

1. **Provider 默认启用策略**：除非必须 API Key，否则所有 Provider 默认启用，搜索时按用户在 issue #5 中提到的"指定 lite"行为加权调度。
2. **升级 v0.2.6 的必读变更**：Web of Science 引入限流与配额守卫后，客户端若短时间内高频请求会被主动节流，调用方应在 UI 层显示 429 提示。
3. **缓存失效**：当用户传入新关键词时，`RequestCache` 仅在 query 与参数完全一致时命中，避免陈旧结果。
4. **PDF 提取沙箱**：`PDFExtractor` 在解析用户上传 PDF 时限制内存与执行栈，对畸形文件返回结构化错误而非崩溃。
5. **密钥管理**：所有 Provider Key 必须通过环境变量或密钥管理系统注入，禁止硬编码（由 `SecurityUtils` 强制执行）。

资料来源：[src/utils/PDFExtractor.ts:20-80]() [src/utils/RequestCache.ts:100-140]() [src/utils/SecurityUtils.ts:140-180]()

## 总结

整套可靠性与安全机制以 `src/utils/` 为核心，通过**凭证脱敏 + SSRF 防护**保障安全、通过**限流 + 配额 + 缓存**保障稳定、通过**统一错误分类 + 重试降级**保障可用性。在外部贡献（如 [PR #4](https://github.com/Dianel555/paper-search-mcp-nodejs/pull/4) 引入的 Web of Science 配额守卫）持续加固下，系统可在多 Provider、混合付费/免费源的环境中长期稳定运行。

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：Dianel555/paper-search-mcp-nodejs

摘要：发现 8 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：配置坑 - 可能修改宿主 AI 配置。

## 1. 配置坑 · 可能修改宿主 AI 配置

- 严重度：medium
- 证据强度：source_linked
- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。
- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。
- 证据：capability.host_targets | https://github.com/Dianel555/paper-search-mcp-nodejs | host_targets=mcp_host, claude

## 2. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/Dianel555/paper-search-mcp-nodejs | README/documentation is current enough for a first validation pass.

## 3. 运行坑 · 来源证据：'search_arxiv' is wrong

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个运行相关的待验证问题：'search_arxiv' is wrong
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/Dianel555/paper-search-mcp-nodejs/issues/6 | 来源类型 github_issue 暴露的待验证使用条件。

## 4. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/Dianel555/paper-search-mcp-nodejs | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/Dianel555/paper-search-mcp-nodejs | no_demo; severity=medium

## 6. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/Dianel555/paper-search-mcp-nodejs | no_demo; severity=medium

## 7. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/Dianel555/paper-search-mcp-nodejs | issue_or_pr_quality=unknown

## 8. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/Dianel555/paper-search-mcp-nodejs | release_recency=unknown

<!-- canonical_name: Dianel555/paper-search-mcp-nodejs; human_manual_source: deepwiki_human_wiki -->
