notebooklm-mcp
CLAUDE.md21 starsChanged 23 days agoMITView on GitHub
TypeScript strict mode is the primary quality gate — fix all type errors before building. CI runs pnpm test before publishing to NPM. This is an MCP (Model Context Protocol) server that bridges AI assistants to Google NotebookLM's internal batchexecute RPC API. NotebookLMClient used to be a 1.4k-LOC class that mixed HTTP transport, auth state, wire-format parsing and domain logic. The split (audit-driven, 2026-05-17) factors each concern into a small SRP-respecting module: AuthenticationError is still exported from src/client.ts for backward…
- Installs packages
In this repositoryOne other file it gives its agents.
- notebooklmSkill
The file
We split this CLAUDE.md into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 106
All NotebookLM calls go through NotebookLMClient.callRpc(rpcId, params).
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
# Install dependencies (pnpm pinned via packageManager field)
corepack enable
pnpm install
# Build (outputs to dist/)
pnpm run build
# Watch mode for development
pnpm run dev
# Run the built CLI directly
node dist/cli.js serve
node dist/cli.js auth# Run the test suite (vitest + MSW)
pnpm test# Release flow
make release # local bump + tag
make release-push # supply-chain audit then push (publishes via CI on tag)
make pre-release # standalone auditTypeScript strict mode is the primary quality gate — fix all type errors before building. CI runs pnpm test before publishing to NPM.
Architecture
This is an MCP (Model Context Protocol) server that bridges AI assistants to Google NotebookLM's internal batchexecute RPC API.
Data Flow
MCP Client (Claude/Cursor/VS Code)
→ stdio transport
→ McpServer (src/server.ts)
→ Tool handler (src/tools/*.ts)
→ NotebookLMClient (src/client.ts) ── domain facade ──┐
composes: │
AuthState (src/rpc/auth-state.ts) │
RpcTransport (src/rpc/transport.ts) ──────────┤
wire helpers (src/rpc/wire.ts) │
→ Google batchexecute RPC endpoint ◀──────────────────┘Key Files
| File | Role |
src/cli.ts | Entry point; defines serve and auth CLI commands |
src/server.ts | Creates McpServer, wires tools to a lazily-initialized NotebookLMClient |
src/client.ts | NotebookLMClient — thin domain facade that composes the rpc/* modules. Public surface for tools. |
src/rpc/transport.ts | RpcTransport — HTTP POST/GET, response.ok enforcement, Set-Cookie merge, abort-bound body read; fetchLandingHtml returns { html, url } (final URL after redirects) |
src/rpc/auth-state.ts | AuthState — tokens / csrf / session id state, single-flight refresh mutex, disk reload |
src/rpc/wire.ts | Pure parsers — parseResponse (batchexecute envelope), extractTextFromBlocks (source content incl. tables), sourceTypeCode, and the studio parsers studioArtifactId / studioTypeName / studioDownloadUrl |
src/auth.ts | Token load/save, cookie validation, manual auth flow |
src/browser-auth.ts | Chrome CDP-based automated cookie extraction (OS-assigned port, loopback bind) |
src/constants.ts | All RPC_IDS, CodeMapper enums, timeouts, URLs |
src/types.ts | Shared TypeScript interfaces (AuthTokens, Notebook, etc.) |
src/tools/index.ts | McpTool<T> interface, registerTools(), resolveSourceIds(), clientResetSignal() |
src/tools/*.ts | Tool implementations grouped by domain (notebook, source, studio, query, research, auth) |
rpc/ split rationale
NotebookLMClient used to be a 1.4k-LOC class that mixed HTTP transport, auth state, wire-format parsing and domain logic. The split (audit-driven, 2026-05-17) factors each concern into a small SRP-respecting module:
RpcTransportowns the wire: fetch + abort + Set-Cookie + HTTP status. It does not know about tokens beyond whatAuthStateexposes.AuthStateowns the credential lifecycle: getters for current values, single-flightrefreshOnce()mutex (no more concurrent Chrome launches),reloadIfNewer()for disk-cache pickup,recordSetCookies/recordSessionId/recordCsrfTokenwrite paths.wireis a pure function module — nothis, easy to test, reusable in the streamingquery()code path.NotebookLMClientstays the only entry point tools import. Public method signatures are unchanged.
AuthenticationError is still exported from src/client.ts for backward compatibility.
Tool System
Each tool file exports an array of McpTool objects:
export const myTools: McpTool<typeof schema>[] = [{
name: "tool_name",
title: "Human-readable name",
description: "What it does. Returns ... When to use it vs related tools.",
annotations: READ_ONLY, // or CREATES / UPDATES / DESTROYS (src/tools/index.ts)
schema: { param: z.string().describe("...") }, // zod schema — omit for no-arg tools
output: { field: z.string() }, // result shape, published as outputSchema — {} if only status/message
execute: async (client, args, opts) => { ... }
}];src/__tests__/tools-metadata.test.ts enforces the catalog rules: every tool has a title, full annotations, a description of at least 120 characters that says what it returns, and a description on every parameter; tools taking confirm say so and are not read-only; *_delete tools are destructive. Directories such as Glama grade these descriptions (one-liners scored C). Shared parameter wording lives in PARAM in src/tools/index.ts. The server's cross-tool workflow guidance is SERVER_INSTRUCTIONS in src/server.ts, sent to clients at initialization; the reported server version comes from package.json (src/version.ts).
registerTools() in src/tools/index.ts loops over these, registers them on the McpServer, and wraps execution with error handling. Tool results are returned as JSON with a status field, both as text and as structuredContent. outputShape() adds status and message to each tool's output, and makes every field optional for tools taking confirm. MCP clients validate structuredContent against the published JSON Schema, which forbids undeclared keys, so a field added to a result must be added to output too; src/__tests__/tools-output.test.ts runs every tool through a real SDK client to catch that. Shared shapes: NOTEBOOK_OUT, SOURCE_OUT. Use { _client_action: "reset" } in a result to trigger client re-initialization (used after auth changes).
RPC Integration
All NotebookLM calls go through NotebookLMClient.callRpc(rpcId, params). Adding a new feature requires:
- Adding the
rpcIdtoRPC_IDSinsrc/constants.ts - Implementing the method in
NotebookLMClient(parse the nested array response format) - Adding a
McpToolentry in the appropriatesrc/tools/*.tsfile
For operations that take a long time (studio generation, deep research, polling), use EXTENDED_TIMEOUT (120s). Default is DEFAULT_TIMEOUT (30s).
Authentication
Token resolution order: NOTEBOOKLM_COOKIES env var → ~/.notebooklm-mcp/auth.json → error.
Automated auth uses Chrome DevTools Protocol (CDP) on an OS-assigned loopback port. browser-auth.ts launches Chrome with --remote-debugging-port=0, connects via WebSocket, and polls Storage.getCookies, keeping only cookies that apply to BASE_URL (cookieAppliesToBase — host-only cookies such as OSID exist once per Google host). It resolves once the required cookies (SID, HSID, SSID, APISID, SAPISID) are present and the tab is on NotebookLM (isNotebookLmUrl: notebook.google.com, or the legacy notebooklm.google.com which now 301s there).
The NotebookLMClient auto-fetches CSRF token and session ID from the NotebookLM page HTML on first use, and can trigger headless browser refresh when session expires. If the landing page ends outside NotebookLM (Google sign-in) or has no CSRF token, refreshAuthTokens throws AuthenticationError telling the user to run auth. That check runs before the recovery try in execute()/query() on purpose: a signed-out session must not start the headless/visible-browser recovery, which kills any Chrome on the shared profile. Recovery still runs for RPC-level auth failures (error code 16). A non-2xx landing page is a plain HTTP error.
Wire format and live verification
The RPC payload and response shapes in src/client.ts / src/rpc/wire.ts were recorded from the web app on 2026-10-18 (comments say "recorded 2026-10"). Google changes them without notice and the MSW tests only replay recorded shapes, so a green suite does not prove a tool works: after any wire change, run the tool against real NotebookLM. Never call tools while node dist/cli.js auth is waiting for a login (they share the Chrome profile).
Dependencies and CI
CI (.github/workflows/publish.yml): gitleaks → scripts/pre-release.sh (frozen install, build, tests, pnpm audit high+, signatures, lockfile pinning, pack preview) and osv-scanner in parallel → tests on Node 20/22/24 → npm publish on v* tags. Fix vulnerable dependencies by bumping or by overrides: in pnpm-workspace.yaml; never add osv-scanner.toml ignores. engines.node is >=20.
Build Output
tsup bundles src/cli.ts → dist/cli.js as a single ESM file with a #!/usr/bin/env node shebang. Only dist/ is published to npm.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

