mcp-notebooklm
Provides tools to interact with Google NotebookLM, allowing users to list notebooks, find notebooks by title, and ask questions grounded in notebook sources.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-notebooklmlist my notebooks"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 every notebook with |
| Case-insensitive partial match over notebook titles. |
| Ask a question; returns the grounded answer from NotebookLM. |
| 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().
Related MCP server: notebooklm-mcp-server
Prerequisites
Python ≥ 3.12
uv(recommended) orpipxA Google account with NotebookLM access
1. Install
From the project root:
uv syncThis 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 notebooklm login --storage-path ./data/auth.jsonThe 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 --quiet4. 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 notebooksfind 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 |
| yes | — | Notebook to query |
| yes | — | Total questions to generate |
| no |
| Specific topic or full notebook |
| no |
|
|
| no | — | Save JSON to this path (creates directories if needed) |
| no |
| If |
| no |
| 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-notebooklmDevelopment
uv run ruff check src/ # lint
uv run flake8 src/ # styleNotes & 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.
Available Tools
4 toolsask_notebookA
Ask a question to a specific NotebookLM notebook and get an AI answer
based on its sources.
Args:
notebook_id: The ID of the notebook to query
(use list_notebooks to find IDs).
question: The question to ask the notebook.
| Name | Required | Description | Default |
|---|---|---|---|
| question | Yes | ||
| notebook_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description fully bears the transparency burden. It describes the tool as a read operation (get answer), non-destructive. However, it lacks details on authentication, rate limits, or the exact format of the answer. The output schema may compensate, but the description itself is minimal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise and well-structured: one sentence for purpose followed by a numbered list for parameters. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (2 required params, no enums, output schema present), the description is complete. It explains what the tool does, the parameters needed, and how to get the notebook ID. The output schema likely covers return value details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds valuable context beyond the schema by specifying that notebook_id is obtained via list_notebooks. The question parameter is simply restated. Schema coverage is 0%, so this addition is significant.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Ask a question' and the resource 'specific NotebookLM notebook', with a clear output 'get an AI answer based on its sources'. It distinguishes from siblings like list_notebooks, find_notebook, and generate_quiz by focusing on querying a notebook for answers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implicitly guides usage by telling the user to use list_notebooks to find notebook IDs, but does not explicitly state when to use this tool vs alternatives or provide exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_notebookA
Find NotebookLM notebooks by title (partial match, case-insensitive).
Args:
title: The title or partial title to search for.
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description bears full burden. It reveals partial match and case-insensitivity but omits behaviors like what happens on no match, multiple results, or error handling, leaving gaps for an agent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no wasted words. Purpose is stated first, then parameter documented. Efficient and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple search with one parameter and an existing output schema, the description is adequate but lacks details on return format, pagination, or edge cases (e.g., no results). Sibling differentiation is implicit only.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% (parameter has no description), so the description must add meaning. The line 'title: The title or partial title to search for.' clarifies the parameter's role beyond the type, which is helpful compensation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (find) and resource (NotebookLM notebooks) and clarifies partial match and case-insensitive search, distinguishing it from siblings like list_notebooks (lists all) or ask_notebook (Q&A).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when you have a title or partial title but does not explicitly state when to use this tool versus alternatives, nor provide exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_quizA
Generate a quiz (JSON) from a NotebookLM notebook's sources.
Generates questions in batches to bypass NotebookLM's ~20 question
limit. Supports multiple_choice and true_false question types.
Args:
notebook_id: The notebook to generate questions from.
num_questions: Total number of questions to generate.
topic: Specific topic or "all sources" for everything.
difficulty: easy, medium, hard, or mixed.
output_path: Optional file path to save the JSON quiz.
cumulative: If true and output_path exists, merge with existing.
language: Language for questions (default: "es").
| Name | Required | Description | Default |
|---|---|---|---|
| topic | No | all sources | |
| language | No | es | |
| cumulative | No | ||
| difficulty | No | mixed | |
| notebook_id | Yes | ||
| output_path | No | ||
| num_questions | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description bears full responsibility for behavioral disclosure. It explains batching to bypass limits and support for question types, but does not mention side effects, authentication requirements, or whether the tool is read-only. This leaves some uncertainty, warranting a 3.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately sized and well-structured: a one-line summary, a behavioral note, and a bulleted Args list. It front-loads the main purpose. Slightly verbose due to the Args repetitions, but overall efficient. A 4 reflects good but not perfect conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers key aspects: parameters, batching, question types, and cumulative merging. However, it lacks details about the output JSON format (keys, structure), which would be helpful given no output schema. The language default ('es') is mentioned without explanation. Overall adequate but with notable gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, so the description must compensate. It does so comprehensively by listing all 7 parameters with clear explanations, defaults, and permissible values (e.g., topic: 'all sources', difficulty: easy/medium/hard/mixed). This adds full meaning beyond the schema's bare types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: generating a JSON quiz from a NotebookLM notebook's sources. It specifies the output format (JSON) and resource (notebook's sources). The verb 'generate' is specific, and the tool is distinct from sibling tools (ask, find, list). No ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not explicitly state when to use this tool versus alternatives. It mentions supporting multiple_choice and true_false question types, which provides some guidance, but no explicit context on when to choose this over siblings like ask_notebook. A 3 reflects the lack of direct usage instructions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_notebooksA
List all available NotebookLM notebooks with their IDs, titles, and source counts.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It only describes the action and output, lacking details on side effects, permissions, or limits. However, as a read-only list operation, the description is minimally adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence that front-loads the verb 'List' and clearly conveys the action and output. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and the existence of an output schema, the description sufficiently explains the tool's purpose and result. It could mention that it returns all accessible notebooks, but overall it is complete for a simple listing tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the schema coverage is 100% trivially. Per guidelines, baseline is 4. The description adds no parameter info but none is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it lists all available notebooks and specifies the returned fields (IDs, titles, source counts). This distinguishes it from sibling tools like ask_notebook, find_notebook, and generate_quiz.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use for getting an overview of notebooks but does not explicitly state when to use this tool versus alternatives or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.1.0- First observed
ask_notebook - First observed
find_notebook - First observed
generate_quiz - First observed
list_notebooks
TDQS
Scored across 4 tools
Each tool has a distinct, non-overlapping purpose: listing notebooks, finding by title, asking questions, and generating quizzes. No ambiguity.
All tools follow a consistent verb_noun snake_case pattern (list_notebooks, find_notebook, ask_notebook, generate_quiz), making predictions easy.
With 4 tools, the server is well-scoped for interacting with NotebookLM notebooks—covering essential operations without excess.
Covers listing, searching, asking, and quiz generation. Minor gaps like notebook creation/deletion or source retrieval, but these are outside the server's apparent focus.
Maintenance
Related MCP Connectors
Google NotebookLM via natural language: create notebooks, add sources (PDF, URL, YouTube) and ask gr
Provides tools for searching Google Workspace documentation and much more.
Create, search, and update notes in an xNotepad AI notebook, with semantic search and AI Q&A.
- KnowtisOAuthapp.knowtis
Create, search and manage Knowtis collaborative notes from AI assistants.
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables AI agents to query and interact with Google NotebookLM notebooks to retrieve citation-backed information. It provides tools for listing notebooks, accessing source data, and asking natural language questions.11-
- AlicenseBqualityBmaintenanceEnables AI agents to interact with Google NotebookLM for grounded, hallucination-free answers through notebook management, source management, research, and generation tools.29528 npm34MIT
- AlicenseBqualityAmaintenanceEnables AI assistants to programmatically interact with Google NotebookLM, allowing them to create and manage notebooks, add sources, query content, generate audio/video, and perform research tasks through natural language commands.24915,448 PyPI6,096MIT
- AlicenseNot gradedqualityCmaintenanceExposes Google NotebookLM as MCP tools, enabling management of notebooks, sources, chat, artifacts, and research via natural language.2MIT