NotebookLM Curator
БесплатноНе проверенAn MCP server that audits and prunes Google NotebookLM libraries, enabling source listing, removal, and freshness-based audits through browser automation.
Описание
An MCP server that audits and prunes Google NotebookLM libraries, enabling source listing, removal, and freshness-based audits through browser automation.
README
An MCP server that audits and prunes Gemini Notebook (formerly NotebookLM) libraries.
Not an official Google or Anthropic integration. This drives NotebookLM through your own signed-in Chrome profile — it is not affiliated with, endorsed by, or connected to Google in any way. Consider using a separate Google account rather than your primary one; the
accountparameter supports multiple profiles. See Known limitations for the full picture before pointing it at anything you care about.
Off-the-shelf NotebookLM MCPs give you add_source and ask_question. None of them give you these three:
| Tool | What it does | In other NotebookLM MCPs |
|---|---|---|
nlm_list_sources |
Lists the sources in a notebook | ✗ missing |
nlm_remove_source |
Deletes a source | ✗ missing |
nlm_audit |
Flags stale sources by shelf life | ✗ missing |
Also included: nlm_auth, nlm_list_notebooks, nlm_create_notebook, nlm_rename_notebook, nlm_add_source, nlm_ask.

(Titles above are representative examples; the counts reflect a real run against a 56-source notebook.)
Why browser automation
NotebookLM has no public API on the consumer side. Source lists, publish dates, and deletion are not reachable over HTTP. The Gemini Notebook Enterprise API on Google Cloud is a separate product that needs an enterprise account.
So the only way in is a persistent Chrome profile. Every selector lives in one
file, src/notebooklm.js — when Google ships a UI change, that's the only file
that needs an update.
Selectors were verified live against notebooklm.google.com on 2026-07-29.
Requirements
- Node.js 20+
- Google Chrome installed (Windows or macOS — the standard desktop app
from google.com/chrome). This tool
automates your real Chrome install on purpose, not a downloaded Chromium
build: patchright's anti-detection patches are far more effective against
NotebookLM's bot checks when running inside an actual Chrome, so we don't
trade that away for a "works anywhere" default. If Chrome isn't found,
nlm_auth/any tool call fails immediately with a clear message instead of a cryptic browser-launch error. Because real Chrome is used by default,npm installdoes not download a separate Chromium build — nothing extra to fetch, nothing extra on disk. (If you deliberately opt intoNLM_BROWSER_CHANNEL=chromium, runnpx patchright install chromiumonce yourself first.) - Tested on Windows and macOS. Linux is not a current target.
Setup
git clone https://github.com/furkancakmakcreative/notebooklm-curator.git
cd notebooklm-curator
npm install
Copy .env.example to .env if you want nlm_audit's YouTube date resolution:
YOUTUBE_API_KEY=your_own_key
The key stays on your machine. The server only sends it to
googleapis.comand never logs or forwards it elsewhere.
Connecting to Claude Desktop / Claude Code
%APPDATA%\Claude\claude_desktop_config.json (Windows) or the equivalent
config on macOS/Linux:
{
"mcpServers": {
"notebooklm-curator": {
"command": "node",
"args": ["/full/path/to/notebooklm-curator/src/index.js"],
"env": { "YOUTUBE_API_KEY": "your_own_key" }
}
}
}
Fully restart Claude Desktop. On first use, call nlm_auth: a visible Chrome
window opens, you sign in with your Google account once, and the session is
saved to a persistent local profile. Every run after that is headless.
Getting a YouTube API key
Google Cloud Console → APIs & Services
- Library → search "YouTube Data API v3" → Enable
- Credentials → Create credentials → API key
- Click the key → API restrictions → Restrict key → select only YouTube Data API v3 → Save
Don't skip step 3. If a restricted key ever leaks, it can only read public YouTube data — it can't touch your account or spend money.
Quota — this matters
The free daily quota is 10,000 units:
videos.list→ 1 unit per call (up to 50 videos)search.list→ 100 units per call (one title)
NotebookLM never exposes a source's URL, so the first audit has to search
by title: 83 sources ≈ 8,300 units, most of the daily quota. But that search
returns a videoId. Save it and pass it back to nlm_audit as knownIds —
every later audit then uses the cheap videos.list path, ~2 units total.
The searchBudget parameter caps this cost (default 60).
Shelf-life policy
A single global "40 days" threshold gets the wrong answer both ways: a model announcement is dead in three weeks; a typography video is still useful in three years. Shelf life is therefore a function of category:
| Category | Days | What lands here |
|---|---|---|
news |
30 | announcements, release notes, weekly roundups |
tactics |
45 | rate limits, model ranking/picking advice tied to a moving target |
tool |
60 | tool usage, workflow tied to a specific release |
official |
150 | Anthropic/Claude official product-feature videos |
tutorial |
120 | courses, walkthroughs, technical deep-dives |
principle |
1095 | theory, strategy, timeless craft |
nlm_audit guesses a category from the title heuristically; override any
threshold with the categories parameter:
{ "notebookId": "...", "categories": { "news": 14, "tool": 45 } }
Status values: fresh → aging (75% of shelf life burned) → stale.
Sources whose date can't be resolved are unknown — a date is never guessed.
By default the response only gives you counts for fresh/pinned sources,
not their full per-item detail — you rarely need to see the sources that
need no action. Pass includeFresh: true to get everything, e.g. for a
full-library export.
Delete safety
nlm_remove_source is irreversible and refuses to run without confirm: true.
nlm_audit never deletes anything — it only produces a report.
Intended flow: nlm_audit → show the list to the user → call
nlm_remove_source one title at a time for what they approve. The model
bulk-deleting on its own is blocked by design.
How nlm_ask actually detects "the answer is done"
This turned out to be the hardest part of the tool, worth documenting because the wrong approach looks like it works until it silently doesn't.
The first instinct is to poll document.querySelector('main').innerText until
it stops changing. That's wrong: NotebookLM's chat panel renders outside
<main> entirely. The text there never changes, so the polling loop reports
"stable" almost instantly and returns whatever happens to be sitting in
<main> at that moment — in one observed case, hidden emoji-picker markup
that had nothing to do with the question asked.
The actual reliable signal is a .thinking-message element (it carries an
is-changing class while streaming) detaching from the DOM once the model
finishes. Even then, the query textarea's disabled attribute clears
slightly after that detachment — firing the next question too early hits a
still-disabled box and hangs. ask() in src/notebooklm.js waits for both,
in order, before reading the last .chat-message-pair's answer text.
If you're extending this tool and NotebookLM's DOM changes again, that's the
one thing worth re-verifying live before touching anything else. If a wait
times out, nlm_ask sets incomplete: true on its response rather than
silently returning stale or partial text as if it were final.
nlm_ask also enforces a minimum gap (default 4s, NLM_MIN_ASK_INTERVAL_MS)
between question submissions. Firing questions back-to-back is a pattern real
usage never produces, and it's the most plausible trigger for NotebookLM
occasionally refusing to answer ("Şu anda yanıt vermekte zorlanıyorum") —
this is cheap insurance against that, not a confirmed root cause.
Known limitations
- Source URLs are not readable. NotebookLM never puts them in the DOM —
no href, no data attribute, clicking a row doesn't reveal one either. Titles
are used as the identifier instead, so two sources with an identical title
can't be told apart (
findDuplicatesreports these separately). - The delete confirmation dialog may or may not appear depending on
rollout; the code handles both and verifies the source count afterward.
removeSourcere-checks the target row's title immediately before acting on it, but a full guarantee against the list reordering mid-click isn't possible with index-based targeting alone. - UI text matching is English/Turkish only. Menu items, buttons, and the
category-guessing heuristics in
policy.jsmatch against those two languages; a notebook in a third UI language may fail to categorize or to find the "remove" menu item. - Freshness dates only resolve for YouTube sources today. Web pages and
PDFs always come back
unknown— there's no per-page date extraction yet. - Fixed
waitForTimeoutcalls are used in a few places instead of polling for a DOM signal; on a slow connection they can under-wait, on a fast one they add latency.ask()uses the more robust polling pattern — anything ported fromremoveSource/addSourceshould follow that model instead. - If Google changes the UI,
src/notebooklm.jsis the only file that needs updating. renameNotebookandaddSourcereport success once the DOM action is triggered, without re-reading the page to confirm it actually applied (unlikeremoveSource, which re-verifies). On a slow/flaky page a rename or add could silently no-op.- The Chrome profile directory is created with
mode: 0o700, which is a no-op on Windows NTFS (no ACL is set) — on Windows the directory's permissions are whatever the OS default is for your user folder, not actually restricted to your account alone.
Roadmap
Ideas that didn't make v0.1, roughly in order of value:
- Export an
nlm_auditreport to Markdown/CSV for offline review. - A batch-delete tool that takes a pre-approved list of
{title, occurrence}pairs (still gated by an explicit human-approved list, not autonomous). - Cross-notebook source search/duplicate detection (
findDuplicatesalready generalizes to this — it just isn't wired up across notebooks yet). - Date resolution for web sources via
Last-Modifiedheaders orarticle:published_time/ JSON-LDdatePublishedmetadata.
Contributions on any of these are welcome.
License
MIT
Установка NotebookLM Curator
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/furkancakmakcreative/notebooklm-curatorFAQ
NotebookLM Curator MCP бесплатный?
Да, NotebookLM Curator MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для NotebookLM Curator?
Нет, NotebookLM Curator работает без API-ключей и переменных окружения.
NotebookLM Curator — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить NotebookLM Curator в Claude Desktop, Claude Code или Cursor?
Открой NotebookLM Curator на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
Playwright
Browser automation, scraping, screenshots
автор: MicrosoftPuppeteer
Browser automation and web scraping.
автор: modelcontextprotocolopentabs-dev/opentabs
Plugin-based MCP server + Chrome extension that gives AI agents access to web applications through the user's authenticated browser session. 100+ plugins with a
автор: opentabs-devrobhunter/agentdeals
1,500+ developer infrastructure deals, free tiers, and startup programs across 54 categories. Search deals, compare vendors, plan stacks, and track pricing chan
автор: robhunterCompare NotebookLM Curator with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории browse
