Scopus MCP Server
Scopus MCP Server
一个包装了 Elsevier Scopus API 的 MCP 服务器,使 MCP 客户端(Claude Desktop、Claude Code 或任何其他 MCP 主机)能够搜索和检索已发表的学术文章——适用于基于真实同行评审来源的引文验证和写作风格分析。
工具
工具 | 输入 | 返回值 |
|
| 最多 |
|
| 单篇文章的完整元数据:上述所有字段,外加作者关键词、学科领域、开放获取标志、聚合类型 |
|
| 仅返回单篇文章的摘要文本,如果 Scopus 没有存档摘要则返回 |
所有响应均为结构化 JSON(见下文 响应结构)。当 Scopus API 不可达、被限流或收到无效 ID 时,每个工具都会返回友好的结构化错误而不是抛出异常——参见 错误处理。
在底层,服务器调用两个 Elsevier API:
Scopus Search API(
GET /content/search/scopus)——由search_scopus使用。Abstract Retrieval API(
GET /content/abstract/scopus_id/{id})——由get_article_details和get_article_abstract使用,因为 Search API 不能可靠地返回完整摘要、被引次数或关键词。
Related MCP server: MCP-scopus
项目结构
mcp-server/
├── src/
│ ├── index.ts # stdio entry point (for local MCP clients)
│ ├── httpServer.ts # Streamable HTTP entry point (for remote deployment)
│ ├── registerTools.ts # tool definitions, shared by both entry points
│ ├── scopusClient.ts # Elsevier API client: requests, normalization, error mapping
│ ├── types.ts # TypeScript types for raw Scopus responses + normalized output
│ └── logger.ts # structured logger → stderr + logs/scopus-mcp.log
├── test/
│ └── test-connection.ts # standalone connectivity test (bypasses the MCP protocol)
├── logs/ # log file written here at runtime (gitignored)
├── .env.example
├── package.json
└── tsconfig.json前提条件
Node.js 18 或更高版本(使用内置的全局
fetch)。用node -v检查。Scopus API 密钥。 在 Elsevier Developer Portal 注册一个免费密钥。请注意,Elsevier 会按 IP 范围(机构订阅)或 Institutional Token 限制全文/摘要访问——仅凭密钥即可测试连接性和基本搜索,但某些字段可能会因您的权限而受到限制。
安装
cd mcp-server
npm install
cp .env.example .env编辑 .env 并设置您的密钥:
SCOPUS_API_KEY=your_real_key_hereSCOPUS_API_KEY 在启动时从环境中读取(src/scopusClient.ts);它绝不会被硬编码,而且 .env 已被 gitignore 忽略,因此不会被意外提交。
环境变量
变量 | 是否必需 | 默认值 | 用途 |
| ✅ | — | 您的 Elsevier Scopus API 密钥 |
| 可选 | — | Institutional Token,如果您的密钥在校外访问时需要它 |
| 可选 |
| 用于针对代理/模拟服务进行测试的覆盖地址 |
| 可选 |
| 每个请求的超时时间 |
| 可选 |
|
|
| 仅 HTTP 模式 |
|
|
| 仅 HTTP 模式 |
|
|
| HTTP 模式,强烈推荐 | — | 如果设置, |
| HTTP 模式,可选 | — | 逗号分隔的 |
先测试连接
在将服务器接入任何 MCP 客户端之前,先验证 Scopus API 密钥和网络路径是否正常:
npm run test:connection这会运行 test/test-connection.ts,它调用与工具相同的客户端函数——但直接调用,不通过 MCP 协议——针对示例查询 "farmland abandonment Nepal"。您也可以传入自己的查询:
npm run test:connection -- "AUTH(Smith J) AND TITLE(remote sensing)"它会按顺序遍历所有三个工具(搜索 → 详情 → 第一条结果的摘要),并逐步打印 ✅/❌,同时在 logs/scopus-mcp.log 中记录完整的请求/响应日志(见 日志)。只有当每一步都成功时退出码才为 0。
本地运行(stdio,适用于本地 MCP 客户端)
npm run dev # runs src/index.ts directly via tsx, no build step
# or
npm run build && npm start # compiles to dist/ then runs the compiled server服务器通过 stdio 通信,因此直接在终端中运行它会一直等待 stdin 上的 JSON-RPC——这是预期行为。它应由 MCP 客户端启动。
连接到 Claude Code
claude mcp add scopus --env SCOPUS_API_KEY=your_real_key_here -- node /absolute/path/to/mcp-server/dist/index.js(先运行 npm run build,确保 dist/index.js 存在),或者将其添加到项目的 .mcp.json:
{
"mcpServers": {
"scopus": {
"command": "node",
"args": ["/absolute/path/to/mcp-server/dist/index.js"],
"env": { "SCOPUS_API_KEY": "your_real_key_here" }
}
}
}连接到 Claude Desktop
将相同的配置块添加到 claude_desktop_config.json
(Windows 上为 %APPDATA%\Claude\claude_desktop_config.json,
macOS 上为 ~/Library/Application Support/Claude/claude_desktop_config.json),然后重启 Claude Desktop:
{
"mcpServers": {
"scopus": {
"command": "node",
"args": ["/absolute/path/to/mcp-server/dist/index.js"],
"env": { "SCOPUS_API_KEY": "your_real_key_here" }
}
}
}响应结构
search_scopus 示例(已截断):
{
"query": "farmland abandonment Nepal",
"totalResults": 42,
"returnedResults": 10,
"articles": [
{
"scopusId": "85123456789",
"eid": "2-s2.0-85123456789",
"title": "Drivers of farmland abandonment in the mid-hills of Nepal",
"authors": ["Sharma B.", "Poudel K."],
"publicationYear": 2021,
"sourceTitle": "Land Use Policy",
"doi": "10.1016/j.landusepol.2021.105123",
"doiUrl": "https://doi.org/10.1016/j.landusepol.2021.105123",
"scopusUrl": "https://www.scopus.com/inward/record.uri?...",
"citedByCount": 17,
"abstract": null,
"documentType": "Article"
}
]
}get_article_details 在相同字段之外还添加了 keywords、subjectAreas、openAccess 和 aggregationType。get_article_abstract 返回 { scopusId, title, abstract, hasAbstract }。
Scopus 对某条记录没有的字段会以 null 返回(列表字段返回 [],或返回 hasAbstract: false),而不是省略——在断定字段缺失是 bug 之前,请先检查 null/false。
错误处理
每个工具都会在内部捕获错误,并返回 isError: true 及结构化 JSON 正文,而不是让 MCP 连接崩溃:
{
"error": true,
"kind": "rate_limited",
"message": "Scopus API rate limit exceeded (HTTP 429) for search_scopus(...). Retry after 30s.",
"status": 429,
"retryAfterSeconds": 30
}kind 为以下之一:unauthorized(API 密钥错误/缺失)、rate_limited(HTTP 429)、not_found(错误的 Scopus ID / HTTP 404)、bad_request(查询为空、输入格式错误)、network_error(DNS/连接失败)、timeout(超过 SCOPUS_REQUEST_TIMEOUT_MS)或 unknown。搜索成功但没有匹配结果不是错误——它会返回 totalResults: 0 以及一条建议如何扩大查询范围的人类可读 message。
日志
所有 API 调用和响应都会记录日志,便于调试:
每个请求在发送前都会记录其 URL(API 密钥已打码)。
每个响应都会记录状态码、耗时和 500 字符的正文预览。
日志以单行 JSON 的形式写入 stderr(绝不会写入 stdout——在 stdio 传输中,stdout 专用于 MCP 协议),同时也会追加到
logs/scopus-mcp.log。设置
LOG_LEVEL=debug可获取更多细节,或设置LOG_LEVEL=error以减少输出。
部署到远程/无服务器平台(Render、Railway 等)
stdio 传输(src/index.ts)仅适用于能够启动本地进程的 MCP 客户端——它无法通过网络访问。要远程托管此服务器,请改用 Streamable HTTP 入口点:src/httpServer.ts。它在 POST /mcp 上提供相同的三个工具,并增加了一个 GET /healthz 端点用于平台的健康检查。
Render 和 Railway 都不是真正的“无服务器”(没有请求中途的缩容到零冷启动)——二者都是将其作为普通的常驻 Node 进程运行,而这正是 MCP 这类有状态协议所需要的。这里的“无服务器平台”可理解为“托管式 Node 托管”。
Render
将此仓库(或仅
mcp-server/文件夹)推送到 GitHub。在 Render 控制台中:New → Web Service,连接仓库,如果它是更大仓库的子文件夹,则将 root directory 设置为
mcp-server。Build command(构建命令):
npm install && npm run buildStart command(启动命令):
npm run start:http在 Environment(环境变量) 下添加:
SCOPUS_API_KEY= 您的密钥(标记为 secret)MCP_HTTP_AUTH_TOKEN= 您生成的一长串随机字符串(例如openssl rand -hex 32)可选
MCP_ALLOWED_HOSTS= 您的 Render 主机名,例如scopus-mcp.onrender.com
Render 会自动设置
PORT——httpServer.ts会读取它,无需任何操作。部署。健康检查路径:
/healthz。
Railway
New Project → Deploy from GitHub repo,如有需要将服务根目录设置为
mcp-server。Railway 会自动检测 Node;如果它没有运行正确的命令,请设置:
Build command(构建命令):
npm install && npm run buildStart command(启动命令):
npm run start:http
在 Variables(变量) 中添加上述
SCOPUS_API_KEY和MCP_HTTP_AUTH_TOKEN。Railway 会自动注入
PORT。部署完成后,您的 MCP 端点为
https://<your-app>.up.railway.app/mcp。
将 MCP 客户端连接到托管的服务器
claude mcp add --transport http scopus https://<your-app>/mcp \
--header "Authorization: Bearer <your MCP_HTTP_AUTH_TOKEN>"HTTP 部署的安全说明
始终设置
MCP_HTTP_AUTH_TOKEN。 否则,任何拥有 URL 的人都可以调用您的工具并消耗您的 Scopus API 配额——如果未设置,服务器会在启动时记录一条警告。服务器会自动为
localhost/127.0.0.1启用 DNS 重绑定防护;对于真正的0.0.0.0部署,请将MCP_ALLOWED_HOSTS设置为您的平台主机名。通过您平台的密钥管理器轮换
SCOPUS_API_KEY和MCP_HTTP_AUTH_TOKEN,切勿将其提交到仓库。对于公开部署,建议在 Elsevier 自身按密钥的速率限制之外,再在前面加上平台自身的速率限制/反向代理。
故障排查
症状 | 可能的原因 |
|
|
| 密钥无效,或密钥缺少 Scopus Search 权限,或校外访问缺少 |
| 已达到 Elsevier 按密钥的速率/配额限制——请退避并在 |
|
|
| 此机器/主机无法访问互联网、企业代理阻止了 |
在 stdio 客户端中工具调用静默无反应 | 有内容写入了 stdout——请检查您是否添加了多余的 |
许可证
MIT
Available Tools
3 toolsget_article_abstractA
Retrieve just the abstract text for a single Scopus article by its Scopus ID. Returns hasAbstract:false with a null abstract when Scopus has no abstract on file for the article (this is common for older or non-English-language records).
| Name | Required | Description | Default |
|---|---|---|---|
| scopusId | Yes | The Scopus ID of the article, e.g. "85123456789". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of behavioral disclosure. It usefully documents an important edge case: missing abstracts return hasAbstract:false with a null abstract, common for older or non-English-language records. It does not cover invalid-ID behavior, but for a simple read operation this is a reasonable level of transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The main purpose is front-loaded, and the second sentence adds valuable edge-case behavior without being verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with no output schema, the description covers the main purpose and a key edge case. It partially describes the return contract via hasAbstract and abstract, though it does not mention invalid-ID behavior. Overall, the core information needed to call the tool correctly is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter has full schema coverage with a description and example. The tool description adds no parameter-specific meaning beyond what the schema already provides, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Retrieve just the abstract text for a single Scopus article by its Scopus ID.' The qualifiers 'just' and 'single' clearly distinguish this from the sibling tools search_scopus and get_article_details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use this tool: when only the abstract is needed and a Scopus ID is already known. However, it does not explicitly mention alternatives or exclusions, such as using search_scopus to find the ID or get_article_details for full metadata.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_article_detailsA
Retrieve full metadata for a single Scopus article by its Scopus ID, including title, authors, publication year, source title, DOI, citation count, author keywords, subject areas, and abstract (when available). Use the scopusId returned by search_scopus.
| Name | Required | Description | Default |
|---|---|---|---|
| scopusId | Yes | The Scopus ID of the article, e.g. "85123456789" (the "SCOPUS_ID:" prefix, if present, is stripped automatically). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden. It describes what the call returns, including the conditional 'abstract (when available),' which clarifies a key edge case. It does not discuss auth, rate limits, or invalid-ID behavior, but the enumerated output is enough for this simple read operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one sentence with no filler. The core action and ID source are front-loaded, and the field list is an efficient way to convey the return shape.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter lookup with no output schema, the description covers the essential context: what to provide, where to get it, and what metadata will come back. It could add behavior for missing/unknown IDs, but nothing critical is missing for normal invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes scopusId and the automatic prefix stripping, so the baseline is high. The description adds provenance semantics by telling the agent to use a scopusId returned by search_scopus, which is useful information not present in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: 'Retrieve full metadata for a single Scopus article by its Scopus ID.' The enumeration of fields (title, authors, DOI, citation count, etc.) makes the purpose concrete and distinct from a search or abstract-only tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit usage pointer: 'Use the scopusId returned by search_scopus,' which tells the agent where the required ID comes from. It does not explicitly say when to prefer the sibling get_article_abstract over this tool, so it stops short of full exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_scopusA
Search Scopus for published academic articles by author name, keywords, title, or DOI. Returns up to count (default 10, max 25) results with title, authors, publication year, abstract (when Scopus provides one in search results), source title, DOI, and Scopus ID. Use this first to find candidate articles, then call get_article_details or get_article_abstract with a returned scopusId for full metadata.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Number of results to return (default 10, max 25). | |
| query | Yes | Search query. Supports free text (e.g. "farmland abandonment Nepal") or Scopus field-search syntax (e.g. "AUTH(Smith J)", "TITLE(remote sensing)", "DOI(10.1000/xyz123)"). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden of behavioral disclosure. It covers the return payload, count defaults and limits, and the conditional presence of abstracts. It does not mention rate limits, auth requirements, or explicit read-only status, but for a search tool the core behavior is well disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler. It front-loads the purpose, then the return contract, then the follow-up workflow—every sentence adds value and is easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even without an output schema, the description lists the returned fields, count constraints, and a nuanced caveat about abstract availability. The tool has only two simple parameters, and the description gives an agent enough context to invoke it correctly and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description reiterates the query modes and count behavior already present in the schema without adding significant new parameter meaning beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Search'), a clear resource ('Scopus'), and identifies the search facets: author name, keywords, title, or DOI. It also distinguishes itself from siblings by describing candidate-finding versus get_article_details/get_article_abstract metadata retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the intended workflow: 'Use this first to find candidate articles, then call get_article_details or get_article_abstract with a returned scopusId for full metadata.' This tells an agent exactly when to use this tool and how to proceed afterward.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v1.0.0- First observed
get_article_abstract - First observed
get_article_details - First observed
search_scopus
TDQS
Scored across 3 tools
The three tools have clearly distinct primary actions: searching versus retrieving by Scopus ID. However, get_article_details and get_article_abstract overlap since details also includes the abstract when available, which could cause minor confusion about which to call.
All tool names follow a consistent verb_noun pattern: search_scopus, get_article_details, get_article_abstract. The get_article_* prefix for the two retrieval tools reinforces a predictable structure.
Three tools is on the small side but appropriately scoped for a simple search-and-retrieve workflow. The count feels slightly thin for a general-purpose Scopus API wrapper, but each tool serves a necessary step in the primary flow.
The core lifecycle of discovering articles and retrieving full metadata or abstracts is covered, with no dead ends. Minor gaps exist, such as no direct citation-list or author-detail endpoints, but these are reasonable omissions given the stated purpose.
Maintenance
Related MCP Connectors
Academic research MCP server for paper search, citation checks, graphs, and deep research.
Scrape arXiv, OpenAlex and Crossref papers by author, topic, journal or DOI. Pay per row.
Academic paper search, scientific literature, citation analysis, arXiv & semantic related-work.
Scholarly search: OpenAlex, Crossref, arXiv, OpenCitations and PubMed in one endpoint.
Related MCP Servers
- AlicenseAqualityFmaintenanceProvides access to the Elsevier Scopus API, enabling AI assistants to search for academic papers, retrieve detailed abstracts, and look up author profiles. It facilitates bibliometric research and scholarly data analysis through natural language commands.5110 PyPI50MIT
- AlicenseAqualityDmaintenanceEnables AI assistants to search and retrieve real academic papers from Scopus, preventing citation hallucination by providing accurate paper metadata, author info, and citation analysis.153MIT
- AlicenseAqualityBmaintenanceEnables AI agents to search and retrieve academic papers, author profiles, and citation data from the Scopus database via MCP tools.12MIT
- AlicenseNot gradedqualityDmaintenanceEnables searching Elsevier's Scopus database for scientific literature, retrieving abstracts and metadata, and exporting results in RIS or BibTeX format.15 PyPI1MIT