Skip to main content
Glama
Pratik-Pou

Scopus MCP Server

by Pratik-Pou

Scopus MCP Server

Сервер MCP, который оборачивает Elsevier Scopus API, чтобы MCP-клиент (Claude Desktop, Claude Code или любой другой MCP-хост) мог искать и получать опубликованные научные статьи — полезно для проверки цитирования и анализа стиля на основе реальных рецензируемых источников.

Tools

Tool

Input

What it returns

search_scopus

query (автор, ключевые слова, название или DOI), необязательно count (1–25, по умолчанию 10)

До count статей: название, авторы, год публикации, аннотация (если Scopus включает её в результаты поиска), название источника, DOI, URL DOI, Scopus ID, число цитирований

get_article_details

scopusId

Полные метаданные для одной стати: всё вышеперечисленное плюс ключевые слова автора, предметные области, флаг открытого доступа, тип агрегации

get_article_abstract

scopusId

Только текст аннотации для одной стати, плюс hasAbstract: false, если в Scopus нет аннотации

Все ответы представляют собой структурированный JSON (см. Форма ответа ниже). Каждый инструмент возвращает понятную структурированную ошибку вместo исключения, когда Scopus API недоступен, превышен лимит запросов или передан неверный ID — см. Обработка ошибок.

Под капотом сервер вызыват два API Elsevier:

  • 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

Project layout

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. Обратите вниманиe: Elsevier ограничивает доступ к полным текстам/аннотациям по диапазону IP (институционалная подписка) или Institutional Token — одного ключа достасточно для проверки подключения и базового поиска, но некоторые поля могут быть ограничены в зависимости от ваших прав.

Setup

cd mcp-server
npm install
cp .env.example .env

Отредактируйте .env и укажите свой ключ:

SCOPUS_API_KEY=your_real_key_here

SCOPUS_API_KEY считывается из окружения при запуске (src/scopusClient.ts); он никогда не зашит в коде, а .env находится в .gitignore, чтобы его нельзя было случайно закоммитить.

Переменные окружения

Variable

Required

Default

Purpose

SCOPUS_API_KEY

✅

—

Ваш ключ Elsevier Scopus API

SCOPUS_INST_TOKEN

необязательно

—

Institutional Token, если он нужен вашему ключу для доступа вне кампуса

SCOPUS_API_BASE_URL

необязательно

https://api.elsevier.com

Переопределение для тестирования через прокси/мок

SCOPUS_REQUEST_TIMEOUT_MS

необязательно

15000

Таймаут на каждый запрос

LOG_LEVEL

необязательно

info

debug | info | warn | error

PORT

только для HTTP-режима

3000

Порт для httpServer.ts (большинство хостов задают его автоматически)

HOST

только для HTTP-режима

0.0.0.0

Адрес привязки для httpServer.ts

MCP_HTTP_AUTH_TOKEN

HTTP-режим, настоятельно рекомендуется

—

Если задан, /mcp требут Authorization: Bearer <token>

MCP_ALLOWED_HOSTS

HTTP-режим, необязательно

—

Разрешённый список заголовков Host через запяту (защита от DNS-rebinding)

Сначала проверьте подключение

Прежде чем подключать сервер к какому-либо 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, поэтому при прямом запуске в терминале он просто будет ждать JSON-RPC на stdin — это нормально. Его запускает 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 (%APPDATA%\Claude\claude_desktop_config.json в Windows, ~/Library/Application Support/Claude/claude_desktop_config.json в macOS), затем перезапустите 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), а не опускатся — проверяйте 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 символов.

  • Журналы идут в stderr в виде однострочного JSON (никогда в stdout — stdout зарезервирован для протокола MCP на stdio-транспорте), а также дописываются в logs/scopus-mcp.log.

  • Установите LOG_LEVEL=debug для большей детализации или LOG_LEVEL=error, чтобы уменьшить количество вывода.

Развёртывание на удалённой/серверless-платформе (Render, Railway и др.)

Транспорт stdio (src/index.ts) работает только с MCP-клиентами, которые могут запускать локальный процес — по сети к нему обратиться нельзя. Чтобы развернуть этот сервер удалённо, используйте вместo входную точку Streamable HTTP: src/httpServer.ts. Она обслуживает те же три инструмента на POST /mcp и добавляет GET /healthz эндпоинт для проверок здоровья платформы.

