Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
BRAVE_API_KEYNoOptional web search backend (alternative to DDG)
TAVILY_API_KEYNoOptional web search backend (alternative to DDG)
ZOTERO_API_KEYNoZotero web API auth, required for paper ingestion
ZOTERO_LIBRARY_IDNoZotero library identifier
SEMANTIC_SCHOLAR_RPSNoOptional Semantic Scholar request-per-second rate override
SEMANTIC_SCHOLAR_API_KEYNoOptional Semantic Scholar API key for higher rate limits

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": true
}
logging
{}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
extensions
{
  "io.modelcontextprotocol/ui": {}
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
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.

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_cluster instead.

build_citationC

Return an inline citation string for a paper.

list_quotesB

List captured quotes, optionally filtered by cluster.

capture_quoteC

Persist a quote to /.research_hub/quotes/.md.

compose_draftC

Assemble captured quotes into a markdown draft.

add_paperC

Fetch a paper by DOI/arXiv ID and ingest it (one-shot).

import_folder_toolC

Walk a local folder and ingest non-DOI files as document notes.

suggest_cluster_splitB

Analyze a cluster's citation graph and suggest sub-topic splits.

list_crystalsC

List all pre-computed crystal answers for a cluster.

read_crystalC

Read a specific crystal at the requested detail level.

emit_crystal_promptC

Emit the markdown prompt the calling AI should answer to generate crystals.

apply_crystalsC

Persist crystal answers to hub//crystals/.md.

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}.

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: [...]}.

check_crystal_stalenessC

Check how many crystals are stale (>10% cluster paper delta since generation).

read_cluster_memoryC

Read cluster memory. kind may be entities, claims, methods, or all.

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.

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.

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.

search_papersC

Search for academic papers across multiple backends.

enrich_candidatesC

Resolve candidate identifiers to full paper records.

verify_paperB

Verify a paper exists via DOI, arXiv ID, or fuzzy title match.

suggest_integrationC

Suggest which cluster a paper belongs to and find related papers.

list_clustersA

List all topic clusters with their bindings.

show_clusterB

Show detailed info for a cluster including sync status.

export_citationC

Export citation in BibTeX, BibLaTeX, RIS, or CSL-JSON format.

get_referencesC

List papers cited by the given paper (its bibliography).

get_citationsA

List papers that cite the given paper (forward citations).

Delegates to research_hub.citation_graph.CitationGraphClient (Semantic Scholar Graph API).

run_doctorB

Run health checks on the research-hub installation.

get_config_infoA

Show current configuration paths and settings.

remove_paperB

Remove a paper from the vault, optionally deleting its Zotero item too.

mark_paperC

Update the reading status of a paper note.

Delegates to research_hub.operations.mark_paper.

move_paperC

Move a paper note from its current cluster to another.

Delegates to research_hub.operations.move_paper.

search_vaultC

Search local vault notes by title or full text.

merge_clustersA

Merge all papers from one cluster into another, then delete the source.

Delegates to research_hub.clusters.ClusterRegistry.merge.

split_clusterB

Split a source cluster into a new cluster based on title keyword overlap.

get_topic_digestC

Return every paper in a cluster plus a markdown digest for overview writing.

write_topic_overviewC

Write a topic overview markdown file for a cluster.

read_topic_overviewA

Return the current topic overview markdown for a cluster, if present.

propose_subtopicsC

Build the Phase 1 sub-topic proposal prompt for an AI to consume.

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.

apply_subtopic_assignmentsC

Write subtopics frontmatter to each paper note.

build_topic_notesC

Generate topics/NN_.md files from paper frontmatter.

list_topic_notesC

List existing sub-topic notes for a cluster.

fit_check_promptC

Build the Gate 1 fit-check prompt for an AI to score.

fit_check_applyC

Consume AI scores, filter candidates, write rejected sidecar.

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": [...]}

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": "..."}

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}

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": []}

label_paperC

Set, add, or remove labels on a paper note.

list_papers_by_labelC

Return paper states for the cluster, optionally filtered by label.

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_labels instead.

  • 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_rebind instead.

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"]}

discover_newC

Run search + emit fit-check prompt, stashing state for discover_continue.

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": "..."}

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_new yet — there's no stash to apply scores against. Run discover_new first.

  • You already have a fully-resolved list of DOIs to ingest; skip discovery and call add_paper per item, or auto_research_topic for 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).

discover_statusC

Return current discover state for a cluster.

discover_cleanC

Remove the discover stash directory for a cluster.

examples_listA

List bundled example clusters.

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"}

examples_copyC

Copy an example into the user's cluster registry.

notebooklm_bundleC

Build a NotebookLM upload bundle for a cluster.

notebooklm_uploadC

Upload the latest cluster bundle to NotebookLM using the saved session.

notebooklm_generateC

Trigger NotebookLM artifact generation for a cluster notebook.

notebooklm_downloadC

Download the latest NotebookLM briefing artifact into the vault.

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' with force_regenerate=True).

When NOT to use:

  • You want one specific crystal answer by slug; use read_crystal instead — it skips dispatch overhead.

  • You want to search across multiple clusters; use web_search or search_papers instead.

  • You want to inspect cluster memory directly (entities / claims / methods); use read_cluster_memory.

sync_clusterC

Aggregate maintenance view: staleness + scope drift + vault health + recommendations.

compose_brief_draftC

Assemble a markdown draft from cluster quotes + overview + crystal TLDRs.

emit_cluster_baseC

Emit (or refresh) the .base dashboard file for a cluster.

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}.

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.

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}.

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}.

collect_to_clusterA

Unified ingest. Auto-routes by source shape: DOI/arXiv -> add_paper, folder -> import_folder, URL -> .url file + import.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/WenyuChiou/research-hub'

If you have feedback or need assistance with the MCP directory API, please join our Discord server