research-hub
This MCP server exposes research-hub's local research workspace, literature discovery, and AI-assisted review workflows to an MCP client.
Search the web and academic sources, verify/enrich papers, and inspect citations/references.
Ingest papers by DOI/arXiv ID, folder, or URL; add/remove/move/mark papers and manage labels/status.
Organize clusters: list/show, merge/split, rebind orphans, prune/archive, and manage subtopics/topic notes.
Work with quotes and drafts: capture/list quotes, compose citation-backed drafts, and build/export citations.
Generate and consume crystals, cluster summaries, autofill, fit-check scoring, and staleness/drift checks.
Integrate with NotebookLM for bundle upload, briefing generation/download, and cluster Q&A.
Run discovery workflows, generate dashboards, search the vault, inspect config/health, and clean/tidy the vault.
Searches arXiv papers as part of the discovery step, enabling retrieval of paper metadata and identifiers.
Provides web search capabilities via the Brave Search API as an alternative search backend for finding papers and sources.
Integrates with Google NotebookLM for bundling sources, uploading, generating briefs, and downloading research summaries.
Writes Markdown notes, tags, and Obsidian Bases dashboards to an Obsidian vault, enabling AI-driven organization and linking of research notes.
Integrates with Semantic Scholar for paper search and metadata enrichment, with configurable API rate limits.
Integrates with Zotero via API to store citations, metadata, and PDFs, and to tag and annotate papers within the Zotero library.
research-hub
A workspace on your computer for researchers to organize papers, evidence, and drafts, with AI-assisted proposals you review.
繁體中文 · Workspace guide · Setup guide · Developer architecture
Why research-hub?
Research is spread across papers, notes, analysis, and manuscripts. A new paper can change a question; an updated file can make a conclusion or section worth revisiting. research-hub gives researchers and AI assistants a local workspace to record those connections, hand off tasks, and review proposals before accepting them.
Keep context: bring questions, sources, evidence, results, and manuscripts into one project rather than leaving them only in a conversation.
Track changes: register file paths and a file fingerprint (hash) to help detect changes, then inspect work that may need review when inputs change.
Keep decisions human: AI proposals require review; a local delivery requires separate approval.