Ни Render, ни Railway не являются по-настоящему "serverless" (нет масштабирования до нуля и холодных стартов посреди запроса) — оба запускают это как обычный постоянный процес Node, что и нужно такому протоколу с состоянием, как MCP. Считайте "serverless-платформу" здесь "управляемым хостингом Node".

Render

  1. Запуштите этот репозиторий (или только папку mcp-server/) на GitHub.

  2. В панели Render: New → Web Service, подключите репозиторий, установите root directory в mcp-server, если это подпапка более крупного репозитория.

  3. Build command: npm install && npm run build

  4. Start command: npm run start:http

  5. В разделе Environment добавьте:

    • SCOPUS_API_KEY = ваш ключ (пометь его как секрет)

    • MCP_HTTP_AUTH_TOKEN = длинная случайная строка, которую вы генерируете (например, openssl rand -hex 32)

    • по желанию MCP_ALLOWED_HOSTS = имя вашего хоста Render, например scopus-mcp.onrender.com

  6. Render установит PORT авотомотически — httpServer.ts читает его, никаких действй не нужно.

  7. Разверните. Путь для проверки здоровя: /healthz.

Railway

  1. New Project → Deploy from GitHub repo, при необходимости укажите корневой католог сервиса mcp-server.

  2. Railway авотомотически определяет Node; если он не запускает нужную команду, укажите:

    • Build command: npm install && npm run build

    • Start command: npm run start:http

  3. В Variables добавьте SCOPUS_API_KEY и MCP_HTTP_AUTH_TOKEN, как выше.

  4. Railway авотомотически внедряет PORT.

  5. После развёртывания ваш 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 — сервер журналирует предупреждение при запуске, если он не установлен.

  • Сервер авотомотически включатет защиту от DNS-rebinding для localhost/127.0.0.1; для настоящего 0.0.0.0 развёртывания укажите MCP_ALLOWED_HOSTS = имя хоста вашей платформы.

  • Ротируйте SCOPUS_API_KEY и MCP_HTTP_AUTH_TOKEN через менеджер секретов платформы, никогда не коммитя их в репозиторий.

  • Рассмотрите возможность разместить перед сервисом собственный лимит запросов платформы / обратный прокси для публичных развёртываний, в дополнение к собственным лимитам Elsevier на ключ.

Устранение неполадок

Симптом

Вероятная причина

SCOPUS_API_KEY is not set

.env отсутствует/не загружен, или вы работаете в оболочке, где он не экспортирован

kind: "unauthorized", HTTP 401/403

Неверный ключ, или у ключа нет прав Scopus Search, или отсутствует SCOPUS_INST_TOKEN для доступа вне кампуса

kind: "rate_limited", HTTP 429

Достигнут лимит скорсти/квоты Elsevier для ключа — отступите и повторите через retryAfterSeconds

kind: "not_found", HTTP 404

scopusId не существут или введён с ошибкой

kind: "network_error" / "timeout"

Нет доступа в интернет с этой машины/хоста, корпоративный прокси блокирут api.elsevier.com, или SCOPUS_REQUEST_TIMEOUT_MS слишком мал

Вызовы инструментов молча ничего не делают в stdio-клиенте

Что-то записало в stdout — проверьте, что вы не добавили случайный console.log; используйте logger (stderr) вместo

Лицензия

MIT

Available Tools

3 tools
get_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).

NameRequiredDescriptionDefault
scopusIdYesThe Scopus ID of the article, e.g. "85123456789".

TDQS

A4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

NameRequiredDescriptionDefault
scopusIdYesThe Scopus ID of the article, e.g. "85123456789" (the "SCOPUS_ID:" prefix, if present, is stripped automatically).

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

NameRequiredDescriptionDefault
countNoNumber of results to return (default 10, max 25).
queryYesSearch 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

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

  1. 3 tool updatesv1.0.0
    • First observedget_article_abstract
    • First observedget_article_details
    • First observedsearch_scopus

TDQS

A4.2/5.0

Scored across 3 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count4/5

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.

Completeness4/5

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

ActivityStale
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    F
    maintenance
    Provides 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.
    5
    133 PyPI
    47
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to search and retrieve real academic papers from Scopus, preventing citation hallucination by providing accurate paper metadata, author info, and citation analysis.
    15
    3
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI agents to search and retrieve academic papers, author profiles, and citation data from the Scopus database via MCP tools.
    7
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables searching Elsevier's Scopus database for scientific literature, retrieving abstracts and metadata, and exporting results in RIS or BibTeX format.
    21 PyPI
    1
    MIT