NotebookBrain MCP
Integrates with Google services for cited project memory: the official Gemini API File Search backend supports uploading sources and answering questions with citations, while the opt-in notebooklm-py backend connects to NotebookLM through an unofficial client for notebook-based retrieval and answers.
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., "@NotebookBrain MCPask my project notes how we roll back a bad deploy, with citations"
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.
NotebookBrain MCP
Cited project memory for agents: an MCP server with three tools, add_source, ask and
list_sources, behind a pluggable backend. Every backend returns the same answer shape: text
with [n] markers and a list of numbered citations that quote the source.
The problem
Agents need to answer from a team's own notes (ADRs, runbooks, meeting notes) and show where each claim came from, without anyone running a vector database. The community notebooklm-py client makes NotebookLM usable from code, but it drives undocumented Google endpoints with your browser session, so it needs a hard opt-in and a filter that keeps secrets and personal data out. Where an official Google path exists, it should be the default remote option.
Related MCP server: loci-mcp
What was built
Backend |
| Kind | Needs | Status here |
Local BM25 + extractive answers |
| local | nothing | runs, measured below |
Gemini API File Search (REST) |
| official |
| built and tested against a mocked REST transport; live run skipped (HTTP 402, see Limits) |
notebooklm-py 0.8.5 |
| unofficial | ToS flag + notebook id + your own | off by default; tested with a fake client and a signature contract test against the real package |
MCP server (
notebookbrain serve, stdio, MCP Python SDKmcp==2.3.0):add_source(title, text),list_sources(),ask(question, top_k). Results are structured JSON.One citation format (
src/notebookbrain/models.py):{n, source_id, source_title, quote, start, end}.normalize()renumbers citations by first marker, drops dangling markers and merges duplicates, for every backend.tests/test_parity.pychecks the three backends return identical keys.Risk gate (
src/notebookbrain/gate.py) runs before any backend call, on sources and questions. Policy by backend kind:local: reports findings, never refuses (nothing leaves the machine).official: refuses secrets (cloud keys, tokens, private keys, password assignments, JWTs).unofficial: also refuses emails, Luhn-valid card numbers, US SSNs, confidentiality markers and sources over 200,000 characters. Findings never include the matched value.
ToS flag: the unofficial backend refuses to start unless
NOTEBOOKBRAIN_ACCEPT_UNOFFICIAL=i-accept-unofficial-google-api-riskis set exactly.Clean skips: missing key, HTTP 401/402/403, no notebooklm-py login or no ToS flag all return
{"ok": false, "status": "unavailable", "error": "skipped: ..."}instead of crashing.CLI:
notebookbrain {serve, add, add-dir, list, ask, gate-check, info, version}.
flowchart LR
Agent -- MCP stdio --> Server[notebookbrain serve]
Server --> Gate{risk gate}
Gate -- local --> BM25[(local BM25 store)]
Gate -- official --> FS[Gemini File Search]
Gate -- "unofficial + ToS flag" --> NB[notebooklm-py]Is there an official NotebookLM API? (checked 2026-10-21)
NotebookLM Enterprise API exists, but only for managing notebooks and sources. Google Cloud documents
v1alphaREST methods onhttps://{us|eu|global}-discoveryengine.googleapis.com/v1alpha/projects/PROJECT_NUMBER/locations/LOCATION/notebooks(notebooks.create,get,listRecentlyViewed,batchDelete,share) and.../notebooks/NOTEBOOK_ID/sources:batchCreate/sources:uploadFile/sources:batchDelete, authenticated with an OAuth bearer token (gcloud auth print-access-token). The pages are marked Preview (Pre-GA terms) and need a NotebookLM Enterprise license. Sources: Create and manage notebooks (API), Add and manage data sources (API).We found no documented method to ask a notebook a question through that API. Without an
askcall it cannot back this server, so the official backend uses the Gemini API instead.Gemini API File Search is documented with stores, document upload and citations:
POST /v1beta/fileSearchStores,POST /upload/v1beta/{store}:uploadToFileSearchStore,GET /v1beta/{store}/documents, andgenerateContentwithtools[].fileSearch, whose response carriesgroundingMetadata.groundingChunks[].retrievedContextandgroundingSupports[].segment(byte offsets). Sources: File Search guide, File Search stores reference, Documents reference, generateContent reference.notebooklm-py: latest release
v0.8.5(published 2026-10-12, MIT, tag commit50493ddf9f9eb9230de998d3dff8565243383078, PyPInotebooklm-py 0.8.5). Auth is a browser login through Playwright, cookies imported from a signed-in browser, or a "master token"; credentials live under~/.notebooklm/. Its README calls itself an unofficial library that uses undocumented Google APIs, not affiliated with Google, that can break at any time.
Measured
Keyless run through the real stdio MCP server with the local backend, over the synthetic notes
in fixtures/notes/ and the questions in fixtures/questions.yaml (some have no answer in the
notes on purpose). The gate rows use the synthetic cases in fixtures/gate-cases.yaml, whose
secret-shaped values are assembled at runtime. Every number below is written by
uv run python scripts/report.py; none is typed by hand.
Metric (keyless run, | Result |
MCP tools exposed over stdio | add_source, ask, list_sources |
Synthetic notes added / listed back | 8 / 8 |
Expected note is citation [1] (hit@1) | 10/12 |
Expected note among citations (hit@3) | 12/12 |
Cited quote from that note contains the key fact | 11/12 |
Unanswerable questions declined with no citations | 3/3 |
Citations whose quote equals source[start:end] | 23/23 |
Answers where every [n] maps to a citation | 15/15 |
Risk gate, local policy: refused / allowed | 0/0 refused, 12/12 allowed |
Risk gate, official policy: refused / allowed | 5/5 refused, 7/7 allowed |
Risk gate, unofficial policy: refused / allowed | 9/9 refused, 3/3 allowed |
| unavailable: skipped: no GEMINI_API_KEY |
| unavailable: disabled: the unofficial notebooklm-py backend needs NOTEBOOKBRAIN_ACCEPT_UNOFFICIAL=i-accept-unofficial-google-api-risk (read SECURITY.md first: undocumented Google endpoints, Terms of Service and account risk are yours) |
Per-question detail: reports/notebookbrain.md. These numbers measure the local BM25 backend on our own synthetic notes. They say nothing about Gemini File Search or NotebookLM answer quality, which we could not run here.
Quickstart
Requires Python 3.12 and uv.
uv sync --frozen
uv run notebookbrain add-dir fixtures/notes
uv run notebookbrain ask "What canary error rate triggers a rollback?"
uv run notebookbrain list
bash scripts/check.sh # the full local gate (same as CI)Use it from an MCP client (Claude Code, Cursor, any stdio client):
{
"mcpServers": {
"notebookbrain": {
"command": "uv",
"args": ["run", "--directory", "/path/to/notebookbrain-mcp", "notebookbrain", "serve"],
"env": { "NOTEBOOKBRAIN_BACKEND": "local" }
}
}
}Official backend: put GEMINI_API_KEY in .env (copy .env.example), then run with
--env-file .env --backend gemini (for MCP: "args": [..., "notebookbrain", "--env-file", ".env", "--backend", "gemini", "serve"]). Nothing reads .env unless you pass --env-file. The first add_source creates a File Search store and saves
its name in .notebookbrain/gemini-store.json. Default model is gemini-3.8-flash, the id
used in the File Search guide's samples; override with GEMINI_MODEL.
Unofficial backend (read SECURITY.md first): uv sync --extra unofficial, run
notebooklm login yourself, then set NOTEBOOKBRAIN_BACKEND=notebooklm-py,
NOTEBOOKBRAIN_NOTEBOOK_ID=<id> and
NOTEBOOKBRAIN_ACCEPT_UNOFFICIAL=i-accept-unofficial-google-api-risk.
Keys and live tests
Need | Keyless (CI) | Live |
Local backend, MCP server, CLI, gate, report | yes | n/a |
Gemini File Search | mocked REST transport |
|
notebooklm-py | fake client + contract test on the real package | ToS flag + notebook id + your own login; run by hand |
Live tests write to .recorded-local/ (gitignored), never to reports/.
Limits
The Gemini backend has not answered a live question. On this machine the key returns
HTTP 402("prepayment credits are depleted") ongenerateContent, so the live test skips. An earlier live attempt uploaded a note into a fresh store: the upload call succeeded but the document ended inSTATE_FAILED; we did not confirm why (unpaid embeddings is a guess, not a finding). That store was deleted. The REST shapes the code relies on come from Google's reference pages and thegoogle-genai2.32.0 SDK, and are tested against synthetic payloads.Gemini citations have no offsets. File Search returns the retrieved chunk text, not a span in your document, so
start/endarenullfor that backend;source_idis matched by document title.The unofficial backend was never run live here (by design: no Google sign-in, no cookies). Mapping is tested with a fake client; the contract test only checks that notebooklm-py 0.8.5 still has the methods and fields we call. notebooklm-py reports citation offsets in UTF-16 units, which we pass through unchanged.
Terms of Service: we did not verify whether automating consumer NotebookLM with notebooklm-py is allowed for your account. The ToS flag records that you accept that risk; it does not make the use compliant.
The risk gate is a regex scan. It catches the listed patterns and nothing else: no names, addresses, phone numbers or free-text secrets. Treat it as a seatbelt, not proof.
The local backend is extractive: it returns whole sentences from your notes, it does not write new prose, and BM25 misses paraphrases (compare hit@1 with hit@3 in Measured).
NotebookLM Enterprise is not wired in: its documented API has no ask method (see above).
Educational minilab; not regularly maintained.
Not affiliated
Not affiliated with, endorsed by, or sponsored by Google (NotebookLM, Gemini) or the notebooklm-py authors. Names are used only to describe compatibility.
Credits
Builds on minilab-notebooklm-py-skill (the notebooklm-py pin) and the repo layout of SkilledDragon's agent-flight-recorder and decisiongate-mcp. See NOTICE.
Built by SkilledDragon LLC. Questions: hello@skilleddragon.com. License: Apache-2.0.
Available Tools
3 toolsadd_sourceAIdempotent
Add a text source (a project note, ADR, runbook...) to the brain. Sensitive content (keys, tokens, private keys; plus personal data and confidentiality markers on the unofficial backend) is refused by the risk gate before it leaves the machine.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| title | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds genuinely useful behavior beyond annotations: a risk gate refuses sensitive content (keys, tokens, private keys, personal data on unofficial backend) before data leaves the machine. This tells the agent about a failure mode it would otherwise not know. It does not address what happens on refusal (error type, partial writes) or confirm the idempotentHint behavior, so not a 5.
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, front-loaded with the core action and examples, followed by the safety constraint. The parenthetical multi-clause safety sentence is slightly dense but each part earns its place by naming distinct refused categories.
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?
An output schema exists, so return values needn't be described, and the safety gate is a welcome addition. However, for a two-required-parameter write tool with no schema descriptions, an agent still lacks guidance on what to supply for title/text and what a gate refusal looks like in practice.
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% – neither title nor text has a description in the schema. The description's phrase "text source" loosely implies text is the content, but title semantics and formatting expectations are left entirely undocumented, so it only partially compensates for the coverage gap.
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?
States a specific verb and resource ("Add a text source ... to the brain") and gives concrete examples of what counts as a source (project note, ADR, runbook). It doesn't explicitly differentiate itself from siblings like list_sources or ask, but the add-vs-read distinction is evident.
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 examples imply the kind of content this tool is for, but there is no explicit statement of when to use this versus ask or list_sources, nor any prerequisites. Usage must be inferred from the examples alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
askARead-only
Answer a question from the added sources only. Returns answer text with [n] markers, citations [{n, source_id, source_title, quote, start, end}], backend and grounded (false when the sources do not contain an answer).
| Name | Required | Description | Default |
|---|---|---|---|
| top_k | No | ||
| question | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the description's job is lighter, but it still adds real behavioral value: answers are grounded strictly in added sources, and the `grounded` flag is false when sources lack an answer. It also specifies the [n] marker and citation structure, though it does not mention latency or failure modes for empty/unavailable sources.
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?
Front-loads the purpose in the first sentence, then packs return-shape details into a compact second clause. Dense but no filler; the nested citation shape listing is arguably more than prose needs but it is efficient.
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?
An output schema exists, yet the description usefully explains the grounded flag and citation fields that an agent must interpret. The main omission is `top_k`, which is left entirely undefined, so the tool is nearly but not fully callable without guesswork.
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 description coverage is 0% and the description never mentions `top_k`, leaving its retrieval-depth semantics undocumented anywhere. Only `question` is self-evident from the prose; the most consequential tuning parameter is unexplained.
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?
Names a specific verb and resource ("Answer a question") and scopes it precisely ("from the added sources only"). The purpose is unmistakable against siblings add_source and list_sources, which ingest and enumerate sources rather than answer questions over them.
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?
"From the added sources only" implies the prerequisite that sources must already be added, which is useful context. However, no sibling is named and there is no explicit guidance on when to prefer this over list_sources or how to behave if no sources exist — usage must be inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sourcesARead-onlyIdempotent
List the sources the brain can cite: source_id, title, backend, size, status.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds that these are sources the brain can cite and names the returned fields, but it does not describe ordering, pagination, or other behavioral details beyond the annotation baseline.
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 definition is a single front-loaded sentence with no wasted wording. Every element earns its place.
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 zero-parameter list tool with an output schema and read-only/idempotent annotations, the description is complete enough to call correctly. Return-field details are further covered by the output schema.
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 there is no parameter semantics burden. The baseline for a no-parameter tool is 4, and the description does not introduce any confusing parameter claims.
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 gives a specific verb (List) and resource (sources) plus the returned fields, making the operation clear. It does not explicitly contrast with the sibling add_source, but the verb choice naturally distinguishes them.
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?
There is no explicit guidance on when to use this tool versus alternatives, and no prerequisites or exclusions are stated. The intended use is only weakly implied by 'the brain can cite'.
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.
3 tool updates
v0.1.0- First observed
add_source - First observed
ask - First observed
list_sources
TDQS
Scored across 3 tools
Each tool has a distinct action and resource: add_source writes a source, list_sources enumerates sources, and ask queries the accumulated sources. There is no plausible overlap in agent selection.
add_source and list_sources follow a clear verb_noun snake_case convention, and ask is also snake_case but is a bare verb. This is mostly consistent with a minor deviation.
The set is intentionally small and well-scoped for a source-backed question-answering server: ingestion, listing, and querying are the three core operations. Each tool earns its place and three tools fit within the recommended range.
The surface covers adding sources, listing them, and asking grounded questions, but lacks update/delete operations and a way to inspect or retrieve an individual source's contents. These are notable lifecycle gaps, though the core ask workflow is present.
Maintenance
Related MCP Connectors
Project memory, semantic code search, and grounded agent context.
Cited, versioned knowledge for agents: retrieve sourced passages and propose owner-approved fixes.
Agent-native notes, tasks, dev-docs, vaults, sync & handoffs. MCP + OpenAPI dual surface.
Securely search and manage workspace context files for AI agents and teams.
Related MCP Servers
- FlicenseNot gradedqualityAmaintenanceEnables AI agents and MCP hosts to query locally indexed notes, docs, chat logs, and other files via hybrid vector/BM25 retrieval with section-level citations. Exposes tools, resources, and prompts for searching and asking over the indexed content.-
- FlicenseNot gradedqualityAmaintenanceEnables AI hosts and agents to query locally indexed notes, docs, PDFs, chat logs, and other scattered files through hybrid vector and BM25 retrieval with section-level citations. It exposes tools, resources, and prompts for searching, asking questions, scoping by tags, traversing links, and reranking results.-
- FlicenseNot gradedqualityAmaintenanceEnables AI agents to search and query a local knowledge base of scattered notes and docs through hybrid vector plus BM25 retrieval with section-level citations, and to store, retract and explore durable memories, note links and agent harness memories. It also exposes note resources plus briefing, study-plan and contradiction-check prompts, all backed by a shared local index.-
- FlicenseNot gradedqualityAmaintenanceEnables AI agents to search and question a personal knowledge base of notes and documents through hybrid vector and BM25 retrieval, with section-level citations. It also lets agents store, retract, and explore durable memories, links, and indexing statistics across tools.-