Related MCP server: zotero-mcp-lite
Choose your starting path
Use your existing AI host: You need working search/reading tools and the portable skill with its references. No Hub installation, Zotero, Obsidian, or NotebookLM is required. See skill loading and host support; Codex MCP is not release-verified.
First request: “Find papers on LLMs simulating human decisions. Include source links, relevance, versions, and actual reading limits.” Expect a source list in your host, with unknowns and unavailable tools/sources stated, not automatic full-text reading or a Hub save.
Use the Hub workspace: You need Python 3.10+, Git, and a local browser. Install and launch the tested demo below to inspect two seed references and their reading limits. Optional result saving and task handoff require a selected destination and authorization.
Install and get started
Try the local workspace
Choose this path for the Hub workspace. If you only want to try the older published literature dashboard, see the separate option below.
You need Python 3.10+ and Git. These commands install a specific source revision and create teaching fixtures in a new or empty workspace-demo directory. The source workspace is separate from the PyPI release: a package version does not establish that the installed wheel contains current source features.
git clone -c core.autocrlf=false https://github.com/WenyuChiou/research-hub.git
cd research-hub
git fetch origin 1f0726a7e92a1231e633963f17236a2f5c1eab8f
git checkout --detach 1f0726a7e92a1231e633963f17236a2f5c1eab8fChoose the block for your system. They call the virtual environment's Python directly, without activation or changing PowerShell execution policy. Dependency installation needs network access.
macOS / Linux
python3 -m venv .venv
./.venv/bin/python -m pip install -e .
./.venv/bin/python -m research_hub project demo --root ./workspace-demo --json
./.venv/bin/python -m research_hub serve --workspace --root ./workspace-demoWindows PowerShell
One Windows test environment using the earlier 14ddc070 source encountered WinError 5 during demo creation; its cause is not yet known. See verification and environment notes.
py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e .
.\.venv\Scripts\python.exe -m research_hub project demo --root ./workspace-demo --json
.\.venv\Scripts\python.exe -m research_hub serve --workspace --root ./workspace-demoFirst task: inspect a saved source and its reading limits.
Open http://127.0.0.1:8765/app/ and, in Projects, choose
DEMO: floating-point reading and review outline(review-demo).Open Literature, then select What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Expect two seed references in the list. The selected source shows DOI
10.1145/103162.103163, Unverified, Coverage unknown, and No summary saved. These are expected demo states: no source text was downloaded or summarized, and the supplied screening decisions are examples, not your review.
The other project, DEMO: three floating-point summation cases (summation-demo), contains numerical examples and a manuscript scaffold; its Literature list is empty. Both projects are account-free teaching inputs, not accepted research.
Keep the terminal running while using the workspace; stop it with Ctrl+C. To return later, run only the serve --workspace --root ./workspace-demo command above. Do not recreate the demo over saved work. If creation was interrupted, inspect the preserved partial directory and use another new or empty root for both creation and serving.
Demo creation, launch, and this bilingual first task were checked on Linux with Python 3.12.14 at source revision 1f0726a7; this does not verify Windows, macOS, or a fresh dependency installation. See the exact verification scope.
For your own files, go directly to bring your own project; the guide’s earlier installation pin is historical.
The PyPI package provides the older literature dashboard, not the newer source workspace. For an account-free sample, this separate virtual environment and empty root were tested on Linux with Python 3.12:
python3 -m venv .dashboard-venv
./.dashboard-venv/bin/python -m pip install research-hub-pipeline==1.2.0
mkdir -p "$HOME/research-hub-preview"
RESEARCH_HUB_ROOT="$HOME/research-hub-preview" ./.dashboard-venv/bin/research-hub dashboard --sampleUse a new or empty research-hub-preview directory under HOME: the command creates .research_hub and logs there. It prints the generated temporary HTML path; open that path in your browser. The bare dashboard --sample failed in a fresh HOME without the root setting; see verification notes for platform and browser limits. For real services, see setup, the dashboard tour, and first 10 minutes.
Work in the workspace

Historical demo capture, reviewed 2026-09-08; the current interface may differ.
Page | Example work |
Overview | Review the research question, goal, and project context. |
Literature | Collect sources and record reasons to include or exclude them. |
Evidence | Link claims to sources and inspect unresolved support. |
Design & results | Record methods, results, limitations, and supporting files. |
Manuscript | Register Word, LaTeX, or Markdown and prepare outlines and revisions. |
Review & delivery | Inspect proposals, record decisions, and prepare a local handoff. |
Your editor remains responsible for changes to original files; the workspace registers their paths and hashes. A resolvable identifier does not prove a source supports a claim: check the evidence and scientific judgments yourself.
Discover literature
In a compatible AI tool (an AI host) that can load the research-hub skill and has search and reading tools, start with a concrete request, for example:
Find literature on LLMs simulating human decisions; include original links, relevance, versions, and limits on available full text.
Then ask to focus on economic decisions and compare human baselines and evaluation methods. Review the sources, reading coverage, and open questions before deciding what to do next. Search snippets are not full-text reading. This research approach can be used independently of Hub; Zotero, Obsidian, NotebookLM, and Hub storage are optional. The Hub visual workspace and saved-result view do require Hub.
The native reader can organize supplied research summaries, source indexes, and bibliographies, and attach a PDF explicitly supplied by the user. The PDF is copied unchanged for download; that does not mean it was parsed, translated, verified, or read in full. The reader can display caller-supplied translations alongside original observations, labeled unverified; it does not generate translations or verify their accuracy. See the native reader export guide for the supplied-translation format.
See AI Research Skills, the AI host support matrix, and MCP/REST integration. The optional saved-result contract describes what a Hub handoff stores and its platform boundaries.
Write, review, and deliver

