openalex-mcp-server 1.0.1
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.
- package/.claude/README.md +680 -0
- package/.claude/commands/prd.md +138 -0
- package/.claude/commands/ralph-yolo.md +346 -0
- package/.claude/commands/ralph.md +226 -0
- package/.claude/ralph-config.json +17 -0
- package/.claude/scripts/prompt.md +108 -0
- package/.claude/scripts/ralph.sh +127 -0
- package/.claude/skills/prd.md +270 -0
- package/.claude/skills/ralph-yolo.md +613 -0
- package/.claude/skills/ralph.md +315 -0
- package/.claude/templates/prd.json.example +64 -0
- package/.env.example +8 -0
- package/.github/workflows/npm-publish.yml +48 -0
- package/README.md +525 -0
- package/config/mcp-config.json +77 -0
- package/docs/PRD.md +897 -0
- package/docs/api-document.md +973 -0
- package/docs/document-mcp.txt +1 -0
- package/package.json +49 -0
- package/prd-progress.txt +66 -0
- package/src/cache-manager.js +204 -0
- package/src/cli.js +47 -0
- package/src/fulltext-downloader.js +333 -0
- package/src/index.js +603 -0
- package/src/json-optimizer.js +153 -0
- package/src/openalex-client.js +305 -0
- package/src/types/pdf-parse.d.ts +13 -0
- package/src/utils.js +90 -0
- package/tests/cli.test.js +31 -0
- package/tsconfig.json +22 -0
package/docs/PRD.md
ADDED
|
@@ -0,0 +1,897 @@
|
|
|
1
|
+
# OpenAlex MCP Server - 产品需求文档 (PRD)
|
|
2
|
+
|
|
3
|
+
**版本**: 1.0
|
|
4
|
+
**日期**: 2026-01-25
|
|
5
|
+
**作者**: AI编程助手架构师
|
|
6
|
+
**状态**: 待开发
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 📋 目录
|
|
11
|
+
|
|
12
|
+
1. [项目概述](#项目概述)
|
|
13
|
+
2. [需求分析](#需求分析)
|
|
14
|
+
3. [功能需求](#功能需求)
|
|
15
|
+
4. [技术架构](#技术架构)
|
|
16
|
+
5. [API设计](#api设计)
|
|
17
|
+
6. [数据模型](#数据模型)
|
|
18
|
+
7. [性能优化](#性能优化)
|
|
19
|
+
8. [部署方案](#部署方案)
|
|
20
|
+
9. [开发计划](#开发计划)
|
|
21
|
+
10. [风险评估](#风险评估)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 1. 项目概述
|
|
26
|
+
|
|
27
|
+
### 1.1 项目背景
|
|
28
|
+
|
|
29
|
+
OpenAlex 是一个完全开放的全球研究系统目录,包含超过 2.4 亿篇学术文献。相比 PubMed,OpenAlex 具有以下优势:
|
|
30
|
+
|
|
31
|
+
- **更快的响应速度**:现代化的 REST API,响应时间通常在 200ms 以内
|
|
32
|
+
- **开放获取支持**:可以直接下载 OA 论文全文
|
|
33
|
+
- **更丰富的元数据**:包含引用关系、主题分类、机构信息等
|
|
34
|
+
- **免费且无限制**:每天 100,000 credits(免费 API Key)
|
|
35
|
+
|
|
36
|
+
### 1.2 项目目标
|
|
37
|
+
|
|
38
|
+
构建一个轻量化的 OpenAlex MCP 服务器,与现有的 PubMed MCP 服务器配合使用,为 AI Agent 提供:
|
|
39
|
+
|
|
40
|
+
1. **快速的文章检索能力**(快速模式)
|
|
41
|
+
2. **详细的摘要信息**(深度模式)
|
|
42
|
+
3. **全文下载与内容缓存**(深度专家模式)
|
|
43
|
+
4. **优化的 JSON 输出格式**,提升上下文利用效率
|
|
44
|
+
5. **多 Agent 协作支持**,便于扩展
|
|
45
|
+
|
|
46
|
+
### 1.3 核心价值
|
|
47
|
+
|
|
48
|
+
- **互补性**:与 PubMed MCP 配合,覆盖更全面的学术资源
|
|
49
|
+
- **高效性**:利用 OpenAlex 的快速 API,提升检索速度
|
|
50
|
+
- **智能化**:基于全文内容的 QA 增强,提供深度分析能力
|
|
51
|
+
- **轻量化**:前端语言实现,易于部署和维护
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 2. 需求分析
|
|
56
|
+
|
|
57
|
+
### 2.1 用户场景
|
|
58
|
+
|
|
59
|
+
#### 场景 1:快速文献检索
|
|
60
|
+
```
|
|
61
|
+
用户:帮我找一下关于"CRISPR基因编辑"的最新论文
|
|
62
|
+
AI Agent → OpenAlex MCP (快速模式) → 返回论文列表
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
#### 场景 2:深度信息获取
|
|
66
|
+
```
|
|
67
|
+
用户:这篇论文的主要发现是什么?
|
|
68
|
+
AI Agent → OpenAlex MCP (深度模式) → 返回详细摘要和关键信息
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### 场景 3:全文分析与QA增强
|
|
72
|
+
```
|
|
73
|
+
用户:这篇论文的实验方法是什么?
|
|
74
|
+
AI Agent → OpenAlex MCP (深度专家模式) → 下载全文 → 提取相关内容 → 回答
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### 场景 4:多源数据对比
|
|
78
|
+
```
|
|
79
|
+
用户:比较 PubMed 和 OpenAlex 中关于某个主题的论文
|
|
80
|
+
AI Agent → PubMed MCP + OpenAlex MCP → 对比分析
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 2.2 功能优先级
|
|
84
|
+
|
|
85
|
+
| 功能 | 优先级 | 说明 |
|
|
86
|
+
|------|--------|------|
|
|
87
|
+
| 文章检索(快速模式) | P0 | 核心功能,必须实现 |
|
|
88
|
+
| 摘要信息(深度模式) | P0 | 核心功能,必须实现 |
|
|
89
|
+
| 全文下载与缓存 | P1 | 重要功能,提升深度分析能力 |
|
|
90
|
+
| JSON格式优化 | P1 | 提升上下文利用效率 |
|
|
91
|
+
| 多Agent协作支持 | P2 | 便于扩展和集成 |
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 3. 功能需求
|
|
96
|
+
|
|
97
|
+
### 3.1 功能 1:文章检索(快速模式)
|
|
98
|
+
|
|
99
|
+
#### 3.1.1 功能描述
|
|
100
|
+
提供快速的文章检索能力,返回论文的基本信息列表,适合快速浏览和筛选。
|
|
101
|
+
|
|
102
|
+
#### 3.1.2 输入参数
|
|
103
|
+
```typescript
|
|
104
|
+
{
|
|
105
|
+
query: string; // 搜索关键词(支持 OpenAlex 查询语法)
|
|
106
|
+
max_results?: number; // 最大返回结果数(默认:20,最大:200)
|
|
107
|
+
filters?: { // 过滤条件
|
|
108
|
+
publication_year?: number | string; // 年份或范围,如 2020, "2020-2023", ">2020"
|
|
109
|
+
is_oa?: boolean; // 是否开放获取
|
|
110
|
+
type?: string; // 类型:article, book, dataset 等
|
|
111
|
+
topics?: string[]; // 主题ID列表
|
|
112
|
+
institutions?: string[]; // 机构ID列表
|
|
113
|
+
authors?: string[]; // 作者ID列表
|
|
114
|
+
};
|
|
115
|
+
sort_by?: string; // 排序:cited_by_count:desc, publication_date:desc 等
|
|
116
|
+
page?: number; // 分页(默认:1)
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### 3.1.3 输出格式(优化后)
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"meta": {
|
|
124
|
+
"total_count": 15234,
|
|
125
|
+
"page": 1,
|
|
126
|
+
"per_page": 20,
|
|
127
|
+
"query_time_ms": 42
|
|
128
|
+
},
|
|
129
|
+
"papers": [
|
|
130
|
+
{
|
|
131
|
+
"id": "W2741809807",
|
|
132
|
+
"title": "论文标题",
|
|
133
|
+
"authors": ["作者1", "作者2"],
|
|
134
|
+
"year": 2023,
|
|
135
|
+
"venue": "期刊名称",
|
|
136
|
+
"cited_by_count": 45,
|
|
137
|
+
"is_oa": true,
|
|
138
|
+
"doi": "10.1234/example",
|
|
139
|
+
"openalex_url": "https://openalex.org/W2741809807"
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
#### 3.1.4 实现要点
|
|
146
|
+
- 使用 `per-page=200` 获取最大页面大小,减少 API 调用
|
|
147
|
+
- 使用 `select` 参数只获取必要字段,提升响应速度
|
|
148
|
+
- 实现请求缓存,避免重复查询
|
|
149
|
+
- 支持批量 DOI/PMID 查询(使用 OR 过滤器)
|
|
150
|
+
|
|
151
|
+
### 3.2 功能 2:摘要信息(深度模式)
|
|
152
|
+
|
|
153
|
+
#### 3.2.1 功能描述
|
|
154
|
+
获取论文的详细信息,包括完整摘要、作者信息、关键词、主题分类等,适合深度分析。
|
|
155
|
+
|
|
156
|
+
#### 3.2.2 输入参数
|
|
157
|
+
```typescript
|
|
158
|
+
{
|
|
159
|
+
work_id: string; // OpenAlex Work ID 或 DOI/PMID
|
|
160
|
+
include_abstract?: boolean; // 是否包含摘要(默认:true)
|
|
161
|
+
include_authors?: boolean; // 是否包含作者详情(默认:true)
|
|
162
|
+
include_topics?: boolean; // 是否包含主题分类(默认:true)
|
|
163
|
+
include_references?: boolean; // 是否包含引用关系(默认:false)
|
|
164
|
+
abstract_mode?: "quick" | "deep"; // 摘要模式(默认:deep)
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### 3.2.3 输出格式(优化后)
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"id": "W2741809807",
|
|
172
|
+
"title": "论文标题",
|
|
173
|
+
"abstract": "完整摘要内容...",
|
|
174
|
+
"abstract_summary": {
|
|
175
|
+
"key_points": ["要点1", "要点2", "要点3"],
|
|
176
|
+
"keywords": ["关键词1", "关键词2"],
|
|
177
|
+
"length": 1200
|
|
178
|
+
},
|
|
179
|
+
"authors": [
|
|
180
|
+
{
|
|
181
|
+
"name": "作者姓名",
|
|
182
|
+
"institution": "机构名称",
|
|
183
|
+
"orcid": "0000-0000-0000-0000"
|
|
184
|
+
}
|
|
185
|
+
],
|
|
186
|
+
"metadata": {
|
|
187
|
+
"publication_date": "2023-01-15",
|
|
188
|
+
"venue": "期刊名称",
|
|
189
|
+
"type": "journal-article",
|
|
190
|
+
"language": "en",
|
|
191
|
+
"cited_by_count": 45,
|
|
192
|
+
"is_oa": true
|
|
193
|
+
},
|
|
194
|
+
"topics": [
|
|
195
|
+
{
|
|
196
|
+
"id": "T12345",
|
|
197
|
+
"name": "主题名称",
|
|
198
|
+
"level": 1
|
|
199
|
+
}
|
|
200
|
+
],
|
|
201
|
+
"open_access": {
|
|
202
|
+
"is_oa": true,
|
|
203
|
+
"oa_status": "gold",
|
|
204
|
+
"oa_url": "https://example.com/paper.pdf"
|
|
205
|
+
},
|
|
206
|
+
"identifiers": {
|
|
207
|
+
"doi": "10.1234/example",
|
|
208
|
+
"pmid": "12345678",
|
|
209
|
+
"mag": "1234567890"
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### 3.2.4 实现要点
|
|
215
|
+
- 支持通过 DOI、PMID、OpenAlex ID 等多种方式查询
|
|
216
|
+
- 实现摘要智能截断(quick: 1500字符,deep: 6000字符)
|
|
217
|
+
- 提取关键点和关键词,便于 LLM 理解
|
|
218
|
+
- 结构化输出,去除冗余信息
|
|
219
|
+
|
|
220
|
+
### 3.3 功能 3:全文下载与论文内容缓存(深度专家模式)
|
|
221
|
+
|
|
222
|
+
#### 3.3.1 功能描述
|
|
223
|
+
检测并下载开放获取论文的全文,建立本地缓存,支持基于全文内容的 QA 增强。
|
|
224
|
+
|
|
225
|
+
#### 3.3.2 输入参数
|
|
226
|
+
```typescript
|
|
227
|
+
{
|
|
228
|
+
work_id: string; // OpenAlex Work ID
|
|
229
|
+
auto_download?: boolean; // 是否自动下载(默认:false)
|
|
230
|
+
force_download?: boolean; // 是否强制重新下载(默认:false)
|
|
231
|
+
extract_sections?: string[]; // 提取的章节:abstract, introduction, methods, results, discussion
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
#### 3.3.3 输出格式
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"work_id": "W2741809807",
|
|
239
|
+
"fulltext_status": "available",
|
|
240
|
+
"oa_url": "https://example.com/paper.pdf",
|
|
241
|
+
"cache_status": "cached",
|
|
242
|
+
"cache_path": "./cache/fulltext/W2741809807.pdf",
|
|
243
|
+
"file_size": 2048576,
|
|
244
|
+
"cached_at": "2026-01-25T10:30:00Z",
|
|
245
|
+
"extracted_sections": {
|
|
246
|
+
"abstract": "摘要内容...",
|
|
247
|
+
"introduction": "引言内容...",
|
|
248
|
+
"methods": "方法内容...",
|
|
249
|
+
"results": "结果内容...",
|
|
250
|
+
"discussion": "讨论内容..."
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### 3.3.4 实现要点
|
|
256
|
+
- 检测 OpenAlex 返回的 `open_access.oa_url` 字段
|
|
257
|
+
- 支持 PDF 下载和文本提取(使用 pdf-parse 或类似库)
|
|
258
|
+
- 实现智能缓存机制,避免重复下载
|
|
259
|
+
- 提取论文关键章节,便于 QA 增强
|
|
260
|
+
- 支持批量下载(带速率限制)
|
|
261
|
+
|
|
262
|
+
#### 3.3.5 缓存策略
|
|
263
|
+
```
|
|
264
|
+
cache/
|
|
265
|
+
├── fulltext/
|
|
266
|
+
│ ├── W2741809807.pdf # PDF 文件
|
|
267
|
+
│ ├── W2741809807.txt # 提取的文本
|
|
268
|
+
│ ├── W2741809807_sections.json # 章节提取结果
|
|
269
|
+
│ └── index.json # 缓存索引
|
|
270
|
+
└── papers/
|
|
271
|
+
└── W2741809807.json # 论文元数据缓存
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### 3.4 功能 4:返回请求头 JSON 格式的线性优化
|
|
275
|
+
|
|
276
|
+
#### 3.4.1 功能描述
|
|
277
|
+
优化返回的 JSON 格式,去除冗余信息,只保留对 LLM 有用的论文内容,提升上下文利用效率。
|
|
278
|
+
|
|
279
|
+
#### 3.4.2 优化策略
|
|
280
|
+
|
|
281
|
+
**原始 OpenAlex 响应示例:**
|
|
282
|
+
```json
|
|
283
|
+
{
|
|
284
|
+
"id": "https://openalex.org/W2741809807",
|
|
285
|
+
"doi": "https://doi.org/10.1234/example",
|
|
286
|
+
"title": "论文标题",
|
|
287
|
+
"display_name": "论文标题",
|
|
288
|
+
"publication_date": "2023-01-15",
|
|
289
|
+
"publication_year": 2023,
|
|
290
|
+
"type": "journal-article",
|
|
291
|
+
"type_crossref": "journal-article",
|
|
292
|
+
"open_access": {
|
|
293
|
+
"is_oa": true,
|
|
294
|
+
"oa_status": "gold",
|
|
295
|
+
"oa_url": "https://example.com/paper.pdf",
|
|
296
|
+
"any_repository_has_fulltext": true
|
|
297
|
+
},
|
|
298
|
+
"authorships": [
|
|
299
|
+
{
|
|
300
|
+
"author": {
|
|
301
|
+
"id": "https://openalex.org/A123456789",
|
|
302
|
+
"display_name": "作者姓名",
|
|
303
|
+
"orcid": "https://orcid.org/0000-0000-0000-0000"
|
|
304
|
+
},
|
|
305
|
+
"institutions": [
|
|
306
|
+
{
|
|
307
|
+
"id": "https://openalex.org/I123456789",
|
|
308
|
+
"display_name": "机构名称",
|
|
309
|
+
"ror": "https://ror.org/123456789",
|
|
310
|
+
"country_code": "US",
|
|
311
|
+
"type": "education"
|
|
312
|
+
}
|
|
313
|
+
],
|
|
314
|
+
"is_corresponding": true,
|
|
315
|
+
"author_position": "first"
|
|
316
|
+
}
|
|
317
|
+
],
|
|
318
|
+
"cited_by_count": 45,
|
|
319
|
+
"biblio": {
|
|
320
|
+
"volume": "10",
|
|
321
|
+
"issue": "3",
|
|
322
|
+
"first_page": "123",
|
|
323
|
+
"last_page": "145"
|
|
324
|
+
},
|
|
325
|
+
"is_retracted": false,
|
|
326
|
+
"is_paratext": false,
|
|
327
|
+
"concepts": [
|
|
328
|
+
{
|
|
329
|
+
"id": "https://openalex.org/C123456789",
|
|
330
|
+
"wikidata": "https://www.wikidata.org/entity/Q123456",
|
|
331
|
+
"display_name": "主题名称",
|
|
332
|
+
"level": 1,
|
|
333
|
+
"score": 0.95
|
|
334
|
+
}
|
|
335
|
+
],
|
|
336
|
+
"mesh": [],
|
|
337
|
+
"locations": [
|
|
338
|
+
{
|
|
339
|
+
"is_oa": true,
|
|
340
|
+
"landing_page_url": "https://example.com/paper",
|
|
341
|
+
"pdf_url": "https://example.com/paper.pdf",
|
|
342
|
+
"source": {
|
|
343
|
+
"id": "https://openalex.org/S123456789",
|
|
344
|
+
"display_name": "期刊名称",
|
|
345
|
+
"issn_l": "1234-5678",
|
|
346
|
+
"issn": ["1234-5678", "5678-1234"],
|
|
347
|
+
"is_oa": true,
|
|
348
|
+
"is_in_doaj": true,
|
|
349
|
+
"host_organization": "出版商名称",
|
|
350
|
+
"host_organization_name": "出版商名称",
|
|
351
|
+
"type": "journal",
|
|
352
|
+
"apc_payment": {
|
|
353
|
+
"value": 0,
|
|
354
|
+
"currency": "USD"
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
"license": "cc-by",
|
|
358
|
+
"version": "publishedVersion",
|
|
359
|
+
"is_accepted": true,
|
|
360
|
+
"is_published": true
|
|
361
|
+
}
|
|
362
|
+
],
|
|
363
|
+
"referenced_works": [
|
|
364
|
+
"https://openalex.org/W123456789",
|
|
365
|
+
"https://openalex.org/W987654321"
|
|
366
|
+
],
|
|
367
|
+
"related_works": [
|
|
368
|
+
"https://openalex.org/W111111111",
|
|
369
|
+
"https://openalex.org/W222222222"
|
|
370
|
+
],
|
|
371
|
+
"abstract_inverted_index": {
|
|
372
|
+
"background": [0, 15, 30],
|
|
373
|
+
"methods": [45, 60],
|
|
374
|
+
"results": [75, 90],
|
|
375
|
+
"conclusion": [105, 120]
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**优化后的 JSON 格式:**
|
|
381
|
+
```json
|
|
382
|
+
{
|
|
383
|
+
"id": "W2741809807",
|
|
384
|
+
"title": "论文标题",
|
|
385
|
+
"abstract": "完整摘要文本(从 abstract_inverted_index 重建)",
|
|
386
|
+
"authors": [
|
|
387
|
+
{
|
|
388
|
+
"name": "作者姓名",
|
|
389
|
+
"institution": "机构名称",
|
|
390
|
+
"orcid": "0000-0000-0000-0000",
|
|
391
|
+
"is_corresponding": true
|
|
392
|
+
}
|
|
393
|
+
],
|
|
394
|
+
"year": 2023,
|
|
395
|
+
"venue": "期刊名称",
|
|
396
|
+
"cited_by_count": 45,
|
|
397
|
+
"is_oa": true,
|
|
398
|
+
"oa_url": "https://example.com/paper.pdf",
|
|
399
|
+
"doi": "10.1234/example",
|
|
400
|
+
"topics": [
|
|
401
|
+
{
|
|
402
|
+
"id": "C123456789",
|
|
403
|
+
"name": "主题名称",
|
|
404
|
+
"level": 1
|
|
405
|
+
}
|
|
406
|
+
],
|
|
407
|
+
"references_count": 25,
|
|
408
|
+
"related_works_count": 10
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
#### 3.4.3 优化规则
|
|
413
|
+
1. **字段精简**:
|
|
414
|
+
- 去除 `display_name`(与 `title` 重复)
|
|
415
|
+
- 去除 `type_crossref`(与 `type` 重复)
|
|
416
|
+
- 去除 `biblio` 详细信息(除非特别需要)
|
|
417
|
+
- 去除 `mesh`(除非特别需要)
|
|
418
|
+
|
|
419
|
+
2. **结构扁平化**:
|
|
420
|
+
- 将 `authorships` 简化为 `authors` 数组
|
|
421
|
+
- 将 `open_access` 信息扁平化到顶层
|
|
422
|
+
- 将 `locations` 信息提取关键字段
|
|
423
|
+
|
|
424
|
+
3. **数据转换**:
|
|
425
|
+
- 将 `abstract_inverted_index` 重建为完整文本
|
|
426
|
+
- 将完整的 OpenAlex URL 简化为 ID
|
|
427
|
+
- 将 `referenced_works` 和 `related_works` 简化为计数
|
|
428
|
+
|
|
429
|
+
4. **智能提取**:
|
|
430
|
+
- 只保留对 LLM 有用的字段
|
|
431
|
+
- 根据模式(quick/deep)决定包含的详细程度
|
|
432
|
+
|
|
433
|
+
### 3.5 功能 5:多 Agent 协作支持
|
|
434
|
+
|
|
435
|
+
#### 3.5.1 功能描述
|
|
436
|
+
提供便于多 Agent 结构高效开发的功能和接口。
|
|
437
|
+
|
|
438
|
+
#### 3.5.2 支持的功能
|
|
439
|
+
1. **批量查询优化**:
|
|
440
|
+
- 支持批量 DOI/PMID 查询(最多 50 个)
|
|
441
|
+
- 使用 OR 过滤器,减少 API 调用
|
|
442
|
+
|
|
443
|
+
2. **缓存共享**:
|
|
444
|
+
- 统一的缓存目录结构
|
|
445
|
+
- 支持缓存统计和清理
|
|
446
|
+
|
|
447
|
+
3. **状态管理**:
|
|
448
|
+
- 提供系统状态查询接口
|
|
449
|
+
- 支持缓存统计和性能监控
|
|
450
|
+
|
|
451
|
+
4. **错误处理**:
|
|
452
|
+
- 统一的错误格式
|
|
453
|
+
- 支持重试和降级策略
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## 4. 技术架构
|
|
458
|
+
|
|
459
|
+
### 4.1 技术选型
|
|
460
|
+
|
|
461
|
+
| 技术 | 选择 | 理由 |
|
|
462
|
+
|------|------|------|
|
|
463
|
+
| 语言 | JavaScript (Node.js) | 轻量化,易于部署,与 PubMed MCP 保持一致 |
|
|
464
|
+
| MCP SDK | @modelcontextprotocol/sdk | 官方 SDK,稳定可靠 |
|
|
465
|
+
| HTTP 客户端 | node-fetch | 轻量,支持代理 |
|
|
466
|
+
| PDF 处理 | pdf-parse | 提取 PDF 文本内容 |
|
|
467
|
+
| 缓存 | 文件系统 | 简单可靠,无需额外依赖 |
|
|
468
|
+
| 配置管理 | dotenv | 环境变量管理 |
|
|
469
|
+
|
|
470
|
+
### 4.2 项目结构
|
|
471
|
+
|
|
472
|
+
```
|
|
473
|
+
openalex-mcp-server/
|
|
474
|
+
├── src/
|
|
475
|
+
│ ├── index.js # 主服务器入口
|
|
476
|
+
│ ├── openalex-client.js # OpenAlex API 客户端
|
|
477
|
+
│ ├── cache-manager.js # 缓存管理
|
|
478
|
+
│ ├── fulltext-downloader.js # 全文下载器
|
|
479
|
+
│ ├── json-optimizer.js # JSON 格式优化器
|
|
480
|
+
│ └── utils.js # 工具函数
|
|
481
|
+
├── config/
|
|
482
|
+
│ └── mcp-config.json # MCP 配置模板
|
|
483
|
+
├── cache/ # 缓存目录(自动创建)
|
|
484
|
+
│ ├── papers/ # 论文元数据缓存
|
|
485
|
+
│ ├── fulltext/ # 全文缓存
|
|
486
|
+
│ └── index.json # 缓存索引
|
|
487
|
+
├── .env.example # 环境变量模板
|
|
488
|
+
├── package.json # 项目配置
|
|
489
|
+
├── README.md # 项目文档
|
|
490
|
+
├── PRD.md # 本文档
|
|
491
|
+
└── LICENSE # 许可证
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### 4.3 核心模块设计
|
|
495
|
+
|
|
496
|
+
#### 4.3.1 OpenAlexClient
|
|
497
|
+
负责与 OpenAlex API 交互:
|
|
498
|
+
- API 请求封装
|
|
499
|
+
- 速率限制管理(100 req/s)
|
|
500
|
+
- 错误重试机制(指数退避)
|
|
501
|
+
- 请求缓存
|
|
502
|
+
|
|
503
|
+
#### 4.3.2 CacheManager
|
|
504
|
+
负责缓存管理:
|
|
505
|
+
- 论文元数据缓存
|
|
506
|
+
- 全文文件缓存
|
|
507
|
+
- 缓存索引维护
|
|
508
|
+
- 缓存清理策略
|
|
509
|
+
|
|
510
|
+
#### 4.3.3 FulltextDownloader
|
|
511
|
+
负责全文下载:
|
|
512
|
+
- OA 论文检测
|
|
513
|
+
- PDF 下载
|
|
514
|
+
- 文本提取
|
|
515
|
+
- 章节分割
|
|
516
|
+
|
|
517
|
+
#### 4.3.4 JsonOptimizer
|
|
518
|
+
负责 JSON 格式优化:
|
|
519
|
+
- 字段精简
|
|
520
|
+
- 结构扁平化
|
|
521
|
+
- 数据转换
|
|
522
|
+
- 智能提取
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
## 5. API 设计
|
|
527
|
+
|
|
528
|
+
### 5.1 MCP Tools 列表
|
|
529
|
+
|
|
530
|
+
#### Tool 1: `openalex_search`
|
|
531
|
+
快速文章检索
|
|
532
|
+
|
|
533
|
+
**参数:**
|
|
534
|
+
```json
|
|
535
|
+
{
|
|
536
|
+
"query": "CRISPR gene editing",
|
|
537
|
+
"max_results": 20,
|
|
538
|
+
"filters": {
|
|
539
|
+
"publication_year": ">2020",
|
|
540
|
+
"is_oa": true
|
|
541
|
+
},
|
|
542
|
+
"sort_by": "cited_by_count:desc"
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
#### Tool 2: `openalex_get_work`
|
|
547
|
+
获取论文详细信息
|
|
548
|
+
|
|
549
|
+
**参数:**
|
|
550
|
+
```json
|
|
551
|
+
{
|
|
552
|
+
"work_id": "W2741809807",
|
|
553
|
+
"include_abstract": true,
|
|
554
|
+
"include_authors": true,
|
|
555
|
+
"abstract_mode": "deep"
|
|
556
|
+
}
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
#### Tool 3: `openalex_batch_get_works`
|
|
560
|
+
批量获取论文信息
|
|
561
|
+
|
|
562
|
+
**参数:**
|
|
563
|
+
```json
|
|
564
|
+
{
|
|
565
|
+
"work_ids": ["W2741809807", "W1234567890"],
|
|
566
|
+
"include_abstract": true
|
|
567
|
+
}
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
#### Tool 4: `openalex_detect_fulltext`
|
|
571
|
+
检测全文可用性
|
|
572
|
+
|
|
573
|
+
**参数:**
|
|
574
|
+
```json
|
|
575
|
+
{
|
|
576
|
+
"work_id": "W2741809807"
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
#### Tool 5: `openalex_download_fulltext`
|
|
581
|
+
下载全文
|
|
582
|
+
|
|
583
|
+
**参数:**
|
|
584
|
+
```json
|
|
585
|
+
{
|
|
586
|
+
"work_id": "W2741809807",
|
|
587
|
+
"force_download": false
|
|
588
|
+
}
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
#### Tool 6: `openalex_get_fulltext_sections`
|
|
592
|
+
获取全文章节
|
|
593
|
+
|
|
594
|
+
**参数:**
|
|
595
|
+
```json
|
|
596
|
+
{
|
|
597
|
+
"work_id": "W2741809807",
|
|
598
|
+
"sections": ["abstract", "methods", "results"]
|
|
599
|
+
}
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
#### Tool 7: `openalex_cache_stats`
|
|
603
|
+
缓存统计
|
|
604
|
+
|
|
605
|
+
**参数:**
|
|
606
|
+
```json
|
|
607
|
+
{
|
|
608
|
+
"action": "stats"
|
|
609
|
+
}
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
#### Tool 8: `openalex_system_check`
|
|
613
|
+
系统检查
|
|
614
|
+
|
|
615
|
+
**参数:**
|
|
616
|
+
```json
|
|
617
|
+
{}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
### 5.2 与 PubMed MCP 的配合
|
|
621
|
+
|
|
622
|
+
#### 5.2.1 互补策略
|
|
623
|
+
- **OpenAlex**:快速检索、OA 论文下载、丰富的元数据
|
|
624
|
+
- **PubMed**:生物医学专业数据、MeSH 主题词、更详细的摘要
|
|
625
|
+
|
|
626
|
+
#### 5.2.2 使用场景
|
|
627
|
+
1. **快速检索**:优先使用 OpenAlex(速度快)
|
|
628
|
+
2. **深度分析**:结合 PubMed(更详细的生物医学信息)
|
|
629
|
+
3. **全文获取**:优先使用 OpenAlex(直接下载 OA 论文)
|
|
630
|
+
4. **数据验证**:交叉验证两个数据源的结果
|
|
631
|
+
|
|
632
|
+
---
|
|
633
|
+
|
|
634
|
+
## 6. 数据模型
|
|
635
|
+
|
|
636
|
+
### 6.1 Work(论文)数据结构
|
|
637
|
+
|
|
638
|
+
```typescript
|
|
639
|
+
interface Work {
|
|
640
|
+
// 基本信息
|
|
641
|
+
id: string; // OpenAlex ID(简化版)
|
|
642
|
+
title: string;
|
|
643
|
+
abstract?: string;
|
|
644
|
+
publication_date: string;
|
|
645
|
+
publication_year: number;
|
|
646
|
+
|
|
647
|
+
// 作者信息
|
|
648
|
+
authors: Author[];
|
|
649
|
+
|
|
650
|
+
// 发表信息
|
|
651
|
+
venue: string;
|
|
652
|
+
type: string;
|
|
653
|
+
language: string;
|
|
654
|
+
|
|
655
|
+
// 引用信息
|
|
656
|
+
cited_by_count: number;
|
|
657
|
+
|
|
658
|
+
// 开放获取
|
|
659
|
+
is_oa: boolean;
|
|
660
|
+
oa_url?: string;
|
|
661
|
+
oa_status?: string;
|
|
662
|
+
|
|
663
|
+
// 标识符
|
|
664
|
+
doi?: string;
|
|
665
|
+
pmid?: string;
|
|
666
|
+
|
|
667
|
+
// 主题分类
|
|
668
|
+
topics: Topic[];
|
|
669
|
+
|
|
670
|
+
// 引用关系(简化)
|
|
671
|
+
references_count?: number;
|
|
672
|
+
related_works_count?: number;
|
|
673
|
+
}
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
### 6.2 缓存数据结构
|
|
677
|
+
|
|
678
|
+
```typescript
|
|
679
|
+
interface CacheIndex {
|
|
680
|
+
version: string;
|
|
681
|
+
created: string;
|
|
682
|
+
papers: {
|
|
683
|
+
[workId: string]: {
|
|
684
|
+
cached_at: string;
|
|
685
|
+
expires_at: string;
|
|
686
|
+
file_path: string;
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
stats: {
|
|
690
|
+
totalPapers: number;
|
|
691
|
+
totalSize: number;
|
|
692
|
+
lastCleanup: string;
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
---
|
|
698
|
+
|
|
699
|
+
## 7. 性能优化
|
|
700
|
+
|
|
701
|
+
### 7.1 API 调用优化
|
|
702
|
+
1. **使用最大页面大小**:`per-page=200`
|
|
703
|
+
2. **批量查询**:使用 OR 过滤器(最多 50 个 ID)
|
|
704
|
+
3. **字段选择**:使用 `select` 参数只获取必要字段
|
|
705
|
+
4. **请求缓存**:避免重复查询
|
|
706
|
+
|
|
707
|
+
### 7.2 速率限制管理
|
|
708
|
+
- **限制**:100 请求/秒,100,000 credits/天
|
|
709
|
+
- **策略**:实现全局速率限制器
|
|
710
|
+
- **监控**:跟踪每日 credit 使用量
|
|
711
|
+
|
|
712
|
+
### 7.3 缓存策略
|
|
713
|
+
1. **内存缓存**:** 最近查询的结果
|
|
714
|
+
2. **文件缓存**:论文元数据和全文
|
|
715
|
+
3. **缓存过期**:元数据 30 天,全文 90 天
|
|
716
|
+
4. **缓存清理**:定期清理过期缓存
|
|
717
|
+
|
|
718
|
+
### 7.4 错误处理
|
|
719
|
+
- **指数退避**:1s, 2s, 4s, 8s, 16s
|
|
720
|
+
- **最大重试**:5 次
|
|
721
|
+
- **降级策略**:API 失败时返回缓存数据
|
|
722
|
+
|
|
723
|
+
---
|
|
724
|
+
|
|
725
|
+
## 8. 部署方案
|
|
726
|
+
|
|
727
|
+
### 8.1 本地部署
|
|
728
|
+
```bash
|
|
729
|
+
npm install
|
|
730
|
+
cp .env.example .env
|
|
731
|
+
# 编辑 .env 文件
|
|
732
|
+
npm start
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
### 8.2 NPX 部署(魔塔社区)
|
|
736
|
+
|
|
737
|
+
#### 8.2.1 发布到 NPM
|
|
738
|
+
```json
|
|
739
|
+
{
|
|
740
|
+
"name": "@your-org/openalex-mcp-server",
|
|
741
|
+
"version": "1.0.0",
|
|
742
|
+
"bin": {
|
|
743
|
+
"openalex-mcp": "./src/index.js"
|
|
744
|
+
},
|
|
745
|
+
"files": [
|
|
746
|
+
"src/",
|
|
747
|
+
"package.json",
|
|
748
|
+
"README.md"
|
|
749
|
+
]
|
|
750
|
+
}
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
#### 8.2.2 使用方式
|
|
754
|
+
```bash
|
|
755
|
+
# 全局安装
|
|
756
|
+
npm install -g @your-org/openalex-mcp-server
|
|
757
|
+
|
|
758
|
+
# 或直接使用 npx
|
|
759
|
+
npx @your-org/openalex-mcp-server
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
#### 8.2.3 MCP 客户端配置
|
|
763
|
+
```json
|
|
764
|
+
{
|
|
765
|
+
"mcpServers": {
|
|
766
|
+
"openalex-mcp": {
|
|
767
|
+
"command": "npx",
|
|
768
|
+
"args": ["@your-org/openalex-mcp-server"],
|
|
769
|
+
"env": {
|
|
770
|
+
"OPENALEX_API_KEY": "your-api-key"
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
### 8.3 环境变量配置
|
|
778
|
+
|
|
779
|
+
```env
|
|
780
|
+
# OpenAlex API 配置
|
|
781
|
+
OPENALEX_API_KEY=your-api-key # 可选,但推荐(提升 credit 限制)
|
|
782
|
+
|
|
783
|
+
# 功能配置
|
|
784
|
+
ABSTRACT_MODE=deep # quick | deep
|
|
785
|
+
FULLTEXT_MODE=enabled # disabled | enabled | auto
|
|
786
|
+
CACHE_ENABLED=true # 是否启用缓存
|
|
787
|
+
|
|
788
|
+
# 代理配置(可选)
|
|
789
|
+
PROXY_ENABLED=false
|
|
790
|
+
HTTP_PROXY=http://proxy.example.com:8080
|
|
791
|
+
HTTPS_PROXY=https://proxy.example.com:8080
|
|
792
|
+
|
|
793
|
+
# 缓存配置
|
|
794
|
+
CACHE_DIR=./cache
|
|
795
|
+
CACHE_EXPIRY_DAYS=30
|
|
796
|
+
FULLTEXT_CACHE_EXPIRY_DAYS=90
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
---
|
|
800
|
+
|
|
801
|
+
## 9. 开发计划
|
|
802
|
+
|
|
803
|
+
### 9.1 开发阶段
|
|
804
|
+
|
|
805
|
+
#### Phase 1: 核心功能(Week 1-2)
|
|
806
|
+
- [ ] 项目初始化
|
|
807
|
+
- [ ] OpenAlex API 客户端实现
|
|
808
|
+
- [ ] 基础工具实现(search, get_work)
|
|
809
|
+
- [ ] JSON 格式优化器
|
|
810
|
+
- [ ] 基础缓存功能
|
|
811
|
+
|
|
812
|
+
#### Phase 2: 全文功能(Week 3)
|
|
813
|
+
- [ ] 全文检测功能
|
|
814
|
+
- [ ] PDF 下载功能
|
|
815
|
+
- [ ] 文本提取功能
|
|
816
|
+
- [ ] 章节分割功能
|
|
817
|
+
- [ ] 全文缓存管理
|
|
818
|
+
|
|
819
|
+
#### Phase 3: 优化与测试(Week 4)
|
|
820
|
+
- [ ] 性能优化
|
|
821
|
+
- [ ] 错误处理完善
|
|
822
|
+
- [ ] 单元测试
|
|
823
|
+
- [ ] 文档编写
|
|
824
|
+
- [ ] 部署准备
|
|
825
|
+
|
|
826
|
+
#### Phase 4: 发布(Week 5)
|
|
827
|
+
- [ ] NPM 发布
|
|
828
|
+
- [ ] 魔塔社区提交
|
|
829
|
+
- [ ] 使用文档
|
|
830
|
+
- [ ] 示例代码
|
|
831
|
+
|
|
832
|
+
### 9.2 里程碑
|
|
833
|
+
|
|
834
|
+
| 里程碑 | 时间 | 交付物 |
|
|
835
|
+
|--------|------|--------|
|
|
836
|
+
| M1: 核心功能完成 | Week 2 | 基础检索和获取功能 |
|
|
837
|
+
| M2: 全文功能完成 | Week 3 | 全文下载和缓存功能 |
|
|
838
|
+
| M3: 测试完成 | Week 4 | 测试报告和文档 |
|
|
839
|
+
| M4: 正式发布 | Week 5 | NPM 包和文档 |
|
|
840
|
+
|
|
841
|
+
---
|
|
842
|
+
|
|
843
|
+
## 10. 风险评估
|
|
844
|
+
|
|
845
|
+
### 10.1 技术风险
|
|
846
|
+
|
|
847
|
+
| 风险 | 影响 | 概率 | 应对措施 |
|
|
848
|
+
|------|------|------|----------|
|
|
849
|
+
| OpenAlex API 变更 | 高 | 低 | 版本锁定,监控 API 变更 |
|
|
850
|
+
| PDF 提取失败 | 中 | 中 | 多库支持,降级策略 |
|
|
851
|
+
| 速率限制 | 中 | 中 | 实现速率限制器 |
|
|
852
|
+
| 缓存损坏 | 低 | 低 | 缓存验证和修复机制 |
|
|
853
|
+
|
|
854
|
+
### 10.2 业务风险
|
|
855
|
+
|
|
856
|
+
| 风险 | 影响 | 概率 | 应对措施 |
|
|
857
|
+
|------|------|------|----------|
|
|
858
|
+
| API Key 限制 | 中 | 低 | 提供免费 Key 获取指南 |
|
|
859
|
+
| 数据质量 | 低 | 低 | 数据验证和清洗 |
|
|
860
|
+
|
|
861
|
+
---
|
|
862
|
+
|
|
863
|
+
## 11. 成功指标
|
|
864
|
+
|
|
865
|
+
### 11.1 性能指标
|
|
866
|
+
- API 响应时间 < 500ms(快速模式)
|
|
867
|
+
- 全文下载成功率 > 90%
|
|
868
|
+
- 缓存命中率 > 60%
|
|
869
|
+
|
|
870
|
+
### 11.2 功能指标
|
|
871
|
+
- 支持所有核心功能
|
|
872
|
+
- JSON 输出体积减少 > 50%
|
|
873
|
+
- 与 PubMed MCP 无缝配合
|
|
874
|
+
|
|
875
|
+
### 11.3 用户体验指标
|
|
876
|
+
- 部署时间 < 5 分钟
|
|
877
|
+
- 配置项 < 10 个
|
|
878
|
+
- 文档完整性 100%
|
|
879
|
+
|
|
880
|
+
---
|
|
881
|
+
|
|
882
|
+
## 12. 附录
|
|
883
|
+
|
|
884
|
+
### 12.1 参考资源
|
|
885
|
+
- [OpenAlex API 文档](https://docs.openalex.org)
|
|
886
|
+
- [MCP 协议规范](https://modelcontextprotocol.io)
|
|
887
|
+
- [PubMed MCP Server](./mcp-pubmed-server)
|
|
888
|
+
|
|
889
|
+
### 12.2 相关项目
|
|
890
|
+
- mcp-pubmed-server:PubMed MCP 服务器参考实现
|
|
891
|
+
- OpenAlex 官方文档:API 使用指南
|
|
892
|
+
|
|
893
|
+
---
|
|
894
|
+
|
|
895
|
+
**文档版本**: 1.0
|
|
896
|
+
**最后更新**: 2026-01-25
|
|
897
|
+
**状态**: 待评审
|