# Scholar Feed (remote · mcp.scholarfeed.org)

Rank CS/AI/ML papers by citations, forecast impact, or code adoption; trace 23.2M citation edges.

- Trust score: 69/100 (medium)
- Change this week: +4
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-09-20

## Components

- remote · `mcp.scholarfeed.org`: 69/100 (this document), [markdown](https://verifymcp.io/servers/ygao2005-scholar-feed-mcp/mcp-2.md), [page](https://verifymcp.io/servers/ygao2005-scholar-feed-mcp/mcp-2)
- npm · `scholar-feed-mcp`: 94/100, [markdown](https://verifymcp.io/servers/ygao2005-scholar-feed-mcp/scholar-feed-mcp.md), [page](https://verifymcp.io/servers/ygao2005-scholar-feed-mcp/scholar-feed-mcp)

## Channel facts

- Endpoint: `https://mcp.scholarfeed.org/mcp?src=mcp-registry`
- Transports: `streamable-http`
- Auth: `none`
- Version: `3.20.0`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-09-20.

- **Endpoint Security**: 57/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - Authorisation check failed: no authorisation is required to call this server, and it exposes a tool marked destructive (unsave_paper).
  - HTTPS is enforced; there's no plaintext access path.
  - HSTS check failed: the Strict-Transport-Security header is absent.
  - DNSSEC check failed: this domain isn't protected by DNSSEC.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 66/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 8348 tokens (~309/item across 27 items; 27 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 43/100
  - Stability observed for 13 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - All 3 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.
  - An AI judge read all 28 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### How do I install the Scholar Feed MCP server?

Scholar Feed is a hosted endpoint at https://mcp.scholarfeed.org/mcp?src=mcp-registry, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add --transport http ygao2005-scholar-feed-mcp 'https://mcp.scholarfeed.org/mcp?src=mcp-registry'
```

### Cursor

```json
{
  "mcpServers": {
    "ygao2005-scholar-feed-mcp": {
      "url": "https://mcp.scholarfeed.org/mcp?src=mcp-registry"
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "ygao2005-scholar-feed-mcp": {
      "type": "http",
      "url": "https://mcp.scholarfeed.org/mcp?src=mcp-registry"
    }
  }
}
```

### Codex

```toml
[mcp_servers.ygao2005-scholar-feed-mcp]
url = "https://mcp.scholarfeed.org/mcp?src=mcp-registry"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ygao2005-scholar-feed-mcp": {
      "type": "remote",
      "url": "https://mcp.scholarfeed.org/mcp?src=mcp-registry",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add ygao2005-scholar-feed-mcp --url 'https://mcp.scholarfeed.org/mcp?src=mcp-registry' --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  ygao2005-scholar-feed-mcp:
    url: "https://mcp.scholarfeed.org/mcp?src=mcp-registry"
```

### Netclaw

```json
{
  "McpServers": {
    "ygao2005-scholar-feed-mcp": {
      "Transport": "http",
      "Url": "https://mcp.scholarfeed.org/mcp?src=mcp-registry"
    }
  }
}
```

### Vellum

```bash
assistant mcp add ygao2005-scholar-feed-mcp -t streamable-http -u 'https://mcp.scholarfeed.org/mcp?src=mcp-registry'
```

### Other

```json
{
  "mcpServers": {
    "ygao2005-scholar-feed-mcp": {
      "type": "http",
      "url": "https://mcp.scholarfeed.org/mcp?src=mcp-registry"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-09-20 (score 69, +1)

No change was recorded against any check on this day. Stability & Change Management went from 40 to 43. That category is still filling its 30-day observation window: 12 days of observed history at the previous scan, 13 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-18 (score 68, +1)

No change was recorded against any check on this day. Stability & Change Management went from 33 to 37. That category is still filling its 30-day observation window: 10 days of observed history at the previous scan, 11 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-16 (score 67, +1)

No change was recorded against any check on this day. Stability & Change Management went from 27 to 30. That category is still filling its 30-day observation window: 8 days of observed history at the previous scan, 9 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-14 (score 66, +1)

No change was recorded against any check on this day. Stability & Change Management went from 20 to 23. That category is still filling its 30-day observation window: 6 days of observed history at the previous scan, 7 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-11 (score 65, +1)

No change was recorded against any check on this day. Stability & Change Management went from 10 to 13. That category is still filling its 30-day observation window: 3 days of observed history at the previous scan, 4 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-09 (score 64, +1)

No change was recorded against any check on this day. Stability & Change Management went from 3 to 7. That category is still filling its 30-day observation window: 1 days of observed history at the previous scan, 2 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-08 (score 63, 0)

- [functional improvement] Stability: unverified → 0.03

### 2026-09-07 (score 63)

First indexed and scored.

## MCP tools (27)

### `search_papers` (~1788 tokens)

Search Papers

Search Scholar Feed's 600k+ CS/AI/ML paper corpus. Semantic (embedding) search by default, so it finds conceptually related work even when the wording differs. EVERY PARAMETER DOCUMENTS ITS OWN BEHAVIOUR AND COVERAGE LIMITS — read the ones you intend to use; this description covers only what no single parameter can tell you. RETRIEVAL LIMIT: semantic ranking favours recent, stylistically-matched papers and routinely MISSES the old high-citation anchor of a field (H2O for KV eviction, GRIT for unified embedding+generation). To reach a field's canonical work, read the top-5 abstracts for repeated baseline mentions ('we compare against X') and look that name up directly, or call get_foundational_lineage. THREE UNRELATED NOTIONS OF IMPACT, easily confused: proven citations (sort='impactful', min_citations) | a ~90-day forecast percentile that is NULL on older papers and therefore excludes them (sort='trending', impact_min) | GitHub adoption (sort='community', min_stars). YOUR LIBRARY IS MARKED INLINE on authenticated calls: each hit carries is_saved and is_read, and a hit you previously annotated carries note_text — your own earlier verdict. Read note_text INSTEAD of re-deriving a conclusion from the abstract; re-judging a paper you already ruled on is the most common way an agent wastes a research session. is_saved=false is a real measurement; on anonymous calls these keys are absent entirely, so never read a missing is_saved as false. Papers new to you are ranked exactly as before — nothing is demoted for being unseen.

Input parameters:

- `anchor_paper_id` (string): Return papers similar to this arXiv paper ID. When set, q is ignored and results carry similarity_score. Example: '2407.15831'.
- `category` (string): Filter by arXiv category e.g. 'cs.AI', 'cs.LG'
- `contribution_type` (string): Filter by paper's contribution type
- `cursor` (string): Cursor from previous response's next_cursor for keyset pagination
- `dataset` (string): Filter to papers that evaluate on a specific dataset e.g. 'MMLU', 'ImageNet'
- `days` (integer): Limit to papers published within N days
- `exclude_ids` (array): arXiv IDs to exclude from results (for deduplication across chained calls)
- `fields` (string): Comma-separated list of fields to return (e.g. 'arxiv_id,title,llm_summary,llm_novelty_score'). If omitted, returns the lean 12-field default unless verbose=true.
- `github_url_exists` (boolean): Filter on whether the paper has a linked GitHub URL (true = only papers with a repo). Stricter than has_code (which counts any code link).
- `has_code` (boolean): Filter to papers with a linked code release (has_code=true). Surfaces runnable/reproducible work — pair with min_stars/sort='community' to find the papers practitioners actually adopt.
- `impact_min` (integer): Minimum impact_pct (0-100), e.g. 80 = top 20% FORECAST impact. This is a RISING-WORK filter: impact_pct is only computed for the last ~90 days, so impact_min restricts results to recent papers predic…
- `limit` (integer): Results per page (max 50)
- `method_category` (string): Filter by method category e.g. 'reinforcement learning', 'transformer'
- `method_name` (string): Filter to papers introducing/using a specific named method e.g. 'LoRA', 'YOLO', 'DPO'. Case-insensitive substring match on the extracted method_name field.
- `min_citations` (integer): Minimum real citation count. Unlike impact_min (a ~90-day FORECAST percentile), this filters on PROVEN citations and keeps established/canonical papers.
- `min_stars` (integer): Minimum GitHub stars on the paper's linked repo. A proxy for engineering adoption — surfaces work that practitioners are actually running/building on. Pair with sort='community' to rank by it. COVERA…
- `mode` (string): Search mode. 'semantic' (default) uses embedding similarity — finds conceptually related papers even without exact keyword matches. 'keyword' uses Postgres full-text search — faster but only matches…
- `novelty_min` (number): Minimum novelty score (0-1). Use 0.5+ for novel papers.
- `page` (integer): Page number
- `published_after` (string): Only papers published on or after this date, 'YYYY-MM-DD'. Use with published_before to bound an arbitrary date window (days only gives a rolling N-day lookback).
- `published_before` (string): Only papers published on or before this date, 'YYYY-MM-DD'. Pair with published_after for an explicit window.
- `q` (string): Search query keywords. REQUIRED unless (a) anchor_paper_id or scope_to_citations_of is set (anchor mode ignores q and returns papers similar to the anchor), or (b) sort is one of 'trending' / 'recent…
- `scope_to_citations_of` (string): Restrict search to this paper's citation graph, ranked by relevance to q. Pass the arXiv ID of the paper whose citations you want to search within.
- `sort` (string): Result ranking — a relevance↔impact dial plus time-based and adoption orders. 'relevance' (default) = best topical match. 'balanced' = relevant AND well-cited. 'impactful' = the most-cited (proven-in…
- `task` (string): Filter by task e.g. 'image classification', 'question answering' (partial match)
- `task_category` (string): Filter by broad research area
- `verbose` (boolean): If true, returns the full 28-field paper shape (method/task/dataset extraction, application_domain, baselines, etc.). Default false returns the lean 12-field set. Ignored when `fields` is provided.

Output parameters:

- `direction` (string): Citation direction (get_citations: citing | cited_by).
- `limit` (number)
- `mode` (string): Search mode actually applied.
- `next_cursor`: Keyset cursor for the next page, or null when exhausted.
- `not_found` (array): Requested IDs that had no match.
- `note`
- `page` (number)
- `papers` (array): Matched / returned papers.
- `sort` (string): Search sort order actually applied.
- `topic` (string)
- `total`: Total results available for the query. null when the count was skipped (query-less browse, or the count query timed out).

### `get_paper` (~438 tokens)

Get Paper

Get full details for one or more papers by arXiv ID. Pass a single-element array for one paper; pass multiple IDs to batch-fetch up to 50 papers in one call. Pass format='bibtex' to get a .bib citation entry (bibtex is single-paper only; for multi-paper bibtex, call repeatedly). Default returns a lean 13-field shape (arxiv_id, title, authors, year, categories, has_code, github_url, citation_count, venue_name, llm_summary, llm_significance, llm_novelty_score, impact_pct — where impact_pct is the ML-forecast impact percentile 0-100 computed WITHIN the paper's own arXiv-category cohort, so it is a cohort-relative rank rather than an absolute score, and is NULL on older papers outside the recent ~90-day scoring window). Pass verbose=true for the full shape with structured extraction (method_name, contribution_type, task_category, datasets, baselines) and institution_tags. Use fields='arxiv_id,title,abstract' to select an exact subset, or fetch_fulltext with sections='all' for the full paper.

Input parameters:

- `arxiv_ids` (array, required): One or more arXiv IDs. Single-paper lookup uses [id]; batch lookup passes multiple IDs (max 50). Example: ['2407.15831'] or ['2407.15831', '2402.09906'].
- `fields` (string): Comma-separated list of fields to return (e.g. 'arxiv_id,title,llm_summary,abstract'). If omitted, returns the lean 12-field default unless verbose=true.
- `format` (string): Response format. 'json' (default) returns structured paper data. 'bibtex' returns a .bib citation entry. Bibtex mode uses the first ID in arxiv_ids.
- `verbose` (boolean): If true, returns the full 28-field paper shape (method/task/dataset extraction, application_domain, baselines, etc.). Default false returns the lean 12-field set. Ignored when `fields` is provided.

Output parameters:

- `bibtex` (string): BibTeX entry (format='bibtex').
- `count` (number)
- `direction` (string): Citation direction (get_citations: citing | cited_by).
- `format` (string)
- `limit` (number)
- `message` (string)
- `mode` (string): Search mode actually applied.
- `next_cursor`: Keyset cursor for the next page, or null when exhausted.
- `not_found` (array): Requested IDs that had no match.
- `note`
- `ok` (boolean)
- `page` (number)
- `papers` (array): Matched / returned papers.
- `sort` (string): Search sort order actually applied.
- `topic` (string)
- `total`: Total results available for the query. null when the count was skipped (query-less browse, or the count query timed out).

### `get_citations` (~243 tokens)

Get Citations

Get the citation graph for a paper, sorted by citing-paper rank_score (highest-impact first). 'citing' = outgoing references this paper cites; 'cited_by' = incoming citations from other papers. Default response is a lean 12-field shape per paper — pass verbose=true for the full 28-field shape.

Input parameters:

- `arxiv_id` (string, required): arXiv ID of the paper
- `direction` (string): 'citing' = outgoing references this paper cites; 'cited_by' = incoming citations from other papers
- `exclude_ids` (array): arXiv IDs to exclude from results (for deduplication across chained calls)
- `fields` (string): Comma-separated list of fields to return (e.g. 'arxiv_id,title,llm_summary,llm_novelty_score'). If omitted, returns the lean 12-field default unless verbose=true.
- `limit` (integer): Number of papers to return (max 50)
- `verbose` (boolean): If true, returns the full 28-field paper shape. Default false returns the lean 12-field set. Ignored when `fields` is provided.

Output parameters:

- `direction` (string): Citation direction (get_citations: citing | cited_by).
- `limit` (number)
- `mode` (string): Search mode actually applied.
- `next_cursor`: Keyset cursor for the next page, or null when exhausted.
- `not_found` (array): Requested IDs that had no match.
- `note`
- `page` (number)
- `papers` (array): Matched / returned papers.
- `sort` (string): Search sort order actually applied.
- `topic` (string)
- `total`: Total results available for the query. null when the count was skipped (query-less browse, or the count query timed out).

### `fetch_fulltext` (~214 tokens)

Fetch Full Text

Extract paper content from an arXiv paper's LaTeX source, falling back to PDF text. Two modes: 'results' (default) returns ~800 chars of results/experiments + up to 3 table captions — lean, ideal for checking a reported number. 'all' returns full paper sections (abstract, introduction, related work, method, results, conclusion) at up to 3000 chars each + 5 table captions, ~15KB, so prefer 'results' unless you need the whole paper. Content is available for ~95% of arXiv papers; a 404 means neither LaTeX nor PDF extraction yielded text. May take a few seconds.

Input parameters:

- `arxiv_id` (string, required): arXiv ID of the paper
- `sections` (string): 'results' (default): lean ~800-char results/experiments excerpt + table captions. 'all': full paper (abstract, intro, method, results, conclusion, related work) — much larger payload.

Output parameters:

- `arxiv_id` (string)
- `results_text`: Results/experiments excerpt (default 'results' mode).
- `sections` (object): Per-section text (sections='all').
- `source` (string): Where the text came from (e.g. arxiv).
- `table_captions` (array)

### `find_author` (~283 tokens)

Find Author

Two-mode author tool. Provide exactly one of q or id. Q-MODE (q=...): search for researchers by topic or name — uses embedding similarity for topics ('efficient LLM inference'), fuzzy matching for names ('Yann LeCun'). Returns a list of matching authors with author_id, name, h_index, total_papers, primary_field, research_topics. ID-MODE (id=...): look up a single author profile by author_id (obtained from a previous q-mode call or from co_author_graph results). Returns h-index, total citations, global rank, primary field, novelty score distribution, research topics, code/venue scores, years active, and their top 10 papers by rank score.

Input parameters:

- `field` (string): (q-mode only) Filter by primary research field e.g. 'cs.LG', 'cs.CV', 'cs.CL'.
- `id` (integer): Author ID for direct profile lookup (id-mode). Returns the single author profile with top 10 papers. Get IDs from q-mode results or co_author_graph.
- `limit` (integer): (q-mode only) Max results to return (default 20).
- `q` (string): Topic or researcher name to search (q-mode). Returns a list of matching authors. Examples: 'efficient transformer training', 'Geoffrey Hinton'.

Output parameters:

- `authors` (array): Matching authors (q-mode).
- `h_index`
- `id` (number)
- `name` (string)
- `primary_field`
- `query` (string)
- `rank`
- `research_topics` (array)
- `search_type` (string)
- `top_papers` (array): Top papers by rank (id-mode profile).
- `total` (number)
- `total_citations`
- `total_papers`

### `co_author_graph` (~177 tokens)

Co-Author Graph

Find the co-authorship neighborhood of one or more authors. Given a list of author_ids, returns edges {from, to, papers_count, last_collab_year} where 'from' is one of the input authors and 'to' is any co-author appearing on a shared paper within the window. Use for AC reviewer triage (find conflicts), disambiguating researchers (who do they actually work with?), or expanding an author seed into a research community. window_years defaults to 10. Result is capped at 500 edges, sorted by papers_count DESC.

Input parameters:

- `author_ids` (array, required): Author IDs to query (1-25). Get author IDs via the find_author tool.
- `window_years` (integer): Only count co-authorships from the last N years (default 10, max 30).

Output parameters:

- `edge_count` (number)
- `edges` (array): Co-authorship edges {from, to, papers_count, last_collab_year}.
- `queried_author_ids` (array)
- `window_years` (number)

### `embed_text` (~225 tokens)

Embed Text

Embed a text string into a 768-dim Gemini Flash vector. Use for HyDE-style retrieval: (1) write a hypothetical short paper that would perfectly answer the user's query, (2) embed it with task_type='RETRIEVAL_DOCUMENT' (default — matches the corpus embedding side), (3) pass the resulting embedding back through search-style tools to find real papers nearest to the hypothetical. task_type='RETRIEVAL_QUERY' matches the query side and is useful for direct user-query embedding without HyDE. Pro-only — requires an SF_API_KEY on a Pro account; anonymous and free callers get a 403 pro_required. Cost: ~$0.0001/call; rate-limited at 30/minute per API key.

Input parameters:

- `task_type` (string): RETRIEVAL_DOCUMENT (default) matches paper-side embeddings — use for HyDE. RETRIEVAL_QUERY matches query-side semantic search.
- `text` (string, required): Text to embed (1-8000 chars). For HyDE flows this is your hypothetical answer/abstract.

Output parameters:

- `dimensions` (number)
- `dims` (number)
- `embedding` (array): The embedding vector (768-dim Gemini Flash).
- `model` (string)
- `task_type` (string)

### `get_field_orientation` (~188 tokens)

Get Field Orientation

Returns CANDIDATE FOUNDATIONAL PAPERS for a research topic — cheap retrieval only, no synthesis. Ranks papers by a blend of citation count (0.6 weight, captures importance) and semantic similarity to your topic (0.4 weight). Use this to bootstrap a literature survey or get a fast sense of the landscape. For a synthesized orientation report (key concepts, open problems, reading order), use the /field-guide skill which calls this tool internally. Does not require a Pro API key — no LLM calls are made.

Input parameters:

- `limit` (integer): Number of candidate papers to return (5–30, default 15).
- `topic` (string, required): Research area to orient on. Be specific for better results. Examples: 'diffusion models for protein structure prediction', 'efficient attention mechanisms for long-context LLMs', 'graph neural networ…

Output parameters:

- `direction` (string): Citation direction (get_citations: citing | cited_by).
- `limit` (number)
- `mode` (string): Search mode actually applied.
- `next_cursor`: Keyset cursor for the next page, or null when exhausted.
- `not_found` (array): Requested IDs that had no match.
- `note`
- `page` (number)
- `papers` (array): Matched / returned papers.
- `sort` (string): Search sort order actually applied.
- `topic` (string)
- `total`: Total results available for the query. null when the count was skipped (query-less browse, or the count query timed out).

### `get_foundational_lineage` (~389 tokens)

Get Foundational Lineage

Returns the FOUNDATIONAL WORK FOR A PAPER'S NICHE via the citation graph — the relative question ('what is foundational for THIS paper's specific sub-field', often itself only modestly cited) rather than the obvious global landmarks. Anchors on the paper, takes its embedding neighbourhood as the niche, and ranks what the niche cites into three tiers: `niche_roots` (the niche-specific foundations, ranked by how specifically the neighbourhood builds on them — surfaces canonical anchors that semantic search misses), `field_level` (broader secondary foundations), and `discipline` (universal landmarks like Attention Is All You Need, collapsed out of the way). Each paper carries `cited_by_in_niche` evidence so the claim is grounded, not asserted. Use this to trace prior art / lineage for a paper, or to find the canonical methods a niche is built on. Complements get_field_orientation (which is topic-anchored and retrieval-only). No Pro key and no LLM calls required.

Input parameters:

- `anchor_paper_id` (string, required): arXiv ID of the paper to anchor on, e.g. '2504.04704' or '2504.04704v2'. The niche is built from this paper's embedding neighbourhood.
- `generality_ceiling` (boolean): When true (default), demote universally-cited landmark papers into the collapsed `discipline` tier so the niche-specific foundations lead. Set false to keep landmarks in the foundational tiers.
- `limit` (integer): Max papers in each of the niche_roots and field_level tiers (5–40, default 15).
- `scope` (string): Niche breadth: 'narrow' (~100 nearest papers, tightest sub-topic — surfaces the few-citation niche root), 'field' (~200, default), 'broad' (~400, wider area foundations).

Output parameters:

- `anchor` (string)
- `discipline` (array)
- `field_level` (array)
- `niche_roots` (array)
- `niche_size` (number)
- `note`
- `scope` (string)
- `tiers` (object): Foundational tiers: niche_roots → field_level → discipline.

### `save_paper` (~118 tokens)

Save Paper

Save a paper to the authenticated user's Scholar Feed library (bookmark). MUTATES the library and feeds the user's personalization — saved papers are the strongest signal in the For You feed and the email digest. Idempotent: calling it again on an already-saved paper leaves it saved. Requires SF_API_KEY. To file it into a named collection in one step, use add_to_collection (that also saves).

Input parameters:

- `arxiv_id` (string, required): arXiv ID of the paper to save, e.g. '2407.15831'.

Output parameters:

- `action` (string): Machine label: saved | no_change | removed | liked | created | updated | deleted.
- `arxiv_id` (string)
- `collection`: The created/affected collection, when applicable.
- `message` (string): Human-readable summary of the outcome.
- `ok` (boolean): True when the operation succeeded.
- `watch`: The created/affected watch, when applicable.

### `unsave_paper` (~115 tokens)

Unsave Paper

Remove a paper from the authenticated user's Scholar Feed library. MUTATES the library. Idempotent: removing a paper that isn't saved leaves it unsaved. Note: the saved library is a superset of all collections, so un-saving a paper ALSO removes it from every collection it was in. To keep it filed in a collection, use remove_from_collection instead (that leaves the paper saved). Requires SF_API_KEY.

Input parameters:

- `arxiv_id` (string, required): arXiv ID of the paper to remove from the library.

Output parameters:

- `action` (string): Machine label: saved | no_change | removed | liked | created | updated | deleted.
- `arxiv_id` (string)
- `collection`: The created/affected collection, when applicable.
- `message` (string): Human-readable summary of the outcome.
- `ok` (boolean): True when the operation succeeded.
- `watch`: The created/affected watch, when applicable.

### `like_paper` (~94 tokens)

Like Paper

Like a paper — a 'more like this' calibration signal that tunes the user's For You feed toward similar work. INSERT-only and idempotent (liking twice is a no-op, never un-likes). Distinct from save_paper: like expresses taste for ranking; save bookmarks for later reading. Requires SF_API_KEY.

Input parameters:

- `arxiv_id` (string, required): arXiv ID of the paper to like.

Output parameters:

- `action` (string): Machine label: saved | no_change | removed | liked | created | updated | deleted.
- `arxiv_id` (string)
- `collection`: The created/affected collection, when applicable.
- `message` (string): Human-readable summary of the outcome.
- `ok` (boolean): True when the operation succeeded.
- `watch`: The created/affected watch, when applicable.

### `list_library` (~354 tokens)

List Library

List the authenticated user's saved papers (their library), newest first. Read-only. Use this to review a reading list or to see what's already saved before saving more. Requires SF_API_KEY. SHAPE: agent callers get a lean record — `llm_summary` (~300 chars) INSTEAD of the abstract, with empty fields omitted rather than sent as null. Each paper also carries the state that makes this a knowledge base rather than a bookmark list: `note_text` (the user's own recorded verdict, when one exists), `is_read`, and `collections` (the axes it is filed under, e.g. 'AgentOPA/G4'). READ note_text FIRST. A paper carrying one was already judged in an earlier session — use that verdict instead of re-reading the paper and re-deriving it. If it is missing, consider recording one with annotate_paper so the next session inherits your conclusion. Pass verbose=true (or fields=...) only when you genuinely need the abstract or the full 28-field shape; the default is ~4x smaller and is the right choice for surveying what you already have.

Input parameters:

- `fields` (string): Comma-separated fields to return, e.g. 'arxiv_id,title,abstract'. Overrides verbose. Library state (note_text/is_read/is_saved/collections) is always included regardless.
- `limit` (integer): How many saved papers to return (max 100).
- `page` (integer): Page number for paging through a large library.
- `verbose` (boolean): Return the full paper shape (including the abstract) instead of the lean default. Costs roughly 4x the tokens — prefer llm_summary unless you specifically need the abstract's wording.

Output parameters:

- `direction` (string): Citation direction (get_citations: citing | cited_by).
- `limit` (number)
- `mode` (string): Search mode actually applied.
- `next_cursor`: Keyset cursor for the next page, or null when exhausted.
- `not_found` (array): Requested IDs that had no match.
- `note`
- `page` (number)
- `papers` (array): Matched / returned papers.
- `sort` (string): Search sort order actually applied.
- `topic` (string)
- `total`: Total results available for the query. null when the count was skipped (query-less browse, or the count query timed out).

### `list_collections` (~43 tokens)

List Collections

List the authenticated user's collections (named groups of saved papers) with paper counts. Read-only. Use before add_to_collection to see existing collections. Requires SF_API_KEY.

Output parameters:

- `collections` (array)
- `message` (string)
- `ok` (boolean)

### `create_collection` (~120 tokens)

Create Collection

Create a new named collection. MUTATES. If a collection with that name already exists, returns the existing one (get-or-create — never errors on duplicate). Use "/" to nest under a folder, e.g. "AgentOPA/Formal" — the folder is derived from the name, so there is no parent to create first. Requires SF_API_KEY.

Input parameters:

- `name` (string, required): Name for the collection, e.g. 'KV-cache compression'. Use '/' to nest: 'AgentOPA/Formal' files it under an 'AgentOPA' folder.

Output parameters:

- `action` (string): Machine label: saved | no_change | removed | liked | created | updated | deleted.
- `arxiv_id` (string)
- `collection`: The created/affected collection, when applicable.
- `message` (string): Human-readable summary of the outcome.
- `ok` (boolean): True when the operation succeeded.
- `watch`: The created/affected watch, when applicable.

### `add_to_collection` (~181 tokens)

Add to Collection

Add a paper to a collection, addressed by collection_id OR collection_name (get-or-create by name — no need to look up an id first). Nest with "/": collection_name "AgentOPA/Formal" files the paper under an "AgentOPA" folder. MUTATES: also auto-saves the paper to the library. Idempotent (adding a paper already in the collection is a no-op). Requires SF_API_KEY.

Input parameters:

- `arxiv_id` (string, required): arXiv ID of the paper to add, e.g. '2407.15831'.
- `collection_id` (string): UUID of an existing collection. Provide this OR collection_name.
- `collection_name` (string): Name of the collection. Created if it doesn't exist. Use '/' to nest, e.g. 'AgentOPA/Formal'. Provide this OR collection_id.

Output parameters:

- `action` (string): Machine label: saved | no_change | removed | liked | created | updated | deleted.
- `arxiv_id` (string)
- `collection`: The created/affected collection, when applicable.
- `message` (string): Human-readable summary of the outcome.
- `ok` (boolean): True when the operation succeeded.
- `watch`: The created/affected watch, when applicable.

### `remove_from_collection` (~107 tokens)

Remove from Collection

Remove a paper from a collection, addressed by collection_id OR collection_name. MUTATES (the paper stays in your library; it's only removed from this collection). Idempotent. Requires SF_API_KEY.

Input parameters:

- `arxiv_id` (string, required): arXiv ID of the paper to remove from the collection.
- `collection_id` (string): UUID of the collection. Provide this OR collection_name.
- `collection_name` (string): Name of the collection. Provide this OR collection_id.

Output parameters:

- `action` (string): Machine label: saved | no_change | removed | liked | created | updated | deleted.
- `arxiv_id` (string)
- `collection`: The created/affected collection, when applicable.
- `message` (string): Human-readable summary of the outcome.
- `ok` (boolean): True when the operation succeeded.
- `watch`: The created/affected watch, when applicable.

### `create_watch` (~540 tokens)

Create Watch

Create a standing watch — evaluated daily against newly-indexed papers, surfacing new matches via the email digest and via check_watches. MUTATES. Get-or-create by name (re-creating with an existing name returns it unchanged — never errors on duplicate). TWO forms: (1) the v2 STRUCTURED filter via `criteria` (collections/authors/categories/text/has_code/min_novelty/similar, AND-composed) — the composable, agent-tunable form, recommended; tune it with preview_watch first, and edit later with update_watch. Structured watches rank by 'rising' (forecasted breakout impact) by default, and tighten with min_impact_pct for an anti-noise watch that surfaces only the breakout papers in your niche. (2) a single legacy seed selector (q OR collection_name OR collection_id OR anchor_paper_id); if `criteria` is given it takes precedence. Requires SF_API_KEY.

Input parameters:

- `anchor_paper_id` (string): Watch papers similar to this arXiv ID. One seed selector only.
- `author_id` (string): Watch an author's new work, by author ID. One seed selector only.
- `category` (string): Watch an arXiv category (e.g. 'cs.LG'), filtered by novelty_min. One seed selector only.
- `collection_id` (string): Watch the neighborhood of a collection by UUID. One seed selector only.
- `collection_name` (string): Watch the neighborhood of a collection by name (resolved by the backend). One seed selector only.
- `criteria` (object): v2 STRUCTURED filter (collections/authors/categories/text/has_code/min_novelty/similar). When provided, this defines the watch (kind='filter') and the single-selector seeds above are IGNORED. This is…
- `name` (string, required): Label for the watch, e.g. 'novel KV-cache work'.
- `novelty_min` (number): Only surface papers at/above this novelty score (0..1). The signal/noise knob — raise it for 'only tell me when it matters'. Default 0.5.
- `q` (string): Semantic/keyword topic seed. One seed selector only.
- `recency_days` (integer): For a structured (criteria) watch: only consider papers from the last N days (default 7; the 'cites' relation uses 30).
- `scope_to_citations_of` (string): Watch new papers citing this arXiv ID. One seed selector only.

Output parameters:

- `action` (string): Machine label: saved | no_change | removed | liked | created | updated | deleted.
- `arxiv_id` (string)
- `collection`: The created/affected collection, when applicable.
- `message` (string): Human-readable summary of the outcome.
- `ok` (boolean): True when the operation succeeded.
- `watch`: The created/affected watch, when applicable.

### `list_watches` (~61 tokens)

List Watches

List the authenticated user's watches with name, a one-line definition summary, last_evaluated_at, and pending_hits (count of new matches since the last digest delivery). Read-only. Use before create_watch to see what's already tracked. Requires SF_API_KEY.

Output parameters:

- `message` (string)
- `ok` (boolean)
- `watches` (array)

### `check_watches` (~163 tokens)

Check Watches

Pull new matching papers since the last digest delivery, in the same shape as search_papers results. Optionally scope to one watch by watch_name OR watch_id; omit both for all watches. Read-only and idempotent — does NOT advance any watermark (only digest delivery does), so it is safe to call repeatedly (no mark-on-read). This is the in-session 'anything new on my watches?' pull. Requires SF_API_KEY.

Input parameters:

- `limit` (integer): Max hits to return (max 100).
- `watch_id` (string): Scope to one watch by UUID. Provide this OR watch_name, or neither for all.
- `watch_name` (string): Scope to one watch by name. Provide this OR watch_id, or neither for all.

Output parameters:

- `direction` (string): Citation direction (get_citations: citing | cited_by).
- `hits` (array): New watch matches (check_watches).
- `limit` (number)
- `mode` (string): Search mode actually applied.
- `next_cursor`: Keyset cursor for the next page, or null when exhausted.
- `not_found` (array): Requested IDs that had no match.
- `note`
- `page` (number)
- `since`: Watermark the hits were computed from, or null on first run.
- `sort` (string): Search sort order actually applied.
- `topic` (string)
- `total`: Total results available for the query. null when the count was skipped (query-less browse, or the count query timed out).

### `delete_watch` (~108 tokens)

Delete Watch

Delete a watch, addressed by watch_id OR name. MUTATES. Idempotent: deleting a non-existent watch is a no-op (no error). To change a watch in place (rename / novelty_min / retarget criteria) use update_watch instead of delete-and-recreate. Requires SF_API_KEY.

Input parameters:

- `name` (string): Name of the watch to delete. Provide this OR watch_id.
- `watch_id` (string): UUID of the watch to delete. Provide this OR name.

Output parameters:

- `action` (string): Machine label: saved | no_change | removed | liked | created | updated | deleted.
- `arxiv_id` (string)
- `collection`: The created/affected collection, when applicable.
- `message` (string): Human-readable summary of the outcome.
- `ok` (boolean): True when the operation succeeded.
- `watch`: The created/affected watch, when applicable.

### `update_watch` (~221 tokens)

Update Watch

Update an existing watch in place — rename, change novelty_min, or RETARGET its structured filter `criteria`. MUTATES. Address by watch_id OR name. Changing criteria replaces the definition and clears the watch's pending hits (so stale matches don't deliver); the next daily eval repopulates. Structured watches rank by 'rising' (forecasted breakout impact) by default, and tighten with min_impact_pct for an anti-noise watch that surfaces only the breakout papers in your niche. Tune the new criteria with preview_watch first. Requires SF_API_KEY.

Input parameters:

- `criteria` (object): Replace the watch's filter (becomes kind='filter'). Clears pending hits.
- `name` (string): Find the watch by its current name. Provide this OR watch_id.
- `new_name` (string): Rename the watch.
- `novelty_min` (number): New novelty floor (0..1).
- `recency_days` (integer): Window for the new criteria.
- `watch_id` (string): Find the watch by UUID. Provide this OR name.

Output parameters:

- `action` (string): Machine label: saved | no_change | removed | liked | created | updated | deleted.
- `arxiv_id` (string)
- `collection`: The created/affected collection, when applicable.
- `message` (string): Human-readable summary of the outcome.
- `ok` (boolean): True when the operation succeeded.
- `watch`: The created/affected watch, when applicable.

### `preview_watch` (~213 tokens)

Preview Watch

Dry-run a structured filter over recent papers WITHOUT creating a watch — the tuning loop. Returns {window_days, needs_similarity, match_count, sample} so you can iterate (add a category, raise min_novelty, switch the collection relation) before saving with create_watch. Structured watches rank by 'rising' (forecasted breakout impact) by default, and tighten with min_impact_pct for an anti-noise watch that surfaces only the breakout papers in your niche. NOTE: for a similarity filter, match_count is capped at 200 (the cosine fetch window) and so saturates at 200 on broad/hot topics — tune by the `sample` scores and narrow with categories/min_novelty (or a higher similar floor) rather than relying on match_count alone. Read-only. Requires SF_API_KEY.

Input parameters:

- `criteria` (object, required): The structured filter to test.
- `recency_days` (integer): Window in days (default 7; the 'cites' relation uses 30).

Output parameters:

- `match_count` (number)
- `message` (string)
- `needs_similarity` (boolean)
- `ok` (boolean)
- `sample` (array): A sample of matching papers.
- `window_days` (number)

### `find_gaps` (~262 tokens)

Find Research Gaps

Find important work you HAVEN'T saved, for a collection or topic — a 'what am I missing?' analysis. Returns two buckets: foundational_gaps (canonical citation-graph anchors in the niche, not in your library) and frontier_gaps (recent high-novelty work in the niche, not yet saved). Provide exactly one seed: collection_name OR collection_id OR topic. The backend derives the niche, runs lineage + recent-novelty search, and subtracts your saved set. Read-only. Requires SF_API_KEY (it needs your library to subtract) and is a Pro feature — free accounts receive an upgrade prompt.

Input parameters:

- `collection_id` (string): Analyze gaps for a collection by UUID. Provide exactly one seed.
- `collection_name` (string): Analyze gaps for a collection by name (resolved by the backend). Provide exactly one seed.
- `limit` (integer): Max gaps per bucket (max 50). Default 10.
- `scope` (string): Which gaps to surface: 'foundational' (canonical anchors you're missing), 'frontier' (recent novel work you haven't saved), or 'both' (default).
- `topic` (string): Analyze gaps for a free-text topic/area. Provide exactly one seed.

Output parameters:

- `foundational_gaps` (array): Canonical anchors in the niche not in your library.
- `frontier_gaps` (array): Recent high-novelty work you haven't saved.
- `message` (string)
- `ok` (boolean)

### `ask_library` (~211 tokens)

Ask Library

Answer a question using ONLY the papers you've saved — a synthesis over your library (or one collection) with inline [arXiv-ID] citations. The inverse of find_gaps (which finds important work you're MISSING): ask_library reasons over what you HAVE. Optionally scope to one collection (collection_name OR collection_id); omit both to use your whole library. Read-only. Requires SF_API_KEY (it reads your saved set). Free accounts get 1 question/month; Pro raises this to 200/day.

Input parameters:

- `collection_id` (string): Scope the answer to one collection by UUID. Omit to use your whole library.
- `collection_name` (string): Scope the answer to one collection by name (resolved by the backend). Omit to use your whole library.
- `limit` (integer): How many of your most-relevant saved papers to ground the answer on (max 20). Default 8.
- `question` (string, required): The natural-language question to answer from your saved papers.

Output parameters:

- `answer` (string): The synthesized answer with inline [arXiv-ID] citations.
- `citations` (array)
- `message` (string)
- `ok` (boolean)
- `papers` (array)

### `annotate_paper` (~413 tokens)

Annotate Paper

Record YOUR verdict on a paper — why it matters for your work, when to use it, or why you ruled it out. One note per paper, upserted (writing again replaces it), so it is safe to call repeatedly. Requires SF_API_KEY. WHY IT MATTERS: this note is the only thing that survives between sessions. list_library returns note_text on every saved paper, so a verdict written now is what a future session reads INSTEAD of re-reading the paper and re-deriving the same conclusion. WRITE A JUDGMENT, NOT A SUMMARY — the paper already carries llm_summary and an abstract, so restating what the paper says adds nothing. Write what those cannot: how it bears on YOUR problem. Prefer a claim someone could later prove wrong ("needs a labeled trace log we don't have", "our baseline — beat this on the 7B setting") over an unfalsifiable verdict ("interesting", "not very relevant"), because a mechanism can be re-checked when circumstances change and a sentiment cannot. State the basis when it is thin: a verdict formed from the abstract alone deserves "(abstract only)", since fetch_fulltext defaults to ~800 characters of the results section rather than the whole paper. Pass action='get' to read the existing note before overwriting it — worth doing when a prior session may already have judged this paper. To correct a note, just write the corrected text (it replaces).

Input parameters:

- `action` (string): 'upsert' (default) writes/replaces the note. 'get' returns the current note without changing it. There is deliberately no delete: a wrong note is corrected by overwriting it, which keeps this tool no…
- `arxiv_id` (string, required): arXiv ID of the paper to annotate, e.g. '2407.15831'.
- `note_text` (string): Your verdict (max 5000 chars). Required for the default upsert; ignored for action='get'.

Output parameters:

- `action` (string): Machine label: saved | no_change | removed | liked | created | updated | deleted.
- `arxiv_id` (string)
- `collection`: The created/affected collection, when applicable.
- `message` (string): Human-readable summary of the outcome.
- `ok` (boolean): True when the operation succeeded.
- `watch`: The created/affected watch, when applicable.

### `check_drift` (~660 tokens)

Check Drift (is my method superseded?)

Answers 'for my problem, is the method I use superseded — and by what?' over a grounded, entity-resolved knowledge base of textual critique receipts + benchmark-dominance edges (no LLM call at query time). Call with a `family` (e.g. 'rag', 'peft', 'kvcache') and a `method` (e.g. 'SnapKV', 'LoRA') to get a verdict: how superseded it is, WHO critiques it (verbatim quotes + the citing paper), WHO beats it on benchmarks (winner, numbers, condition, source paper), and the not-yet-superseded alternatives in the same sub-problem. Omit `method` to get the whole-family map: most-superseded baselines, competition sub-problems, and the live frontier. Method names are matched case- and spacing-insensitively, with did-you-mean suggestions on a miss. Use this when choosing or reviewing a technique for a known problem area, or to check whether a baseline a paper relies on has been beaten. Does not require a Pro API key. Covers ~10 builder-problem families and growing; the `family` parameter lists them, or pass family='list' for the live set. Coverage caveat: evidence is drawn only from arXiv benchmark tables, so 'superseded' means a method was beaten in a published comparison (not that it is dead or unusable), production frameworks (LangChain, LlamaIndex, etc.) appear only as baselines and never as winners, and results are a literature signal rather than a deployment recommendation. GROUNDING — how far to trust an individual receipt: every claim passes a deterministic gate against the source paper's raw LaTeX (a critique must carry a verbatim quote shingle found in the source; a benchmark edge must have every one of its numbers present there), so a fabricated quote or table cell cannot enter the KB. What the gate does NOT verify is ATTRIBUTION: the quote is real but its subject may be class-level or a pronoun ('these methods', 'they') rather than the named method, so tying a receipt to one specific method is sometimes an inference. No end-to-end precision number has been measured…

Input parameters:

- `family` (string): Builder-problem family to query, e.g. 'rag' (retrieval-augmented generation), 'peft' (parameter-efficient fine-tuning), 'kvcache' (KV-cache compression). Omit it (or pass an unknown family like 'list…
- `limit` (integer): Max items per list — receipts, dominance edges, frontier (3–50, default 12).
- `method` (string): Method to check, e.g. 'SnapKV', 'H2O', 'StreamingLLM' (case/spacing-insensitive). Omit to get the whole-family map instead of a single-method verdict.

Output parameters:

- `anchor_arxiv`
- `anchor_title`
- `available_families` (array)
- `beaten_by` (array)
- `beaten_by_papers` (number)
- `criticized_by` (array)
- `critiqued_by_papers` (number)
- `description` (string)
- `family` (string)
- `first_seen`
- `found` (boolean)
- `frontier` (array)
- `label` (string)
- `message` (string)
- `method` (string)
- `methods_ranked` (number)
- `most_superseded` (array)
- `newer_alternatives` (array)
- `note` (string)
- `stats` (object)
- `sub_problem`
- `sub_problems` (array)
- `suggestions` (array)
- `summary` (string)
- `superseded_rank`
- `verdict` (string)

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/ygao2005-scholar-feed-mcp/mcp-2#diagnostics

## Score history

- 2026-09-20: 69
- 2026-09-19: 68
- 2026-09-18: 68
- 2026-09-17: 67
- 2026-09-16: 67
- 2026-09-15: 66
- 2026-09-14: 66
- 2026-09-13: 65
- 2026-09-12: 65
- 2026-09-11: 65
- 2026-09-10: 64
- 2026-09-09: 64
- 2026-09-08: 63
- 2026-09-07: 63

## Common questions

### What is the Scholar Feed MCP server?

Scholar Feed is an MCP server listed in the public MCP registry as io.github.YGao2005/scholar-feed-mcp. Rank CS/AI/ML papers by citations, forecast impact, or code adoption; trace 23.2M citation edges. This page covers its hosted endpoint (https://mcp.scholarfeed.org/mcp?src=mcp-registry).

### Is the Scholar Feed MCP server safe to use?

Scholar Feed scores 69 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the Scholar Feed MCP server expose?

Scholar Feed exposes 27 tools: search_papers, get_paper, get_citations, fetch_fulltext, find_author, and 22 more. Their descriptions and schemas cost roughly 7,929 tokens of context every time the server is loaded.

### Does the Scholar Feed MCP server require authentication?

No. We connected to Scholar Feed without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.

### Is the Scholar Feed MCP server still maintained?

Scholar Feed is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

## Links

- Remote endpoint: https://mcp.scholarfeed.org/mcp?src=mcp-registry
- Repository: https://github.com/YGao2005/scholar-feed-mcp
- Website: https://www.scholarfeed.org/
- Changelog RSS feed: https://verifymcp.io/servers/ygao2005-scholar-feed-mcp/mcp-2.xml
- Changelog JSON feed: https://verifymcp.io/servers/ygao2005-scholar-feed-mcp/mcp-2.json
- HTML version of this page: https://verifymcp.io/servers/ygao2005-scholar-feed-mcp/mcp-2
