
notebooklm-py 的 MCP 工具粒度治理mega-tool 与离散动词之争、Schema 预算棘轮与 38 个工具的决策全记录【免费下载链接】notebooklm-pyUnofficial Python API and agentic skill for Google Gemini Notebook. Full programmatic access to NotebookLMs features—including capabilities the web UI doesnt expose—via Python, CLI, and AI agents like Claude Code, Codex, and OpenClaw.项目地址: https://gitcode.com/GitHub_Trending/no/notebooklm-py本文基于 notebooklm-py 仓库中已接受的 ADR-0025docs/adr/0025-mcp-tool-granularity.md完整还原该项目围绕 MCPModel Context ProtocolServer 工具粒度做出的核心决策为什么不拆分source_add/artifact_generate两个巨型工具、如何用 Schema 字符预算棘轮防止工具表面无限膨胀以及后续三次表面变更两次折回合并、一次逆势新增的chat_start/chat_status对如何在该决策框架内演进出当前 38 个工具、44,590 Schema 字符的最终形态。读完后你既能理解更少工具与更清晰契约之间的权衡方法论也能直接获得一套可复用的工具表面治理手段精确 manifest 测试、参数上限棘轮与 Schema 成本预算。问题背景35 个工具已超建议值而两个 mega-tool 把契约藏在运行时ADR-0025 撰写时notebooklm-py 的 MCP 表面为35 个工具更新后为 38 个见 tests/unit/mcp/test_manifest.py上限 40超出业界指南建议的每 Server 5–15 个工具区间ADR 中引用了 Anthropic 2025 年 9 月的工具编写指南以及 GitHub Copilot 将工具数从 40 削减到 13 后准确性与延迟均有提升的行业事实。真正的矛盾不在工具偏多而在工具接口评审发现两个工具承载了相反的问题——它们是 mega-tool巨型工具真实的调用契约存在于运行时校验器中是 JSON Schema 无法表达的部分source_add— 10 个参数、两种模式单条经source_type批量经urls、每个参数都可省略由三个运行时校验器强制哪些参数组合合法实现位于 src/notebooklm/mcp/tools/sources.py。artifact_generate现名为studio_generate— 20 个参数各 artifact 类型的选项适用性在运行时检查选项取值已经用Literal固定到核心映射表上。沿着离散动词方向走完的修复方案把 ADR-0021 传输中立哲学应用到工具边界是把它们拆开让 Schema 自己陈述每种契约。但拆分会推高工具总数与更少工具的证据直接冲突——除非配合渐进式披露progressive disclosure延迟工具加载Anthropic 的 Tool Search Tool 用该机制将 Schema token 成本削减约 85% 并提升了准确率。ADR 指出的决定性约束是渐进式披露是客户端/平台特性。MCP 规范2025-06-18要求 Server 通过tools/list广播完整工具列表不存在 Server 侧强制延迟加载。因此一个 MCP Server 无法为任意客户端Claude Desktop/Code、Cursor 等保证精简的上下文内表面。当时的上限算术以 Tier-1 读合并把表面从 37 降到 35 之后计把source_add拆成source_add_url/_file/_text保留已有批量模式是3 工具 38恰好落在 40 上限之内还留有少量余量——所以上限本身不再阻塞那次拆分但artifact_generate按家族的完整拆分数个仍会突破 40。撰写时表面为 37source_add拆分恰好落在 40——后来的 Tier-1 合并释放了两个槽位。决策现在不拆分 mega-tool用三条具体规则固化立场ADR-0025 的决策是**现在不拆分 mega-tools**并给出三条具体规则artifact_generate保持统一。其有限选项已经是固定到核心映射表的Literal枚举只有按类型适用性留在运行时而按家族拆分会突破上限还会把共享的source_ids/language/style参数在 N 个工具上重复。改法是通过更精炼的 docstring 按类型示例来改进响应塑形阶段而不是拆工具。source_add的拆分推迟而非采纳。它是更强的拆分候选互斥参数、三个运行时校验器但它已支持批量且会耗尽剩余的上限余量。只有当 (a) 某个客户端支持的精简表面机制落地或 (b) 有意提高上限并以该拆分为理由时才重新审视。不实现渐进式披露。Server 端无法强制。保持描述精简这样确实会做延迟加载的客户端付出更少把配置注册核心工具子集的选项留作未来工作而非承诺交付物。同时明确不触碰工具数量的一致性改进与响应塑形改进——统一变更mutation信封、标识符/命名一致性、列表分页、有界内容读取——独立于本决策推进。这一立场在代码中有直接的工程化承载。src/notebooklm/mcp/server.py 中register_all是工具注册的单一咽喉点single chokepoint把 notebooks/sources/chat/notes/studio/research/sharing/meta 等域模块逐一挂到 FastMCP 上SERVER_INSTRUCTIONS则以 Server 级指令告诉 agent 长任务拆成非阻塞 generate返回 task_id status 轮询、破坏性工具需confirmtrue等全局协议——这正是描述保持精简、把公共契约上移决策的落地。约束的棘轮化manifest 测试与工具评估 harnessADR 的 Consequences 部分把如果 mega-tool 变大、或表面 token 成本爬升棘轮会失败并强制重新审视写成了硬机制。仓库中对应两套测试1. 精确 manifest 门tests/unit/mcp/test_manifest.py通过内存 FastMCPClient构建 Server绑定 mock client并列出工具然后钉死完整工具名集合EXPECTED_TOOLS——当前 38 个工具横跨 8 个域任何静默增删改名都会失败该门。集合注释完整记录了演化链设计目标约 25 → 共享域到 34 → artifact get-prompt/retry 到 36 →suggest_prompts到 37 → Tier-1 读合并降到 32 → source-add 组合工具回升 → #1890 折回source_add到 34 → #1896 折到 33 → 分离式 ask 对chat_start/chat_status到 35 → #2292 Play Books 工具到 37 → #2303 取消动词到 38工具数上限TOOL_CEILING 40上限有呼吸空间但意外爆炸仍会触发门;破坏性工具双契约notebook_delete、source_delete、studio_delete、share_remove_user必须同时带destructiveHint注解与confirm参数只读工具注解notebook_list、source_read、chat_status、studio_status等 13 个只读工具必须带readOnlyHint另有共享放宽类变更工具share_set_access/share_set_user单独成类——带confirm默认False但故意不带destructiveHint。2. 离线工具评估 harnesstests/unit/mcp/test_tool_eval.pyADR 所称离线工具评估 harnessSchema token 成本 参数数代理指标即此文件。它是静态、确定性、无 live model 的诚实度量两个可诚实度量的量并棘轮化Schema token 成本——按工具与全表面的字符代理序列化inputSchema description 长度。当前棘轮值SCHEMA_CHAR_BUDGET 44_610实测 44,590保留约 20 字符惯例余量。文件头部的注释按时间线记录了每次预算变更的逐字符依据#1807 新增source_add_and_wait约 1,920 字符、11 参数、#1803 新增source_upload_bytes1,581、Phase 1 远程上传的await_upload773、2 参数、#1890 折回−3,099从 42,450 棘轮到 39,319 实测、#1896 折回−367棘轮到 39,015、#2286 chat 分离对2,830重调用协议文本 2,262、批量轮询/队列状态/计时 443、复评的重新提问措辞 125直至 #2303 的chat_cancel43,386 → 44,590。Schema 歧义代理——每工具可见参数数。MAX_PARAMS_PER_TOOL 22注释标明当前高水位是studio_generate。三条断言test_mega_tools_do_not_grow点名盯住studio_generate与source_add两个已知 mega-tool 不许长参数、test_no_tool_exceeds_param_ceiling任何新工具突破 22 即视为新 mega-tool 混入、以及全表面字符预算断言。pytest tests/unit/mcp/test_tool_eval.py -s还会打印按 Schema 字符数降序排列的每工具成本表。ADR 明确指出live 工具选择准确率故意不在此处度量需要真实模型超出该离线 harness 的范围。决策之后的四次表面变更两次折回与一次逆势新增ADR 正文是 2026-07 之前的快照其Update章节记录了决策框架在真实演化中的三次应用其中两次是折回合并一次是新增动词对——恰好构成该决策正反两面的完整判例集。Update #18902026-07把 source-add 组合体折回source_add两个源工具曾以离散动词形式在组合 vs mega-tool张力下发布source_add_and_wait单模式 add source_wait合成一次调用与source_upload_bytes通道内 base64 文件添加。ADR 判定它们不是独立操作——各自只是添加源的一个切面source_upload_bytes是文件输入模式bytes 代替 pathadd 运行前解码source_add_and_wait是 add 与后续source_wait轮询的同调用合成。再加上source_add_drive_file本就带wait: bool单独的 wait-动词反而制造不一致。两者被折回source_addadd wait→source_add(..., waitTrue, timeout…, interval…)——返回source_wait聚合buckets 各桶*_counttotal_count与顶层source_id超时/失败时也存在仅限单条源不适用于远端file签名 URL 上传通道内字节→source_add(source_typefile, bytes_base64…, filename…)——file类型的path替代项任意传输可用标准 base64、≤10,000 字符约 7 KB更大文件走签名 URL≤200 MiB。净效果36 → 34 工具、−3,099 Schema 字符SCHEMA_CHAR_BUDGET从 42,450 棘轮到 39,400 一线。source_add增长到15 个参数——仍远低于MAX_PARAMS_PER_TOOL 22test_mega_tools_do_not_grow参数上限保持成立。这正体现了优先重载现有工具而非新增工具——与论证反对拆分 mega-tool 的同一批更少工具证据是同一枚硬币的两面合并这些组合体降低了 harness 棘轮计量的表面总 Schema token 成本。底层_app的 addwait / bytes 逻辑_waitagg、_fileupload原样保留——只删除了两个 MCP 工具注册。这一折回在当前 src/notebooklm/mcp/tools/sources.py 的source_addL617 起中可直接验证15 个参数签名notebook、source_type、url、text、title、path、bytes_base64、filename、document_id、mime_type、allow_internal、wait、timeout、interval、urlsdocstring 完整陈述了单模式/批量模式二选一的 fail-closed 契约且source_type/urls互斥、wait仅限单模式、批量条目数上限共享_app.source_batch.MAX_BATCH_URLS等三个运行时校验器约束逐一落地在 I/O 之前的失败快速分支里。Update #18962026-07把studio_get_prompt折进studio_liststudio_get_prompt(notebook, artifact)曾是返回单个 artifact 生成提示词的只读工具。但类型化Artifact已携带generation_prompt从LIST_ARTIFACTS行解码#1925且默认studio_list的摘要列表已在每一行上暴露它——独立工具只是复制了统一列表工具已有的能力。删除后其单 artifact 查找折到现有studio_list(item…)路径现在透传include_artifact_metaTrue使解析出的 artifact 携带其 prompt。这是 ADR-0025 更少工具证据中**优先折入现有工具而非独立动词**的一面——与 #1890 同源。由于 prompt 搭载列表本就拉取的LIST_ARTIFACTS行没有额外请求无逐 artifact 拉取、无 N1。净效果34 → 33 工具、−367 Schema 字符预算从 39,400 棘轮到 39,050实测 39,015。传输中立的_app.get_artifact_prompt核心原样保留——CLI 的notebooklm artifact get-prompt与 REST 路由仍在使用只删除了 MCP 工具注册。该更新还留下重要的解析语义注记studio_list(item…)走统一的跨类型 Studio 解析器resolve_studio_item在合并的 notesartifacts 列表上按完整 id / hex 前缀 / 精确标题解析——与studio_delete/studio_rename同一解析器不是旧的 artifact 域内resolve_artifact。因此相对studio_get_prompt同时被某 note 和某 artifact 精确共用的标题会歧义传kind限定域artifact-标题前缀查找不再支持用 id 或完整标题。这是单解析器 Studio 表面的有意后果且对常见场景无碍——摘要列表已暴露每个 artifact 的 prompt无需任何引用。Update #22862026-09chat_start/chat_status作为两个独立动词慢速 chat 生成的分离式 ask 对issue #2285以两个新工具落地而非重载chat_ask——这是该 ADR 两次折回之后的首次表面增长也是最需要对优先重载现有工具这条纹理逆行之处的变更。重载备选方案chat_ask(..., detachtrue)返回task_id轮询折到chat_ask(task_id…)约 9 个参数、对 22 上限毫无压力却因两点被否决——这两点恰恰是上面折回所没有面对的chat_ask的线上契约是{answer, turn_number, references, …}被所有现有调用方钉死detach标志会让同一工具按一个布尔返回两种无关形状——正是变更信封规则要防止的每工具不同成功形状成本轮询是与 ask 生命周期词汇不同的另一操作pending/completed/failed/unknown与await_upload对齐且它 READ_ONLY 而chat_ask不是——折叠会丢掉轮询的readOnlyHint或错误地把该提示延伸到 ask。于是 chat 遵循既有长任务先例studio_generate/studio_status、research_start/research_status同样是独立的 starter poll 对而非折入先例后者适用于同一操作的变体。净效果35 → 37 工具初写时为 33 → 35#2292 的两个 Play Books 动词在中间落地见 src/notebooklm/mcp/tools/sources_playbooks.pySCHEMA_CHAR_BUDGET从 40,580 棘轮到 43,410。这对工具在 src/notebooklm/mcp/tools/chat.py 中可直接核对chat_startL311以watchdog 安全的提问路径自述——大型/共享 notebook 常需 1–3 分钟而远端 MCP 传输在约 60 秒静默后切断调用会杀死阻塞式chat_ask的生成中途ask 作为 server 自有任务运行返回started/already_runningtask_idchat_statusL401READ_ONLY注解支持单个/列表/逗号分隔字符串三种 id 形态、单次最多 64 个 id 的批量轮询逐任务返回pendingqueued/generating/completed含queued_s/generation_s计时/failed/unknown四态。Update #23032026-09实时 chat 会话控制——chat_cancel的落地生成状态复用chat_status的互斥notebook模式它仍是同一读动词保留readOnlyHint——conversation_id可选并默认到该 notebook 最近会话结果idle/generating含 Google 提供的 generation token源码中notebook与task_id同时给出即抛ValidationError。取消则是不同的变更操作所以新增chat_cancel而非让chat_status条件变写、或重载chat_ask。当提供分离式task_id时它合成服务端取消 放弃 MCP 自有的流——这是 Google 在 Web 端刻意保持打开的流。chat_cancelchat.py L490 起先本地取消任务使终态检查对竞态安全旧任务不可能取消恰好共享同一会话的新生成再取消关联的 Google 会话且会拒绝未知task_id或属于其他 notebook 的task_id。净效果37 → 38 工具Schema 字符43,386 → 44,590棘轮到 44,610。ADR 的结语点明性质这消耗上限剩余槽位之一用于一个无法通过现有变更工具如实表达的后台操作。方法论沉淀什么时候重载、什么时候独立动词把 ADR 正文与三次 Update 对齐后可以提炼出该项目实际执行的判定规则均有一手案例支撑判据结论案例新能力是同一操作的输入/组合变体bytes vs pathadd wait重载现有工具删独立动词#1890 折回source_add新能力复制现有工具已暴露的字段折入现有工具prompt 随列表行走#1896 折回studio_list新操作与现有工具成功形状不同或读写语义不同独立 starter/poll 或动词对#2286chat_start/chat_status、#2303chat_cancel拆分会把互斥契约暴露给 Schema但参数适用性检查必须留在运行时、且上限不允许保留 mega-tool用 docstring 参数上限棘轮兜底source_add、studio_generate保持不拆配套的工程护栏使这些规则不可被悄悄绕过manifest 门钉死工具全集与数量上限40、字符预算棘轮44,610与参数上限棘轮22test_tool_eval.py L33–L35、L128、readOnlyHint/destructiveHint/confirm的注解契约测试test_manifest.py。ADR 同时留了明确的再评审触发器若 Anthropic 等客户端标准化server 可提示的延迟加载多个 MCP SEP 在途应重审本决策——source_add拆分是第一个要重想的并以上限上调为其理由。适用前提与限制文中所有工具数、字符预算、参数上限均对应当前仓库快照38 工具 / 44,590 实测字符 / 44,610 预算 / 22 参数上限 / 40 工具上限ADR 正文中的 35/40 等数字是撰写时的历史值文中已按 ADR 自身标注区分。MCP 工具测试依赖mcpextrafastmcp缺少该依赖时tests/unit/mcp/会被 conftest 的collect_ignore_glob自动跳过。ADR 中的行业对照Anthropic 指南、Copilot 40→13、Tool Search Tool 约 85% 削减是撰写者引用的外部证据仓库内不承载其可验证性本文只将其作为决策背景转述。ADR-0025 只约束MCP 工具表面的粒度与成本CLI 与 REST 路由共享同一套传输中立_app核心如get_artifact_prompt在 CLInotebooklm artifact get-prompt与 REST 路由中仍在使用不受折回工具注册的影响。【免费下载链接】notebooklm-pyUnofficial Python API and agentic skill for Google Gemini Notebook. Full programmatic access to NotebookLMs features—including capabilities the web UI doesnt expose—via Python, CLI, and AI agents like Claude Code, Codex, and OpenClaw.项目地址: https://gitcode.com/GitHub_Trending/no/notebooklm-py创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考