Skip to main content
Glama
its-antony

paper-search

by its-antony

Paper Search

基于 openags/paper-search-mcp 重构 — 原项目由 P.S Zhang 开发,MIT 协议。

本项目在原始项目基础上进行了服务化架构重构,将业务逻辑从 MCP 协议绑定中解耦,形成独立的服务层,可作为 Python 库直接调用,也可作为 MCP Server 接入 Claude Desktop 等 LLM 客户端。

一个支持 20+ 学术平台的论文搜索、下载与导出服务。

Python License Pydantic v2


特性

  • 20+ 学术数据源 — arXiv、PubMed、Semantic Scholar、Crossref、OpenAlex、Google Scholar 等

  • 三层架构 — Connectors → Service → Transport,关注点清晰分离

  • 即插即用 — 添加新平台只需一个文件,自动注册,零配置

  • 双模式使用 — 既是 Python 库(from paper_search import PaperSearchService),也是 MCP Server

  • Pydantic 数据模型 — 类型安全、序列化友好

  • 多源并发搜索 + 自动去重 — 基于 DOI / 标题+作者 去重

  • Open-access first 下载链 — 源原生下载 → OA 仓库 → Unpaywall;其他来源需要显式 opt-in

  • 引文网络追踪 — Snowball search,支持前向/后向引用递归(1-3 层深度)

  • 多格式导出 — CSV、RIS(Zotero/Mendeley/EndNote)、BibTeX


架构

paper_search/
├── models/          # Pydantic 数据模型 (Paper, SearchResult, SnowballResult)
├── connectors/      # 平台连接器 (@register 自动注册)
│   ├── base.py      #   抽象基类 PaperConnector
│   ├── registry.py  #   连接器注册表(自动发现)
│   ├── arxiv.py     #   arXiv 连接器
│   ├── semantic.py  #   Semantic Scholar 连接器
│   └── ...          #   25+ 连接器
├── service/         # 业务编排层(不依赖任何传输协议)
│   ├── search_service.py    # 多源搜索 + Snowball
│   ├── download_service.py  # 下载回退链
│   └── export_service.py    # CSV/RIS/BibTeX 导出
├── transports/      # 传输适配层
│   └── mcp_server.py        # MCP Server(薄包装)
├── config.py        # 环境变量管理
└── utils.py         # 工具函数

与原项目的区别

方面

原项目 (paper-search-mcp)

本项目 (paper-search)

架构

单文件 server.py(1570 行)

三层架构,职责分离

数据模型

dataclass

Pydantic v2

复用性

仅限 MCP 调用

可作为库 import 使用

添加新平台

改 5 处代码

只写 1 个文件

平台分派

20+ 个 if/elif

@register 自动注册

测试

需启动 MCP Server

直接测试 Service 层


支持的数据源

免费开放数据源(无需 API Key)

平台

搜索

下载

读取

说明

arXiv

预印本,覆盖物理/CS/数学等

PubMed

-

-

生物医学文献元数据

bioRxiv

生物学预印本

medRxiv

医学预印本

Crossref

-

-

DOI 元数据骨干

OpenAlex

-

-

开放学术知识图谱

Europe PMC

欧洲生物医学 OA

PubMed Central

NIH OA 全文

dblp

-

-

计算机科学文献索引

IACR

密码学预印本

HAL

法国开放存档

SSRN

⚠️

⚠️

社科预印本(best-effort)

ChemRxiv

化学预印本

可选 API Key 数据源(免费申请,提升速率)

平台

环境变量

申请地址

Semantic Scholar

PAPER_SEARCH_MCP_SEMANTIC_SCHOLAR_API_KEY

semanticscholar.org

CORE

PAPER_SEARCH_MCP_CORE_API_KEY

core.ac.uk

DOAJ

PAPER_SEARCH_MCP_DOAJ_API_KEY

doaj.org

Zenodo

PAPER_SEARCH_MCP_ZENODO_ACCESS_TOKEN

zenodo.org

Unpaywall

PAPER_SEARCH_MCP_UNPAYWALL_EMAIL

unpaywall.org

Google Scholar

PAPER_SEARCH_MCP_GOOGLE_SCHOLAR_PROXY_URL

自备代理

OpenAIRE

PAPER_SEARCH_MCP_OPENAIRE_API_KEY

openaire.eu

CiteSeerX

PAPER_SEARCH_MCP_CITESEERX_API_KEY

-

付费/受限数据源(需 API Key 激活)

平台

环境变量

说明

IEEE Xplore

PAPER_SEARCH_MCP_IEEE_API_KEY

未设置 key 时自动禁用

ACM Digital Library

PAPER_SEARCH_MCP_ACM_API_KEY

未设置 key 时自动禁用


快速开始

安装

# 克隆项目
git clone https://github.com/its-antony/paper-search.git
cd paper-search

# 安装依赖(自动创建虚拟环境)
uv sync

# 如果需要 MCP Server 功能
uv sync --extra mcp

作为 Python 库使用

import asyncio
from paper_search import PaperSearchService

