GRaDOS
Graduate Research and Document Operating System
The enrichment-grade MCP server for academic paper search and full-text extraction. For science.
GRaDOS gives AI agents (Claude, Codex, etc.) the ability to search academic databases, download full-text papers through paywalls, and synthesize citation-grounded answers. It is designed for campus network environments where institutional access provides database permissions.
Architecture
User Question
|
v
SKILL.md (6-step academic protocol)
|
├─ Step 0: Check Local Paper Library (mcp-local-rag)
│ └─ Semantic + keyword search over previously downloaded papers
├─ Step 1: Query Decomposition
├─ Step 2: Relevance Screening (abstract / title filtering)
├─ Step 3: Full-Text Extraction & Indexing
│ ├─ Waterfall Fetch: TDM API → Unpaywall OA → Sci-Hub → Headless Browser
│ ├─ Progressive Parse: LlamaParse → Marker (local GPU) → pdf-parse
│ ├─ QA Validation: length + paywall detection + structure + title match
│ ├─ PDF saved to downloads/ (archival)
│ └─ Markdown saved to papers/ (RAG-indexed by mcp-local-rag)
├─ Step 4: Synthesis & Citation (Chinese output)
└─ Step 5: Double-Check Protocol (anti-hallucination)
MCP Tools exposed:
| Server | Tool | Description |
|---|---|---|
| GRaDOS | search_academic_papers | Waterfall search across Scopus, Web of Science, Springer, Crossref, PubMed. Deduplicates by DOI. |
| GRaDOS | extract_paper_full_text | 4-stage fetch + 3-stage parse + QA validation. Returns Markdown. Auto-saves .md to papers directory. |
| GRaDOS | save_paper_to_zotero | Saves cited paper metadata to Zotero web library via API. Called after synthesis for papers used in the answer. |
| mcp-local-rag | query_documents | Semantic + keyword search over locally indexed papers. |
| mcp-local-rag | ingest_file | Index a paper's Markdown file into the local RAG database. |
| mcp-local-rag | list_files | List all indexed papers with status. |
Installation
Option A: npm (recommended)
npm install -g grados
# Generate config file in your working directory
grados --init
# Edit the config with your API keys
# (see mcp-config.example.json for all options)
Option B: From source
git clone https://github.com/STSNaive/GRaDOS.git
cd GRaDOS
npm install
npm run build
cp mcp-config.example.json mcp-config.json
# Edit mcp-config.json with your API keys
Configure your MCP client
Claude Code:
claude mcp add --transport stdio grados -- npx -y grados
Codex:
codex mcp add grados -- npx -y grados
Or configure manually — Claude Code (.claude/settings.json):
{
"mcpServers": {
"grados": {
"command": "npx",
"args": ["-y", "grados"],
"cwd": "/path/to/directory/containing/mcp-config.json"
}
}
}
Codex (~/.codex/config.toml):
[mcp_servers.grados]
command = "npx"
args = ["-y", "grados"]
cwd = "/path/to/directory/containing/mcp-config.json"
Optional: Install Marker (high-quality local PDF parsing)
Marker uses deep learning models to convert PDFs to Markdown with much better accuracy than the built-in parser (pdf-parse). It is the recommended parser for production use.
Prerequisites: Python 3.12 (required by marker-pdf). Optional: NVIDIA GPU + CUDA for significant speedup.
Install:
cd marker-worker
.\install.ps1 # Auto-detect CPU/GPU
.\install.ps1 -Torch cuda # Force GPU (CUDA)
.\install.ps1 -Torch cpu # Force CPU
The install script will:
- Set up a Python 3.12 virtual environment (via
uv) - Install
marker-pdf==1.10.2and PyTorch - Download model weights and fonts to
marker-worker/.cache/(first run only, ~1 GB)
Enable in config: After installation, update mcp-config.json to enable Marker:
{
"extract": {
"parsing": {
"markerTimeout": 120000,
"order": ["Marker", "Native"],
"enabled": {
"LlamaParse": false,
"Marker": true,
"Native": true
}
}
}
}
Marker is part of the progressive parsing waterfall: if it fails or times out, GRaDOS automatically falls back to Native (pdf-parse). The markerTimeout setting (milliseconds) controls how long to wait before falling back (default: 120 seconds).
Verify: Run the smoke test to confirm Marker is working:
node tests/mcp-smoke.mjs
If Marker is active, the log will show:
[Marker] Converting PDF with local Marker worker...
✨ Marker successfully converted PDF to Markdown.
Integrated Paper Knowledge Base
GRaDOS builds a local paper knowledge base by combining three components:
GRaDOS mcp-local-rag
│ │
1. Fetch PDF ─────────┤ │
2. Parse to Markdown ─┤ │
3. QA Validation ─────┤ │
│ │
▼ ▼
┌─────────────┐ ┌──────────────────┐
│ downloads/ │ (PDF, archival) │ LanceDB vectors │
│ papers/ │ ──── ingest ─────► │ all-MiniLM-L6-v2 │
└─────────────┘ (Markdown, RAG) └──────────────────┘
Storage separation: PDFs and Markdown are stored in separate directories to prevent duplicate indexing:
| Directory | Content | Purpose | Configured by |
|---|---|---|---|
downloads/ | Raw .pdf files | Archival only, not indexed | extract.downloadDirectory |
papers/ | Parsed .md files (with YAML front-matter) | Indexed by mcp-local-rag | extract.papersDirectory |
Each Markdown file includes structured front-matter:
---
doi: "10.1038/s41598-025-29656-1"
title: "Triple-negative complementary metamaterial..."
source: "Unpaywall OA"
fetched_at: "2026-03-17T12:00:00.000Z"
---
Database workflow:
- Extract — GRaDOS downloads a PDF and parses it (Marker or pdf-parse), saves
.pdftodownloads/and.mdtopapers/ - Ingest — The AI agent calls
ingest_file(mcp-local-rag) on the new.mdfile, which embeds it into a local LanceDB vector store usingall-MiniLM-L6-v2embeddings - Query — On future questions, the SKILL.md protocol checks the local library first via
query_documents(semantic + keyword search), avoiding redundant API calls and re-extraction - Manage — Use
list_filesto see all indexed papers,delete_fileto remove outdated entries
Note: mcp-local-rag does NOT auto-scan directories. Papers must be explicitly ingested via the
ingest_filetool. The SKILL.md protocol handles this automatically at Step 3.
Optional: Install mcp-local-rag (local paper library with RAG)
mcp-local-rag provides a local paper library with semantic search. GRaDOS automatically saves parsed Markdown files to a papers/ directory that mcp-local-rag indexes and makes searchable. No Python required — it's pure Node.js, just like GRaDOS.
Register with your MCP client (one command):
# Claude Code
claude mcp add local-rag -- npx -y mcp-local-rag
# Codex
codex mcp add local-rag -- npx -y mcp-local-rag
Or configure manually (.claude/settings.json):
{
"mcpServers": {
"grados": {
"command": "npx",
"args": ["-y", "grados"],
"cwd": "/path/to/project"
},
"local-rag": {
"command": "npx",
"args": ["-y", "mcp-local-rag"],
"env": {
"BASE_DIR": "/path/to/project/papers"
}
}
}
}
Important:
BASE_DIRmust point to the same directory asextract.papersDirectoryinmcp-config.json(default:./papers).
How it works:
GRaDOS extracts paper mcp-local-rag indexes papers/
│ │
▼ ▼
downloads/ LanceDB vector store
└── 10_1234_xxxxx.pdf (archival) ┌───────────────────┐
│ query_documents │ ◄── AI Agent
papers/ │ ingest_file │
├── 10_1234_xxxxx.md ─────────────► │ list_files │
└── 10_5678_yyyyy.md ─────────────► │ delete_file │
└───────────────────┘
- GRaDOS saves raw PDFs to
downloads/(archival, not indexed). - GRaDOS saves parsed Markdown (with YAML front-matter: DOI, title, source) to
papers/. - The AI agent calls
ingest_fileon each new.mdfile to index it into mcp-local-rag's vector database. - Next time, the SKILL.md protocol checks the local library first via
query_documents, saving API calls and extraction time.
Optional: Zotero web library integration
GRaDOS can automatically save cited papers to your Zotero web library after each research session. No desktop client required — it uses the Zotero Web API directly.
Setup:
- Get your API key at
https://www.zotero.org/settings/keys→ New Key → check "Write Access". - Get your library ID (numeric user ID shown on the same page as "Your userID for use in API calls").
- Add both to
mcp-config.json:
{
"zotero": {
"libraryId": "1234567",
"libraryType": "user",
"defaultCollectionKey": ""
},
"apiKeys": {
"ZOTERO_API_KEY": "your-api-key-here"
}
}
Papers are saved as journalArticle items with title, DOI, authors, abstract, journal, year, URL, and tags. The research query topic is automatically added as a tag to keep your library organised by theme.
Configuration
All configuration lives in a single file: mcp-config.json. Run grados --init to generate one from the template.
API Keys
| Key | Source | Required | Free |
|---|---|---|---|
ELSEVIER_API_KEY | Elsevier Developer Portal | No | Yes (institutional) |
WOS_API_KEY | Clarivate Developer Portal | No | Yes (starter) |
SPRINGER_meta_API_KEY | Springer Nature API | No | Yes |
SPRINGER_OA_API_KEY | Same as above (OpenAccess endpoint) | No | Yes |
LLAMAPARSE_API_KEY | LlamaCloud | No | Free tier |
ZOTERO_API_KEY | Zotero Settings → Keys | No | Free |
Crossref and PubMed require no API keys. Sci-Hub and Unpaywall require no keys either.
No API keys are strictly required -- GRaDOS will use whichever services are configured and skip the rest. At minimum, Crossref + PubMed + Sci-Hub work with zero configuration.
Search Priority
The search.order array controls which databases are queried first. GRaDOS searches in order and stops as soon as it has enough unique results:
{
"search": {
"order": ["Elsevier", "Springer", "WebOfScience", "Crossref", "PubMed"]
}
}
Extraction Waterfall
The extract.fetchStrategy.order controls the full-text extraction priority:
{
"extract": {
"fetchStrategy": {
"order": ["TDM", "OA", "SciHub", "Headless"]
}
}
}
Storage Directories
| Setting | Default | Description |
|---|---|---|
extract.downloadDirectory | ./downloads | Raw PDF files (archival, not indexed by RAG) |
extract.papersDirectory | ./papers | Parsed Markdown files (indexed by mcp-local-rag) |
mcp-local-rag's BASE_DIR environment variable must point to the same path as extract.papersDirectory.
SKILL.md
The skills/GRaDOS/SKILL.md file is a structured prompt that teaches the AI agent the 6-step research protocol (Step 0: local library check + Steps 1-5). Copy it into your agent's skill/prompt directory to enable the full workflow.
License
MIT