内容
mcp
MCP 服务器,暴露 [Google NotebookLM](https://notebooklm.google.com/)
笔记本 助手的工具(开源)。
在 [`FastM://github.com/modelcontext-sdk) 上薄封装 [lm-py](https://github.com/teng-lin/note)。
## 实现内容
工具的标准输入输出 MCP 服务器:
| 工具 | 目的 |
| ------------------------------------------------ | -------------------------------------------------------------------------- |
| `list_notebooks()` | 列出每个笔记本的 `id`、`title` 和 `source_count`。 |
| `find_notebook(title)` | 笔记本标题的不区分大小写的部分匹配。 |
| `ask_notebook(note, question)` |;从 NotebookLM 返回答案。 |
| `generate_quiz(notebook num_questions, ...)` | 生成带有 multiple_choice / true_false测验 JSON(分 |
服务(`src_notebooklm/service.py`)封装了异步 `NotebookLMClient`
并应用了措施,以防止主机 LLM起:
- **** — 每次只有一个查询`asyncio.Sem)`),超时时间为 另一个查询正在运行,工具
`[RETRY_NEEDED] NotebookLM 忙...60 秒后重试。 **执行超时**底层 `chat.ask()` 的 秒硬上限。超时和会以 `[RETRY]` / `[ERROR]` 前,以便 LLM 可以做出反应。
身份验证状态保存在/auth.json` 中,并在时通过 `NotebookLM_storage()` 重新加载。
置条件
- Python3.12
- [`https://docs.astr/uv/) (推荐)pipx`
- 具有 访问权限的 Google 帐户
## 1. 安装根目录:
```bash
uv sync
```
这项目(包括 `notebooklm-py]` 额外会拉取 Playwright暴露 `mcp-notebook 控制台脚本。
##. 安装 Playwright 浏览器)
notebooklm-py[browser] 安装了 Play 包,但 Chromium 浏览器二进制单独下载。
uv run playwright
这是一次性步骤(约 170 MB),首次登录前完成。
3. 与 NotebookLM 身
首次运行会下载约 170 MB)并 登录窗口。身份验证 `data/auth.json`时重复使用。
# 一次性交互式 — 在浏览器中完成)
uv run notebooklm login-path ./data/auth.json
```
登录命令由上游 `lm-py` CLI 提供
[其 README](.com/teng-lin/notebooklm-py) 获取
(`--browser msedge`、`--browser-cookies chrome`、多帐户 `--profile)。
> `data/auth 被 git 忽略。备份到安全的位置 — 它是全新登录之间唯一的东西静默刷新 cookie(cron / launchd / systemd):
```bash
notebooklm auth refresh --quiet
```
## 4. 在 opencode 上注册
将服务器添加到 `~/.config/opencode/opencode.json`:
```jsonc
{
"mcp": {
"notebooklm": {
"command": [
"uv",
"run",
"--project",
"<>/mcp-note",
"mcplm",
],
" 120000,
" "local",
},
}
```
重启 opencode。四个工具(`list`、`find_notebook`、`ask_notebook`、`generate`)立即显示为booklm__*`即可用。
> 超时(120 秒)涵盖了情况下的询问路径:队列 + 60 秒
> 额外开销。如果在慢速网络上看到传输重置,请提高它。
##. 使用
从 op任何 MCP 主机)内部:
```text
my NotebookLM notebooks
```
find the notebook about>
```
```text
ask notebook <notebook_id>: <question grounded in that notebook's sources>
```
LLM 通常会遵循以下流程:
1. `list_notebooks()` → 选择正确的 `notebook_id`。
2. `ask_notebook(id, question)` → 获取引用的答案。
3. 如果响应以 `[RETRY_NEEDED]` 开头,请再次调用该工具。
### 测验生成
生成结构化测验,通过分批请求绕过 NotebookLM 的 ~20 个问题限制:
```text
generate_quiz(
notebook_id = "abc123",
num_questions = 50,
topic = "sorting algorithms",
difficulty = "mixed",
output_path = "~/quizzes/algorithms.json",
cumulative = true,
language = "es"
)
```
**参数:**
| 参数 | 必需 | 默认值 | 描述 |
| --------------- | -------- | --------------- | ----------------------------------------------------------------- |
| `notebook_id` | 是 | — | 查询的笔记本 |
| `num_questions` | 是 | — | 要生成的总问题数 |
| `topic` | 否 | `"所有来源"` | 特定主题或完整笔记本 |
| `difficulty` | 否 | `"混合"` | `简单` / `中等` / `困难` / `混合` |
| `output_path` | 否 | — | 保存 JSON 到此路径(如果需要,创建目录) |
| `cumulative` | 否 | `false` | 如果 `true` 且文件存在,请将新问题与现有问题合并 |
| `language` | 否 | `"es"` | 问题、选项和解释的语言 |
**批处理工作原理:**
问题分批生成,每批 15 个。对于 50 个问题,工具会调用 NotebookLM 4 次(15 + 15 + 15 + 5),解析每个响应,并将它们合并为单个 JSON。如果一批失败(超时、解析错误),则该批,`failed 中的元数据会告诉您有多少批丢失。
**:**
```json
{
"metadata": {
"notebook_id": "abc123",
"notebook_title": "算法",
"generated_at": "2026-06-24T10:30:00Z",
"topic":算法",
"difficulty": "混合",
"total_questions": 50,
"failed_batches": 0
},
"questions": [
{
"id": 1,
"type": "multiple_choice",
"question": "快速排序的平均时间复杂度是多少?",
"options": [
{
"text": "O(n)",
"rationale": "错误。线性时间仅适用于特定情况,如在未排序数组中搜索。"
},
{
"text": "O(n log n)",
"rationale": "正确。快速排序平均为 O(n log n),具有良好的枢轴选择和平衡分区。"
},
{
"text": "O(n²)",
"rationale": "错误。这是最坏情况下的复杂度,当枢轴选择较差时(例如,已经排序的数组使用第一个/最后一个元素作为枢轴)。"
},
{
"text": "O(log n)",
"rationale": "错误。对数时间适用于像二分查找这样的操作,而不是完整的排序算法。"
}
],
"correct_answer": 1
},
{
"id": 2,
"type": "true_false",
"question": "归并排序是一种稳定排序算法。",
"correct_answer": true,
"explanation": "归并排序保留了相等元素的相对顺序,使其稳定。"
}
]
}
```
**累积模式:**
当 `cumulative = true` 且 `output_path` 存在时,新问题会追加到现有数组中,ID 会顺序重新编号。这允许您通过多次调用建立问题库。
## 项目布局
```text
src/mcp_notebooklm/
├── __init__.py
├── main.py # 入口点 → server.main()
├── server.py # FastMCP 工具定义(list, find, ask, generate_quiz)
└── service.py # NotebookLMClient 包装 + 并发 / 超时保护 + 测验生成
data/
└── auth.json # notebooklm-py 会话存储(git-ignored)
pyproject.toml # 依赖项,入口点:mcp-notebooklm
```
## 开发
```bash
uv run ruff check src/ # 校验
uv run flake8 src/ # 风格
```
## 备注和限制
- 上游库使用 **未记录的 Google API** — 端点可以无通知地中断。
- 重度使用会受到速率限制;1-并发信号量是故意的,不是 bug。带有许多问题的测验生成将由于顺序批次而需要时间。
- 仅使用 `chat.ask` 端点。源管理、工件生成等未连接到 MCP 接口。
- 服务器仅支持标准输入输出。对于 HTTP,请查看上游 `notebooklm-py` REST 服务器。