async def main():
    svc = PaperSearchService()

    # 多源并发搜索
    result = await svc.search(
        "real world assets tokenization",
        sources="crossref,openalex,arxiv",
        max_results_per_source=5,
    )

    for paper in result.papers:
        print(f"{paper.title} ({paper.source})")
        print(f"  DOI: {paper.doi}")

asyncio.run(main())
async def snowball_demo():
    svc = PaperSearchService()

    result = await svc.snowball(
        paper_id="DOI:10.1038/nature12373",
        direction="both",      # forward + backward
        depth=2,               # 2 层递归
        max_results_per_direction=10,
    )
    print(f"发现 {result.total} 篇相关论文")

下载与导出

from paper_search.service import DownloadService, ExportService
from paper_search.connectors.registry import ConnectorRegistry

async def download_and_export():
    reg = ConnectorRegistry()
    dl = DownloadService(registry=reg)
    export = ExportService()

    # 下载论文 PDF(默认只走 open-access fallback)
    path = await dl.download(
        source="arxiv",
        paper_id="2106.12345",
        save_path="./downloads",
    )

    # 导出搜索结果
    svc = PaperSearchService()
    result = await svc.search("blockchain finance", sources="crossref")
    export.export(result.papers, format="bibtex", save_path="./exports")

作为 MCP Server 使用

Claude Desktop 配置

{
  "mcpServers": {
    "paper-search": {
      "command": "uv",
      "args": [
        "run", "--directory", "/path/to/paper-search",
        "-m", "paper_search.transports.mcp_server"
      ],
      "env": {
        "PAPER_SEARCH_MCP_UNPAYWALL_EMAIL": "your@email.com",
        "PAPER_SEARCH_MCP_SEMANTIC_SCHOLAR_API_KEY": ""
      }
    }
  }
}

Claude Code (CLI) 配置

# 添加为全局 MCP Server(所有项目可用)
claude mcp add --scope user paper-search -- \
  uv run --directory /path/to/paper-search -m paper_search.transports.mcp_server

# 或仅当前项目可用
claude mcp add paper-search -- \
  uv run --directory /path/to/paper-search -m paper_search.transports.mcp_server

# 如需配置 API Key
claude mcp add --scope user paper-search \
  -e PAPER_SEARCH_MCP_UNPAYWALL_EMAIL=your@email.com \
  -e PAPER_SEARCH_MCP_SEMANTIC_SCHOLAR_API_KEY=sk-xxx \
  -- uv run --directory /path/to/paper-search -m paper_search.transports.mcp_server

添加后重启 Claude Code 即可在对话中直接使用论文搜索工具。

局域网 / 远程访问(HTTP 模式)

MCP Server 支持三种传输模式:stdio(默认)、ssestreamable-http

# 启动 HTTP 模式(局域网可访问)
uv run -m paper_search.transports.mcp_server --transport streamable-http --host 0.0.0.0 --port 8000

# 或 SSE 模式
uv run -m paper_search.transports.mcp_server --transport sse --host 0.0.0.0 --port 8000

其他机器的 Claude Code 通过 URL 连接:

claude mcp add --scope user paper-search --transport http http://192.168.x.x:8000/mcp

配置

将 API Key 写入项目根目录的 .env 文件(启动时自动加载):

cp .env.example .env
# 编辑 .env 填入你的 key

所有环境变量均使用 PAPER_SEARCH_MCP_ 前缀,兼容原项目的无前缀写法。

下载策略

默认下载流程只使用源站、开放仓库和 Unpaywall 等 open-access 来源。任何非 OA fallback 都需要调用方显式开启,并由使用者自行确认合规性。


扩展新平台

添加一个新的学术数据源只需 1 个文件

# paper_search/connectors/my_platform.py
from ..models.paper import Paper
from .base import PaperConnector, ConnectorCapabilities
from .registry import register

@register("my_platform")
class MyPlatformConnector(PaperConnector):
    capabilities = ConnectorCapabilities(search=True, download=True, read=False)

    def search(self, query: str, max_results: int = 10, **kwargs):
        # 你的搜索逻辑
        return [Paper(paper_id="...", title="...", source="my_platform")]

    def download_pdf(self, paper_id: str, save_path: str) -> str:
        # 你的下载逻辑
        return f"{save_path}/{paper_id}.pdf"

无需修改任何其他文件 — Registry 自动发现,Service 自动包含,MCP 自动注册工具。


开发

# 安装开发依赖
uv sync --extra dev --extra mcp

# 运行测试
uv run pytest tests/ -v

# 启动 MCP Server(stdio 模式)
uv run paper-search-mcp

# 启动 MCP Server(HTTP 模式,局域网可访问)
uv run paper-search-mcp --transport streamable-http --host 0.0.0.0 --port 8000

致谢

许可证

MIT License — 详见 LICENSE 文件。

A
license - permissive license
-
quality - not tested
C
maintenance

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/its-antony/paper-search'

If you have feedback or need assistance with the MCP directory API, please join our Discord server