Install
$ agentstack add skill-lari-uqac-researchtools-scopus ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Scopus Skill
Prerequisites
Before running any command, verify:
- API key is set:
python -c "import os; print('OK' if os.environ.get('SCOPUS_API_KEY') else 'NOT SET')" requestsis installed:python -c "import requests; print('OK')"— if missing, runpip install requests- Network: campus network or VPN active (Scopus blocks non-institutional IPs)
If the key is missing, ask the user to run:
[System.Environment]::SetEnvironmentVariable("SCOPUS_API_KEY", "your-key", "User")
Then restart Claude Code for the variable to be visible.
Optional — Semantic Scholar fallback. Scopus search returns only the first author (dc:creator), and a few abstract records carry no author block. When a Semantic Scholar key is set, the script backfills the full ordered author list by DOI. Key env var (checked in order): S2_API_KEY, SEMANTIC_SCHOLAR_API_KEY. Without a key the public S2 pool is used (heavily throttled). The fallback is non-fatal: if S2 is unreachable or lacks the DOI, the pure-Scopus data is returned unchanged. See ## Semantic Scholar fallback.
Mode Dispatch
Parse $ARGUMENTS to determine the mode, then run the script from the skill directory:
cd ".claude/skills/scopus"
| If $ARGUMENTS starts with | Mode | Script call | |---|---|---| | validate | Title/DOI lookup (legacy, single-field) | python scripts/scopus_api.py validate "" | | verify | Per-field validation against Scopus — title, authors (full ordered list), journal, volume, issue, pages, year | python scripts/scopus_api.py verify "" --expected-title "..." --expected-authors "..." --expected-journal "..." --expected-volume "..." --expected-issue "..." --expected-pages "..." --expected-year "YYYY" | | cite | Full metadata by DOI (now includes volume, issue, pages, full author list) | python scripts/scopus_api.py cite "" | | author | Author profile | python scripts/scopus_api.py author "" | | journal | Venue metadata — journal, conference proceeding, book series, trade journal (SJR, CiteScore, publisher, ISSN/ISBN, venue type) | python scripts/scopus_api.py journal "" [--fallback-doi ""] | | review | Literature review | python scripts/scopus_api.py search "" --count 15 then synthesize | | download | Full-text retrieval into a project refs/ dir (Elsevier -> Semantic Scholar -> publisher PDF with browser-TLS (curl_cffi) + Akamai interstitial solver + curl fallback -> Unpaywall -> arXiv -> PMC -> validated landing HTML) | python scripts/download_pdf.py doi "" --latex "" or python scripts/download_pdf.py bib "" --latex "" | | batch | Batch corpus pipeline — strict TITLE() title-to-DOI resolution (no weak-hit fallback), cite enrichment, venue grading A-D, BibTeX generation (doi + clickable url, at-free excluded blocks, forbidden-char normalization) | python scripts/bib_batch.py all candidates.json --corpus corpus.json --bib review.bib (modes: resolve, enrich, bib, all) | | anything else | Search (optional --year_min YYYY to constrain to recent papers) | python scripts/scopus_api.py search "" --count 10 |
Output Formatting
Search results
Present as a numbered list:
[1] Title. Author et al. (Year). Journal. DOI: https://doi.org/...
[2] ...
Validate
Report ✓ Found or ✗ Not found, then show the full metadata block (title, authors, journal, year, DOI, citations). Use this only as a coarse existence check — for reference auditing prefer verify.
Verify (field-by-field validation)
This is the canonical mode for reference auditing. A paper is considered valid only when every supplied field matches Scopus. The fields checked are:
| Field | What is compared | |---|---| | title | normalized lowercase, punctuation stripped | | authors | each author position is checked independently — surname must match and initial must agree. Mismatched 2nd / 3rd authors are a recurrent issue and are reported per position | | journal | publication name. Covers four venue types: journal, conference / proceedings, book (monograph or edited volume), and book series. The comparison is the same string match; venue type is reported separately by the journal mode | | volume | numeric component only (tokens such as Vol., Volume are stripped) | | issue | numeric component only (No., Issue, n° stripped) | | pages | normalized to start-end form (handles –, —, --, pp.) | | year | digits only |
Output schema:
{
"mode": "verify",
"query": "10.xxxx/yyyy",
"resolution": "doi" | "title-exact" | "title-best-match" | "not-found",
"scopus_doi": "10.xxxx/yyyy",
"valid": true | false,
"mismatched_fields": ["volume", "issue", "authors"],
"field_checks": [ { "field": "...", "match": true|false|null, "expected": "...", "scopus": "..." } ],
"scopus_record": { "title": "...", "authors": [...], "journal": "...", "volume": "...", ... }
}
match: null means the caller did not supply that field — it is not treated as a passing check.
Review mode
- Run search with
--count 15 - For each paper that has a DOI, run
citeto retrieve the full abstract - Identify 3–5 themes across the papers
- Write 3–5 sentences per theme, citing papers with
[N] - Append a numbered reference list
- Append a BibTeX block ready to paste into LaTeX
Author
Show: full name, affiliation, h-index, document count, top 5 papers by citation.
Venue (journal mode)
The journal mode covers every venue type Scopus indexes:
| venue_type value | Examples | SJR quartile rule | | --- | --- | --- | | journal | IEEE Trans., Elsevier journals | Q1–Q4 by SJR | | conference proceeding | IEEE conference proceedings with ISSN, Springer LNCS | Q1–Q4 by SJR when present | | trade journal | industry magazines | Q1–Q4 by SJR when present | | book series | Springer Lecture Notes, Studies in Computational Intelligence | SJR sometimes assigned | | book (via --fallback-doi) | one-off monographs, edited volumes without ISSN | SJR not applicable — publisher approval is the only criterion | | unknown | venue not found in the Serial Title API and no fallback DOI | mark [VENUE UNVERIFIED] |
For books and edited volumes without ISSN, the Serial Title API returns no result. Provide --fallback-doi "" so the script can resolve the venue via the Abstract Retrieval API and surface aggregation_type and publisher — the response then carries "source": "abstract-retrieval-fallback".
PDF retrieval
scripts/download_pdf.py fetches the full-text PDF of references that are already fully known (validated DOI + metadata) and stores them in a refs/ directory placed directly under the LaTeX project. It is a separate script — scopus_api.py stays a pure JSON metadata client and never writes files.
Two subcommands:
# single reference, refs/ resolved next to main.tex
python scripts/download_pdf.py doi "10.1109/TRO.2024.1" --citekey Smith2024 --latex "path/src/main.tex"
# whole bibliography; --bib path explicit, or auto-discovered from \bibliography{} in the .tex
python scripts/download_pdf.py bib "path/src/assets/references.bib" --latex "path/src/main.tex"
python scripts/download_pdf.py bib --latex "path/src/main.tex"
Behaviour:
- Output dir =
dirname(main.tex)/refs(or an explicit--out-dir). No path is
hardcoded; everything is derived from --latex / --bib / --out-dir.
- Filename =
.pdfwhen known (stable presence check), else
__.pdf.
- Presence-gated: an existing target file is skipped — no re-download.
- Source chain: 1) Elsevier Full-Text API (
SCOPUS_API_KEYenv, read like every
other mode; optional --insttoken for off-campus). 2) Semantic Scholar openAccessPdf as the fallback when Scopus cannot deliver. Works for OA papers without the VPN.
- Validation on every fetch: HTTPS-only, capped redirect hops,
%PDFmagic-byte
check (rejects publisher HTML "access denied" pages), and a 100 MB size cap. Atomic write via a *.part rename.
- Reports:
refs/_manifest.json(per-reference file + source + status) and
refs/_failed.md (DOI links to fetch manually on the UQAC network).
Env var: SCOPUS_API_KEY (Windows user variable). The Elsevier source is skipped if it is unset; the Semantic Scholar fallback still runs.
Semantic Scholar fallback
scripts/semantic_scholar_api.py is the fallback metadata source. It resolves a paper by DOI on the Academic Graph API and returns authors in the same {surname, given_name, initials, display} shape as Scopus, so the two lists are directly comparable in verify mode.
| Concern | Behaviour | |---|---| | Rate limit | Hard 1 request/second, cumulative across all endpoints. _throttle() enforces a >= 1.05 s gap; do not bypass. | | Coverage | DOI-precise lookup only. If S2's DOI index lacks the paper (404), no authors are returned — by design, to never substitute a wrong author list during an audit. | | Trigger | Auto for cite/verify when Scopus returns 0 authors. For search, opt-in with --enrich-authors (one throttled S2 call per result DOI). | | Output marker | Every enriched record carries authors_source: "scopus" \| "semantic_scholar". Search results gain authors_full (list) when enriched. | | Disable | Pass --no-s2 to any call for pure-Scopus behaviour. |
Standalone testing:
python scripts/semantic_scholar_api.py authors "10.1023/A:1010933404324"
python scripts/semantic_scholar_api.py paper "10.1023/A:1010933404324"
Search with author backfill:
python scripts/scopus_api.py search "soft robotics actuator" --count 5 --enrich-authors
Error Handling
| Error | Action | |---|---| | 401 Unauthorized | API key invalid — ask user to verify SCOPUS_API_KEY | | 403 Forbidden | Not on institution network — ask user to connect to UQAC VPN or provide --insttoken | | 429 Too Many Requests | Rate limit hit — wait 60 s and retry once | | requests module missing | Run pip install requests then retry | | No results returned | Broaden search terms; suggest alternative Scopus query keywords |
For off-campus access without VPN, append --insttoken to any script call.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: LARi-UQAC
- Source: LARi-UQAC/ResearchTools
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.