Mode | How it works |
Portable handoff | Export a task to your AI host, then import prose and candidate file hashes. Export leaves the task waiting for the agent. |
Connected Codex | An authenticated, compatible Codex CLI uses an explicitly trusted public writing bundle to produce prose; the result waits for human review. |
The optional writing setup explains how to verify and configure the adapter. Connected Codex receives bounded text excerpts, not binary document contents. Use your editor for Word formatting, LaTeX compilation, and final document changes. Accepted proposals can be packaged into a local ZIP after separate approval; this does not authorize publication or cloud upload. Workspace approval does not automatically protect existing direct-write CLI, MCP, dashboard, or cloud tools. See boundaries and recovery.
Optional integrations
Zotero: manage references; the connection requires an API key and library ID.
Obsidian: organize notes in a local vault, or begin with local files.
NotebookLM: create source-based briefings; it requires browser sign-in and a working session. See setup and troubleshooting.
AI hosts: connect through MCP/REST or portable skills; MCP requires the optional
[mcp]extra.
Choose integrations as needed and run ./.venv/bin/python -m research_hub doctor (macOS/Linux) or .\.venv\Scripts\python.exe -m research_hub doctor (Windows PowerShell) to inspect them individually. Setup or installation does not itself verify a service. The setup guide covers extras and credentials; see also local file import, EZproxy, and the live smoke checklist.
The local workspace demo needs none of these credentials. Existing personas use optional extras: Researcher and Humanities [playwright,secrets]; Analyst and Internal KM [import,secrets].
Name | Required | Purpose |
| Zotero only | Zotero API authentication |
| Zotero only | Zotero library identifier |
| no | Optional search API key |
| no | Optional search request-rate override |
| no | Optional web search backend |
| no | Optional web search backend |
Documentation and contributing
Available Tools
76 toolsadd_paperC
Fetch a paper by DOI/arXiv ID and ingest it (one-shot).
Inputs: identifier (required), cluster, no_zotero, skip_verify. Returns: object
apply_cluster_summariesA
Persist a JSON payload of per-paper summaries (when LLM was invoked
out-of-band) to Obsidian + Zotero. The payload shape matches the
summarize_cluster prompt's expected output: {summaries: [...]}.
Inputs: cluster_slug (required), summaries_json (required). Returns: object
apply_crystalsC
Persist crystal answers to hub//crystals/.md.
Inputs: cluster_slug (required), crystals_json (required). Returns: object
apply_fit_check_to_labelsA
Convert fit-check sidecar decisions into paper labels.
Persists fit_check_apply decisions before pruning.
When to use: after accepted and rejected sidecars are written.
When NOT to use: to score candidates; use fit_check_apply instead.
Args: cluster_slug: cluster whose sidecars and notes are used.
Returns: keys tagged, already, missing, error.
Example:
>>> apply_fit_check_to_labels("my-topic")
{"tagged": ["paper-1"]}
Inputs: cluster_slug (required). Returns: object
apply_subtopic_assignmentsC
Write subtopics frontmatter to each paper note.
Inputs: cluster_slug (required), assignments (required). Returns: object
ask_clusterA
Answer a question about one cluster, dispatching to the source named by source / mode.
Single entrypoint for all cluster-question workflows. Replaces the
deprecated aliases ask_cluster_notebooklm / read_briefing /
brief_cluster (gated behind
RESEARCH_HUB_MCP_INCLUDE_DEPRECATED=1, removed in v2.0.0).
Routes the question through three internal paths:
source='local' answers from cached crystals + memory only;
source='notebooklm', mode='ask' opens NotebookLM via Playwright
and asks live; source='notebooklm', mode='briefing' returns the
last downloaded NotebookLM briefing markdown; source='notebooklm', mode='brief' runs the full bundle-upload-generate-download
round-trip to refresh the briefing artifact.
When to use:
User asks a natural-language question about one cluster and you want the cheapest, fastest answer first (
source='local').User asks an ad-hoc question that requires fresh paper content retrieval (
source='notebooklm', mode='ask').User wants to read the existing brief text (
mode='briefing').User asks to regenerate the brief (
mode='brief'withforce_regenerate=True).
When NOT to use:
You want one specific crystal answer by slug; use
read_crystalinstead — it skips dispatch overhead.You want to search across multiple clusters; use
web_searchorsearch_papersinstead.You want to inspect cluster memory directly (entities / claims / methods); use
read_cluster_memory.
Inputs: cluster, question, source, detail, +6 more. Returns: object
autofill_applyA
Apply AI-authored autofill sections to paper notes.
Consumes autofill_emit JSON and updates notes.
When to use: after an AI returns summaries for an autofill prompt.
When NOT to use: to generate prompts; use autofill_emit instead.
Args: cluster_slug: cluster to update; scored: list or {"papers": [...]}.
Returns: keys cluster_slug, candidate_count, filled, skipped, missing, error.
Example:
>>> autofill_apply("my-topic", {"papers": [{"slug": "paper-1"}]})
{"cluster_slug": "my-topic", "filled": []}
Inputs: cluster_slug (required), scored (required). Returns: object
autofill_emitA
Build an autofill prompt for paper notes with TODO bodies. Emits the JSON prompt for autofill_apply. When to use: after ingest creates notes with abstracts but TODO content. When NOT to use: to write AI output; use autofill_apply instead. Args: cluster_slug: cluster whose notes are scanned for TODO placeholders. Returns: keys prompt, paper_count, error. Example: >>> autofill_emit("my-topic") {"paper_count": 3}
Inputs: cluster_slug (required). Returns: object
auto_research_topicA
One-shot research pipeline: search + ingest + NotebookLM brief (+ optional crystals).
Slugifies topic into a cluster (or reuses cluster_slug), searches
arXiv + Semantic Scholar, ingests papers into Zotero + Obsidian, then
bundles + uploads + generates + downloads a NotebookLM brief. With
do_crystals=True and a detected supported LLM CLI on PATH,
also generates and applies the canonical Q&A crystals so the cluster is
fully ready for read_crystal() queries.
Use when: user says "research X for me" or "find papers on X".
Returns {ok, cluster_slug, papers_ingested, notebook_url, brief_path, total_duration_sec, error}.
Inputs: topic (required), cluster_slug, cluster_name, max_papers, +10 more. Returns: object
build_citationC
Return an inline citation string for a paper.
Inputs: doi_or_slug (required), style. Returns: object
build_topic_notesC
Generate topics/NN_.md files from paper frontmatter.
Inputs: cluster_slug (required). Returns: object
capture_quoteC
Persist a quote to /.research_hub/quotes/.md.
Inputs: slug (required), page (required), text (required), context. Returns: object
check_crystal_stalenessC
Check how many crystals are stale (>10% cluster paper delta since generation).
Inputs: cluster_slug (required). Returns: object
cleanup_garbageA
Garbage-collect accumulated research-hub files (v0.46+).
Pass everything=True for the common case (bundles + debug logs +
artifacts). Default mode lists candidates without deleting; pass
apply=True to actually remove.
Use when: user says "clean up", "free disk space", or "GC the vault".
Returns {ok, total_bytes, files_deleted, dirs_deleted, candidates}.
Inputs: bundles, debug_logs, artifacts, everything, +4 more. Returns: object
cluster_rebindA
Run the cluster-rebind workflow specified by action.
Single entrypoint that consolidates four legacy rebind operations
(propose / apply / list_orphans / status) into one tool with an
action discriminator. Replaces the deprecated aliases
propose_cluster_rebind / apply_cluster_rebind /
list_orphan_papers / summarize_rebind_status, which are
gated behind RESEARCH_HUB_MCP_INCLUDE_DEPRECATED=1 and slated
for removal in v2.0.0.
When to use:
After ingest leaves orphan paper notes that don't match any active cluster, and you want to plan moves before touching files.
After a manual cluster rename, when existing paper notes still reference the old slug.
Periodic vault hygiene: surface stuck or low-confidence orphans via
action='status'.
When NOT to use:
You want to delete clusters wholesale, not rebind their papers; use
research-hub clusters delete(CLI) instead.You want to archive papers carrying a label; use
prune_clusterinstead.
Inputs: action, cluster_slug, report_path, dry_run, +2 more. Returns: object
collect_to_clusterA
Unified ingest. Auto-routes by source shape: DOI/arXiv -> add_paper, folder -> import_folder, URL -> .url file + import.
Inputs: source (required), cluster_slug (required), skip_verify, no_zotero, +1 more. Returns: object
compose_brief_draftC
Assemble a markdown draft from cluster quotes + overview + crystal TLDRs.
Inputs: cluster_slug (required), outline, max_quotes. Returns: object
compose_draftC
Assemble captured quotes into a markdown draft.
Inputs: cluster_slug (required), outline, quote_slugs, style, +1 more. Returns: object
discover_cleanC
Remove the discover stash directory for a cluster.
Inputs: cluster_slug (required). Returns: object
discover_continueA
Apply fit-check scores from an AI judge and produce a papers_input.json ready for ingest.
Second half of the interactive discovery flow. The user runs
discover_new first (which emits a search-results stash + a
scoring prompt), pastes the prompt into an AI of choice, then
feeds the AI's scored output back through this tool. The scored
candidates are filtered by threshold and written to
papers_input.json in the cluster's discover-stash directory,
ready for the standard ingest pipeline (research-hub auto or
research-hub clusters ingest).
When to use:
You have a JSON list of fit-check scores from an AI judge and want to admit only the high-confidence candidates into the vault.
You're running the two-phase discovery flow because the topic boundaries are fuzzy and you want a human / AI in the loop on which papers belong.
When NOT to use:
You haven't run
discover_newyet — there's no stash to apply scores against. Rundiscover_newfirst.You already have a fully-resolved list of DOIs to ingest; skip discovery and call
add_paperper item, orauto_research_topicfor the one-shot path.You want to re-score an EXISTING ingested cluster's papers; use
fit_check_emit+fit_check_apply(the post-ingest re-scoring path).
Inputs: cluster_slug (required), scored (required), threshold, auto_threshold. Returns: object
discover_newC
Run search + emit fit-check prompt, stashing state for discover_continue.
Inputs: cluster_slug (required), query (required), year_from, year_to, +16 more. Returns: object
discover_statusC
Return current discover state for a cluster.
Inputs: cluster_slug (required). Returns: object
discover_variantsA
Emit a query-variation prompt for discovery search.
Generates alternate discover_new queries.
When to use: before discovery when the seed query is narrow.
When NOT to use: to run search; use discover_new instead.
Args: cluster_slug: context; query: seed query; count: variant target.
Returns: keys prompt, target_count, error.
Example:
>>> discover_variants("my-topic", "LLM agents", count=4)
{"target_count": 4, "prompt": "..."}
Inputs: cluster_slug (required), query (required), count. Returns: object
download_artifactsA
Download a generated NotebookLM briefing back to the vault.
Opens the cluster's NotebookLM notebook using the saved local
session, extracts the latest briefing summary text, and saves it under
<vault>/.research_hub/artifacts/<cluster_slug>/brief-<UTC>.txt.
The cluster's nlm_cache.json entry is updated with the new path.
Inputs: cluster_slug (required), artifact_type, headless. Returns: object
emit_assignment_promptA
Build the topic-build Phase 2 (sub-topic assignment) LLM prompt.
Part of the multi-phase topic build flow: Phase 1 proposes
sub-topics for a cluster; Phase 2 (this tool) emits the prompt
that asks an LLM to assign each paper to one of those
sub-topics.
Inputs: cluster_slug (required), subtopics (required). Returns: object
emit_cluster_baseC
Emit (or refresh) the .base dashboard file for a cluster.
Inputs: cluster_slug (required), force. Returns: object
emit_crystal_promptC
Emit the markdown prompt the calling AI should answer to generate crystals.
Inputs: cluster_slug (required), question_slugs. Returns: object
enrich_candidatesC
Resolve candidate identifiers to full paper records.
Inputs: candidates (required), backends. Returns: result
examples_copyC
Copy an example into the user's cluster registry.
Inputs: name (required), cluster_slug. Returns: object
examples_listA
List bundled example clusters.
Inputs: no named parameters. Returns: result
examples_showA
Return one bundled example cluster definition.
Inspects sample JSON before examples_copy.
When to use: before copying an example such as cs_swe.
When NOT to use: to list names; use examples_list instead.
Args: name: bundled example id, such as cs_swe or bio_protein.
Returns: keys name, slug, field, query, definition, year_from, year_to, min_citations, sample_dois, description, error.
Example:
>>> examples_show("cs_swe")
{"slug": "llm-agents-software-engineering"}
Inputs: name (required). Returns: object
export_citationC
Export citation in BibTeX, BibLaTeX, RIS, or CSL-JSON format.
Inputs: identifier, cluster, format. Returns: result
fit_check_applyC
Consume AI scores, filter candidates, write rejected sidecar.
Inputs: cluster_slug (required), candidates (required), scores (required), threshold. Returns: object
fit_check_auditA
Parse the latest NotebookLM briefing for off-topic flags.
Audits briefing text before fit_check_drift.
When to use: after NotebookLM flags papers.
When NOT to use: to emit scoring prompts; use fit_check_emit instead.
Args: cluster_slug: cluster whose briefing is audited.
Returns: keys ok, cluster_slug, flagged, reason, error.
Example:
>>> fit_check_audit("my-topic")
{"ok": True, "flagged": [...]}
Inputs: cluster_slug (required). Returns: object
fit_check_driftA
Emit a drift-check prompt for the current cluster overview. Re-scores papers after fit_check_audit. When to use: when an overview changed and papers may not fit. When NOT to use: to apply scores; use fit_check_apply instead. Args: cluster_slug: cluster; threshold: accepted score cutoff, default 3. Returns: keys cluster_slug, paper_count, threshold, prompt, error. Example: >>> fit_check_drift("my-topic", threshold=3) {"cluster_slug": "my-topic", "prompt": "..."}
Inputs: cluster_slug (required), threshold. Returns: object
fit_check_promptC
Build the Gate 1 fit-check prompt for an AI to score.
Inputs: cluster_slug (required), candidates (required), definition. Returns: object
generate_dashboardA
Generate a personal HTML dashboard for the vault.
Returns the path to the generated file. Open it in a browser to see cluster overview, paper counts, reading status breakdown, and NotebookLM links.
Inputs: no named parameters. Returns: object
get_citationsA
List papers that cite the given paper (forward citations).
Delegates to research_hub.citation_graph.CitationGraphClient
(Semantic Scholar Graph API).
Inputs: identifier (required), limit. Returns: result
get_config_infoA
Show current configuration paths and settings.
Inputs: no named parameters. Returns: object
get_referencesC
List papers cited by the given paper (its bibliography).
Inputs: identifier (required), limit. Returns: result
get_topic_digestC
Return every paper in a cluster plus a markdown digest for overview writing.
Inputs: cluster_slug (required). Returns: object
import_folder_toolC
Walk a local folder and ingest non-DOI files as document notes.
Inputs: folder (required), cluster_slug (required), dry_run. Returns: object
label_paperC
Set, add, or remove labels on a paper note.
Inputs: slug (required), labels, add, remove, +2 more. Returns: object
list_clustersA
List all topic clusters with their bindings.
Inputs: no named parameters. Returns: result
list_crystalsC
List all pre-computed crystal answers for a cluster.
Inputs: cluster_slug (required). Returns: object
list_papers_by_labelC
Return paper states for the cluster, optionally filtered by label.
Inputs: cluster_slug (required), label, label_not. Returns: result
list_quotesB
List captured quotes, optionally filtered by cluster.
Inputs: cluster_slug. Returns: object
list_topic_notesC
List existing sub-topic notes for a cluster.
Inputs: cluster_slug (required). Returns: object
mark_paperC
Update the reading status of a paper note.
Delegates to research_hub.operations.mark_paper.
Inputs: slug (required), status (required). Returns: object
merge_clustersA
Merge all papers from one cluster into another, then delete the source.
Delegates to research_hub.clusters.ClusterRegistry.merge.
Inputs: source (required), into (required). Returns: object
move_paperC
Move a paper note from its current cluster to another.
Delegates to research_hub.operations.move_paper.
Inputs: slug (required), to_cluster (required). Returns: object
notebooklm_bundleC
Build a NotebookLM upload bundle for a cluster.
Inputs: cluster_slug (required), download_pdfs. Returns: object
notebooklm_downloadC
Download the latest NotebookLM briefing artifact into the vault.
Inputs: cluster_slug (required), artifact_type, headless. Returns: object
notebooklm_generateC
Trigger NotebookLM artifact generation for a cluster notebook.
Inputs: cluster_slug (required), artifact_type, headless. Returns: object
notebooklm_uploadC
Upload the latest cluster bundle to NotebookLM using the saved session.
Inputs: cluster_slug (required), dry_run, headless, create_if_missing. Returns: object
plan_research_workflowA
Convert a freeform user intent into a structured research plan.
Call this BEFORE auto_research_topic when the user's request is vague, ambitious, or could collide with an existing cluster. Returns a suggested topic + search depth + NLM/crystals choices + clarifying questions for you to confirm with the user.
Use when the user says things like: "I want to learn about X" "research X for my dissertation" "find recent papers on X" "ingest X but skip NotebookLM"
The plan includes:
intent_summary: rephrased one-line restatement (confirm with user)
suggested_topic / cluster_slug
suggested_max_papers (auto-tuned: 25 for thesis, 8 default, etc.)
suggested_do_nlm / do_crystals (with detected CLI awareness)
existing_cluster_match: warns if a similar cluster already exists
clarifying_questions: ask these BEFORE calling auto_research_topic
next_call: ready-to-execute auto_research_topic args after confirmation
estimated_duration_sec: rough time estimate
After presenting the plan + getting user confirmation, call auto_research_topic with the plan's suggested args.
Inputs: user_intent (required). Returns: object
propose_research_setupA
Propose names for a new research collection without creating anything.
Use this BEFORE creating clusters/collections/notebooks. Show the suggestions to the user and ask them to confirm or override each name. Only after the user agrees should you call the create tools.
Inputs: topic (required). Returns: object
propose_subtopicsC
Build the Phase 1 sub-topic proposal prompt for an AI to consume.
Inputs: cluster_slug (required), target_count. Returns: object
prune_clusterA
Archive or delete paper notes in a cluster whose frontmatter carries label.
Cluster cleanup operation that acts on the label sidecars written
by apply_fit_check_to_labels (e.g. deprecated,
off_topic, low_relevance). Moves matching paper notes to
the cluster's _archive/ subfolder by default, or deletes them
outright if delete=True. Pairs with apply_fit_check_to_labels
as a two-step "decide → act" workflow: that tool labels papers
based on fit-check sidecars; this tool acts on the labels.
When to use:
After running
apply_fit_check_to_labels(or manually labelling papers), you want to physically move the off-topic notes out of the active cluster folder.You want to keep an audit trail (default
archive=True) so the moves are reversible.
When NOT to use:
You want to ADD labels, not act on them; use
apply_fit_check_to_labelsinstead.You want to delete the entire cluster (not just labelled papers); use
research-hub clusters delete(CLI) instead.You want to rebind orphans to a different cluster, not archive them; use
cluster_rebindinstead.
Inputs: cluster_slug (required), label, archive, delete, +1 more. Returns: object
read_cluster_memoryC
Read cluster memory. kind may be entities, claims, methods, or all.
Inputs: cluster (required), kind, min_confidence. Returns: object
read_crystalC
Read a specific crystal at the requested detail level.
Inputs: cluster_slug (required), crystal_slug (required), level. Returns: object
read_topic_overviewA
Return the current topic overview markdown for a cluster, if present.
Inputs: cluster_slug (required). Returns: object
remove_paperB
Remove a paper from the vault, optionally deleting its Zotero item too.
Inputs: identifier (required), include_zotero, dry_run. Returns: object
run_doctorB
Run health checks on the research-hub installation.
Inputs: no named parameters. Returns: result
search_papersC
Search for academic papers across multiple backends.
Inputs: query (required), limit, verify, year_from, +9 more. Returns: result
search_vaultC
Search local vault notes by title or full text.
Inputs: query (required), cluster, status, full_text. Returns: result
show_clusterB
Show detailed info for a cluster including sync status.
Inputs: slug (required). Returns: object
split_clusterB
Split a source cluster into a new cluster based on title keyword overlap.
Inputs: source (required), query (required), new_name (required). Returns: object
suggest_cluster_splitB
Analyze a cluster's citation graph and suggest sub-topic splits.
Inputs: cluster_slug (required), min_community_size, max_communities. Returns: object
suggest_integrationC
Suggest which cluster a paper belongs to and find related papers.
Inputs: identifier (required), top_clusters, top_related. Returns: object
summarize_clusterA
Generate per-paper Key Findings + Methodology + Relevance via LLM CLI.
For each paper in cluster_slug, builds a prompt from the abstract and
invokes the detected LLM CLI (claude, codex, or gemini — pass
llm_cli to override). With apply=False (default), returns the parsed
JSON without writing. With apply=True, writes back to BOTH the Obsidian
markdown blocks and the Zotero child note for each paper.
Use when: user says "summarize this cluster's papers", "fill the TODO
Findings", or after auto ingest before scanning the vault.
No LLM CLI on PATH: prompt is saved to artifacts//summarize-prompt.md; user can pipe it through their LLM and re-run with --apply (CLI) or pass the parsed payload to the apply_cluster_summaries MCP tool below.
Returns {cluster_slug, ok, error, cli_used, prompt_path, apply_result}.
Inputs: cluster_slug (required), llm_cli, apply, write_zotero, +1 more. Returns: object
sync_clusterC
Aggregate maintenance view: staleness + scope drift + vault health + recommendations.
Inputs: cluster_slug (required). Returns: object
tidy_vaultA
One-shot vault maintenance: doctor autofix + dedup rebuild + bases refresh + cleanup preview.
Each sub-step is non-fatal — failures logged but don't abort the others.
Use when: user says "tidy", "maintenance", "vault health check".
Returns {ok, steps, total_duration_sec, cleanup_preview_bytes}.
Inputs: apply_cleanup. Returns: object
verify_paperB
Verify a paper exists via DOI, arXiv ID, or fuzzy title match.
Inputs: doi, arxiv_id, title, authors, +1 more. Returns: object
web_searchA
General web search (blog posts / docs / news / GitHub READMEs).
Use alongside auto_research_topic when the user's need extends beyond peer-reviewed papers and into official docs, engineering blogs, or news.
Inputs: query (required), max_results, provider. Returns: object
write_topic_overviewC
Write a topic overview markdown file for a cluster.
Inputs: cluster_slug (required), markdown (required), overwrite. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 76 tools
Every tool has a clearly distinct purpose, with detailed descriptions that explicitly state when and when not to use each tool, eliminating ambiguity even among closely related functions like fit_check variants.
All tool names follow a consistent snake_case verb_noun pattern, with predictable prefixes like 'discover_', 'fit_check_', 'notebooklm_', etc., making it easy for an agent to infer behavior from the name.
76 tools is far beyond the typical well-scoped range; the server appears to cover a broad domain but could benefit from consolidation, as many tools are highly specialized (e.g., individual discover_* steps) and may overwhelm agents.
The tool set covers the full research workflow from discovery and ingest to analysis, labeling, cleanup, and dashboard generation. Minor gaps exist (e.g., no direct tool for deleting a cluster, relying on CLI), but core operations are well-covered.
Maintenance
Related MCP Connectors
Search arXiv/Semantic Scholar/OpenAlex + medical evidence (PubMed/Europe PMC) + LaTeX/PDF tools.
arXiv and OpenAlex/Crossref paper search (an open Google Scholar alternative) as agent tools.
Research paper search with real citations and reference formatting for AI assistants
Academic literature search, retrieval, and private library management on top of OpenAlex.
Related MCP Servers
- AlicenseBqualityCmaintenanceYour AI's research copilot. Searches 6 academic databases, downloads real PDFs, reads them cover to cover, extracts evidence, renders figures, syncs to Zotero.1616MIT
- AlicenseAqualityDmaintenanceEnables AI assistants to search, read, and manage Zotero references locally with customizable research workflows.939 PyPI4MIT
- AlicenseNot gradedqualityDmaintenanceEnables natural language interaction with Zotero libraries, allowing users to search, retrieve, and update papers and metadata via AI assistants like Claude and Gemini.1GPL 2.0
- FlicenseNot gradedqualityDmaintenanceAggregates academic paper search from multiple databases (OpenAlex, Semantic Scholar, etc.) with PDF storage and full-text search capabilities.1-