notebooklm-mcp-server 3.0.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/auth.js CHANGED
@@ -77,10 +77,27 @@ export class AuthManager {
77
77
  }
78
78
  if (onStatus)
79
79
  onStatus('Extracting secure session cookies...');
80
- const cookies = await context.cookies();
81
- const cookieString = cookies
82
- .map(c => `${c.name}=${c.value}`)
80
+ // CRITICAL: Filter cookies to only those that match notebooklm.google.com
81
+ // Playwright's context.cookies() without URL returns ALL cookies from ALL domains
82
+ // (including accounts.google.com, youtube.com, etc.), causing duplicate cookie names
83
+ // and conflicting session values. CDP's Network.getCookies (used by Python) only
84
+ // returns cookies for the current page URL. We match that behavior here.
85
+ const allCookies = await context.cookies('https://notebooklm.google.com');
86
+ // Deduplicate by name (keep last value, like browsers do)
87
+ const cookieMap = new Map();
88
+ for (const c of allCookies) {
89
+ cookieMap.set(c.name, c.value);
90
+ }
91
+ const cookieString = Array.from(cookieMap.entries())
92
+ .map(([name, value]) => `${name}=${value}`)
83
93
  .join('; ');
94
+ // Validate that required session cookies are present
95
+ const REQUIRED_COOKIES = ['SID', 'HSID', 'SSID', 'APISID', 'SAPISID'];
96
+ const missingCookies = REQUIRED_COOKIES.filter(name => !cookieMap.has(name));
97
+ if (missingCookies.length > 0) {
98
+ console.error(`Warning: Missing required cookies: ${missingCookies.join(', ')}`);
99
+ }
100
+ console.error(`Extracted ${cookieMap.size} unique cookies for notebooklm.google.com`);
84
101
  const authData = {
85
102
  cookies: cookieString,
86
103
  updatedAt: new Date().toISOString()
package/dist/client.d.ts CHANGED
@@ -68,6 +68,16 @@ export declare class NotebookLMClient {
68
68
  */
69
69
  private extractRpcResult;
70
70
  listNotebooks(): Promise<Notebook[]>;
71
+ /**
72
+ * Get a single notebook's data including all source IDs.
73
+ * Uses the GET_NOTEBOOK RPC (rLM1Ne).
74
+ */
75
+ getNotebook(notebookId: string): Promise<any>;
76
+ /**
77
+ * Extract source IDs from raw notebook data returned by getNotebook().
78
+ * Matches Python _extract_source_ids_from_notebook().
79
+ */
80
+ private extractSourceIdsFromNotebook;
71
81
  createNotebook(title: string): Promise<string>;
72
82
  deleteNotebook(notebookId: string): Promise<boolean>;
73
83
  renameNotebook(notebookId: string, newTitle: string): Promise<boolean>;
package/dist/client.js CHANGED
@@ -340,6 +340,47 @@ export class NotebookLMClient {
340
340
  }
341
341
  return notebooks;
342
342
  }
343
+ /**
344
+ * Get a single notebook's data including all source IDs.
345
+ * Uses the GET_NOTEBOOK RPC (rLM1Ne).
346
+ */
347
+ async getNotebook(notebookId) {
348
+ // Python: params = [notebook_id, None, [2], None, 0]
349
+ const result = await this.callRpc(RPC_IDS.GET_NOTEBOOK, [notebookId, null, [2], null, 0], `/notebook/${notebookId}`);
350
+ return result;
351
+ }
352
+ /**
353
+ * Extract source IDs from raw notebook data returned by getNotebook().
354
+ * Matches Python _extract_source_ids_from_notebook().
355
+ */
356
+ extractSourceIdsFromNotebook(notebookData) {
357
+ const sourceIds = [];
358
+ if (!notebookData || !Array.isArray(notebookData))
359
+ return sourceIds;
360
+ try {
361
+ // Structure: notebookData[0] = [title, sources_array, notebook_id, ...]
362
+ const notebookInfo = Array.isArray(notebookData[0]) ? notebookData[0] : notebookData;
363
+ if (notebookInfo.length > 1 && Array.isArray(notebookInfo[1])) {
364
+ const sources = notebookInfo[1];
365
+ for (const source of sources) {
366
+ // Each source: [[source_id], title, metadata, ...]
367
+ if (Array.isArray(source) && source.length > 0) {
368
+ const sourceIdWrapper = source[0];
369
+ if (Array.isArray(sourceIdWrapper) && sourceIdWrapper.length > 0) {
370
+ const sourceId = sourceIdWrapper[0];
371
+ if (typeof sourceId === 'string') {
372
+ sourceIds.push(sourceId);
373
+ }
374
+ }
375
+ }
376
+ }
377
+ }
378
+ }
379
+ catch {
380
+ // ignore parse errors
381
+ }
382
+ return sourceIds;
383
+ }
343
384
  async createNotebook(title) {
344
385
  // Python: params = [title, None, None, [2], [1, None, None, None, None, None, None, None, None, None, [1]]]
345
386
  const params = [title, null, null, [2], [1, null, null, null, null, null, null, null, null, null, [1]]];
@@ -973,9 +1014,21 @@ export class NotebookLMClient {
973
1014
  // =========================================================================
974
1015
  async query(notebookId, queryText, sourceIds, conversationId, _retryCount = 0) {
975
1016
  await this.init();
1017
+ // Auto-fetch source_ids from notebook if not provided (matches Python behavior)
1018
+ if (!sourceIds || sourceIds.length === 0) {
1019
+ try {
1020
+ const notebookData = await this.getNotebook(notebookId);
1021
+ sourceIds = this.extractSourceIdsFromNotebook(notebookData);
1022
+ console.error(`[NotebookLM] Auto-fetched ${sourceIds.length} source IDs from notebook`);
1023
+ }
1024
+ catch (e) {
1025
+ console.error(`[NotebookLM] Warning: Could not auto-fetch source IDs: ${e.message}`);
1026
+ sourceIds = [];
1027
+ }
1028
+ }
976
1029
  const cid = conversationId || uuidv4();
977
1030
  // Python: sources_array = [[[sid]] for sid in source_ids] (triple nested)
978
- const sources = sourceIds ? sourceIds.map(id => [[id]]) : [];
1031
+ const sources = sourceIds.length > 0 ? sourceIds.map(id => [[id]]) : [];
979
1032
  // Python: params = [sources_array, query_text, None, [2, null, [1]], conversation_id]
980
1033
  const params = [
981
1034
  sources,
package/dist/server.js CHANGED
@@ -4,7 +4,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextpro
4
4
  import { NotebookLMClient } from "./client.js";
5
5
  import { AuthManager } from "./auth.js";
6
6
  import chalk from "chalk";
7
- const VERSION = "3.0.1";
7
+ const VERSION = "3.0.3";
8
8
  const server = new Server({
9
9
  name: "notebooklm-mcp-server",
10
10
  version: VERSION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "notebooklm-mcp-server",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Node.js Model Context Protocol server for Google NotebookLM",
5
5
  "type": "module",
6
6
  "repository": {