mcp-notebooklm
Exposes Google NotebookLM notebooks as tools for AI assistants, enabling listing, finding, and querying notebooks with grounded answers.
README
mcp-notebooklm
MCP server that exposes Google NotebookLM notebooks as tools for AI assistants (opencode).
Thin wrapper over notebooklm-py
using FastMCP.
What it implements
A stdio MCP server with four tools:
| Tool | Purpose |
|---|---|
list_notebooks() |
List every notebook with id, title, source_count. |
find_notebook(title) |
Case-insensitive partial match over notebook titles. |
ask_notebook(notebook_id, question) |
Ask a question; returns the grounded answer from NotebookLM. |
generate_quiz(notebook_id, num_questions, ...) |
Generate quiz JSON with multiple_choice / true_false questions in batches. |
The service (src/mcp_notebooklm/service.py) wraps the async NotebookLMClient
and applies two safety rails so the host LLM never hangs:
- Concurrency limit — one in-flight query at a time
(
asyncio.Semaphore(1)), with a 10s queue timeout. If another query is running, the tool returns[RETRY_NEEDED] NotebookLM is busy... call again in ~60 seconds. - Execution timeout — 60s hard cap on the underlying
chat.ask(). Timeouts and transport failures surface as[RETRY_NEEDED]/[ERROR]prefixes so the LLM can react instead of looping.
Authentication state is persisted to data/auth.json and reloaded on every
request via NotebookLMClient.from_storage().
Prerequisites
- Python ≥ 3.12
uv(recommended) orpipx- A Google account with NotebookLM access
1. Install
From the project root:
uv sync
This installs the project (including the notebooklm-py[browser] extra, which
pulls Playwright) and exposes the mcp-notebooklm console script.
2. Install Playwright browser (one-time)
notebooklm-py[browser] installs the Playwright Python package, but the Chromium browser binary must be downloaded separately.
uv run playwright install chromium
This is a one-time step (~170 MB) and must be done before the first login.
3. Authenticate with NotebookLM
The first run downloads Chromium (~170 MB) and opens a Google sign-in window.
Auth state is written to data/auth.json and reused on subsequent calls.
# one-time login (interactive — finishes in the browser)
uv run --project notebooklm login --storage-path ./data/auth.json
# verify the session
uv run --project notebooklm auth check --test
The login command is provided by the upstream notebooklm-py CLI; see
its README for browser options
(--browser msedge, --browser-cookies chrome, multi-account --profile,
etc.).
data/auth.jsonis git-ignored. Back it up somewhere safe — it is the only thing standing between you and a fresh login.
To refresh cookies silently (cron / launchd / systemd):
notebooklm auth refresh --quiet
4. Register with opencode
Add the server to ~/.config/opencode/opencode.json:
{
"mcp": {
"notebooklm": {
"command": [
"uv",
"run",
"--project",
"<your-path>/mcp-notebooklm",
"mcp-notebooklm",
],
"timeout": 120000,
"type": "local",
},
},
}
Restart opencode. The four tools (list_notebooks, find_notebook,
ask_notebook, generate_quiz) appear as notebooklm__* and are available
immediately.
The
timeout(120s) covers the worst-case ask path: 10s queue + 60s ask + overhead. Raise it if you see transport resets on slow networks.
5. Use it
From inside opencode (or any MCP host):
list all my NotebookLM notebooks
find the notebook about <topic>
ask notebook <notebook_id>: <question grounded in that notebook's sources>
Typical flow the LLM will follow:
list_notebooks()→ choose the rightnotebook_id.ask_notebook(id, question)→ get a cited answer.- If the response starts with
[RETRY_NEEDED], call the tool again.
Quiz generation
Generate structured quizzes that bypass NotebookLM's ~20 question limit by batching requests:
generate_quiz(
notebook_id = "abc123",
num_questions = 50,
topic = "sorting algorithms",
difficulty = "mixed",
output_path = "~/quizzes/algorithms.json",
cumulative = true,
language = "es"
)
Parameters:
| Param | Required | Default | Description |
|---|---|---|---|
notebook_id |
yes | — | Notebook to query |
num_questions |
yes | — | Total questions to generate |
topic |
no | "all sources" |
Specific topic or full notebook |
difficulty |
no | "mixed" |
easy / medium / hard / mixed |
output_path |
no | — | Save JSON to this path (creates directories if needed) |
cumulative |
no | false |
If true and file exists, merge new questions with existing ones |
language |
no | "es" |
Language for questions, options, and explanations |
How batching works:
Questions are generated in batches of 15. For 50 questions, the tool makes 4
calls to NotebookLM (15 + 15 + 15 + 5), parses each response, and merges them
into a single JSON. If a batch fails (timeout, parse error), it's skipped and
failed_batches in metadata tells you how many were lost.
Output format:
{
"metadata": {
"notebook_id": "abc123",
"notebook_title": "Algorithms",
"generated_at": "2026-06-24T10:30:00Z",
"topic": "sorting algorithms",
"difficulty": "mixed",
"total_questions": 50,
"failed_batches": 0
},
"questions": [
{
"id": 1,
"type": "multiple_choice",
"question": "What is the average time complexity of quicksort?",
"options": [
{
"text": "O(n)",
"rationale": "Incorrect. Linear time only applies to specific cases like searching in unsorted arrays."
},
{
"text": "O(n log n)",
"rationale": "Correct. Quicksort averages O(n log n) with good pivot selection and balanced partitions."
},
{
"text": "O(n²)",
"rationale": "Incorrect. This is the worst-case complexity when the pivot selection is poor (e.g., already sorted array with first/last element as pivot)."
},
{
"text": "O(log n)",
"rationale": "Incorrect. Logarithmic time applies to operations like binary search, not full sorting algorithms."
}
],
"correct_answer": 1
},
{
"id": 2,
"type": "true_false",
"question": "Mergesort is a stable sorting algorithm.",
"correct_answer": true,
"explanation": "Mergesort preserves the relative order of equal elements, making it stable."
}
]
}
Cumulative mode:
When cumulative = true and output_path exists, new questions are appended to
the existing array and IDs are renumbered sequentially. This lets you build up a
question bank over multiple calls.
Project layout
src/mcp_notebooklm/
├── __init__.py
├── main.py # entry point → server.main()
├── server.py # FastMCP tool definitions (list, find, ask, generate_quiz)
└── service.py # NotebookLMClient wrapper + concurrency / timeout guards + quiz generation
data/
└── auth.json # notebooklm-py session storage (git-ignored)
pyproject.toml # deps, entry point: mcp-notebooklm
Development
uv run ruff check src/ # lint
uv run flake8 src/ # style
Notes & limits
- The upstream library uses undocumented Google APIs — endpoints can break without notice.
- Heavy usage is rate-limited; the 1-concurrent semaphore is intentional, not a bug. Quiz generation with many questions will take time due to sequential batches.
chat.askis the only endpoint used. Source management, artifact generation, etc. are not wired into the MCP surface.- The server is stdio-only. For HTTP, look at the upstream
notebooklm-pyREST server.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
Neon Database
MCP server for interacting with Neon Management API and databases
E2B
Using MCP to run code via e2b.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.