notebooklm-mcp-ultimate 2.2.1

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.
Files changed (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +420 -0
  3. package/dist/api/batch-execute-client.d.ts +232 -0
  4. package/dist/api/batch-execute-client.d.ts.map +1 -0
  5. package/dist/api/batch-execute-client.js +672 -0
  6. package/dist/api/batch-execute-client.js.map +1 -0
  7. package/dist/api/content-types.d.ts +44 -0
  8. package/dist/api/content-types.d.ts.map +1 -0
  9. package/dist/api/content-types.js +89 -0
  10. package/dist/api/content-types.js.map +1 -0
  11. package/dist/api/csrf-manager.d.ts +94 -0
  12. package/dist/api/csrf-manager.d.ts.map +1 -0
  13. package/dist/api/csrf-manager.js +178 -0
  14. package/dist/api/csrf-manager.js.map +1 -0
  15. package/dist/api/index.d.ts +27 -0
  16. package/dist/api/index.d.ts.map +1 -0
  17. package/dist/api/index.js +56 -0
  18. package/dist/api/index.js.map +1 -0
  19. package/dist/api/operation-poller.d.ts +67 -0
  20. package/dist/api/operation-poller.d.ts.map +1 -0
  21. package/dist/api/operation-poller.js +132 -0
  22. package/dist/api/operation-poller.js.map +1 -0
  23. package/dist/api/request-builder.d.ts +196 -0
  24. package/dist/api/request-builder.d.ts.map +1 -0
  25. package/dist/api/request-builder.js +371 -0
  26. package/dist/api/request-builder.js.map +1 -0
  27. package/dist/api/response-parser.d.ts +124 -0
  28. package/dist/api/response-parser.d.ts.map +1 -0
  29. package/dist/api/response-parser.js +595 -0
  30. package/dist/api/response-parser.js.map +1 -0
  31. package/dist/api/rpc-ids.d.ts +92 -0
  32. package/dist/api/rpc-ids.d.ts.map +1 -0
  33. package/dist/api/rpc-ids.js +138 -0
  34. package/dist/api/rpc-ids.js.map +1 -0
  35. package/dist/api/streaming-chat-client.d.ts +50 -0
  36. package/dist/api/streaming-chat-client.d.ts.map +1 -0
  37. package/dist/api/streaming-chat-client.js +198 -0
  38. package/dist/api/streaming-chat-client.js.map +1 -0
  39. package/dist/api/types.d.ts +318 -0
  40. package/dist/api/types.d.ts.map +1 -0
  41. package/dist/api/types.js +22 -0
  42. package/dist/api/types.js.map +1 -0
  43. package/dist/auth/auth-manager.d.ts +163 -0
  44. package/dist/auth/auth-manager.d.ts.map +1 -0
  45. package/dist/auth/auth-manager.js +1055 -0
  46. package/dist/auth/auth-manager.js.map +1 -0
  47. package/dist/auth/cookie-store.d.ts +121 -0
  48. package/dist/auth/cookie-store.d.ts.map +1 -0
  49. package/dist/auth/cookie-store.js +283 -0
  50. package/dist/auth/cookie-store.js.map +1 -0
  51. package/dist/config.d.ts +89 -0
  52. package/dist/config.d.ts.map +1 -0
  53. package/dist/config.js +217 -0
  54. package/dist/config.js.map +1 -0
  55. package/dist/errors.d.ts +26 -0
  56. package/dist/errors.d.ts.map +1 -0
  57. package/dist/errors.js +41 -0
  58. package/dist/errors.js.map +1 -0
  59. package/dist/index.d.ts +32 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +439 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/library/notebook-library.d.ts +79 -0
  64. package/dist/library/notebook-library.d.ts.map +1 -0
  65. package/dist/library/notebook-library.js +296 -0
  66. package/dist/library/notebook-library.js.map +1 -0
  67. package/dist/library/types.d.ts +67 -0
  68. package/dist/library/types.d.ts.map +1 -0
  69. package/dist/library/types.js +8 -0
  70. package/dist/library/types.js.map +1 -0
  71. package/dist/operations/content-operations.d.ts +78 -0
  72. package/dist/operations/content-operations.d.ts.map +1 -0
  73. package/dist/operations/content-operations.js +162 -0
  74. package/dist/operations/content-operations.js.map +1 -0
  75. package/dist/operations/hybrid-executor.d.ts +47 -0
  76. package/dist/operations/hybrid-executor.d.ts.map +1 -0
  77. package/dist/operations/hybrid-executor.js +114 -0
  78. package/dist/operations/hybrid-executor.js.map +1 -0
  79. package/dist/operations/notebook-crud-operations.d.ts +52 -0
  80. package/dist/operations/notebook-crud-operations.d.ts.map +1 -0
  81. package/dist/operations/notebook-crud-operations.js +248 -0
  82. package/dist/operations/notebook-crud-operations.js.map +1 -0
  83. package/dist/operations/research-operations.d.ts +42 -0
  84. package/dist/operations/research-operations.d.ts.map +1 -0
  85. package/dist/operations/research-operations.js +189 -0
  86. package/dist/operations/research-operations.js.map +1 -0
  87. package/dist/operations/source-operations.d.ts +59 -0
  88. package/dist/operations/source-operations.d.ts.map +1 -0
  89. package/dist/operations/source-operations.js +280 -0
  90. package/dist/operations/source-operations.js.map +1 -0
  91. package/dist/operations/studio-operations.d.ts +98 -0
  92. package/dist/operations/studio-operations.d.ts.map +1 -0
  93. package/dist/operations/studio-operations.js +309 -0
  94. package/dist/operations/studio-operations.js.map +1 -0
  95. package/dist/resources/resource-handlers.d.ts +22 -0
  96. package/dist/resources/resource-handlers.d.ts.map +1 -0
  97. package/dist/resources/resource-handlers.js +216 -0
  98. package/dist/resources/resource-handlers.js.map +1 -0
  99. package/dist/session/browser-session.d.ts +113 -0
  100. package/dist/session/browser-session.d.ts.map +1 -0
  101. package/dist/session/browser-session.js +670 -0
  102. package/dist/session/browser-session.js.map +1 -0
  103. package/dist/session/session-manager.d.ts +88 -0
  104. package/dist/session/session-manager.d.ts.map +1 -0
  105. package/dist/session/session-manager.js +314 -0
  106. package/dist/session/session-manager.js.map +1 -0
  107. package/dist/session/shared-context-manager.d.ts +107 -0
  108. package/dist/session/shared-context-manager.d.ts.map +1 -0
  109. package/dist/session/shared-context-manager.js +447 -0
  110. package/dist/session/shared-context-manager.js.map +1 -0
  111. package/dist/tools/definitions/ask-question.d.ts +8 -0
  112. package/dist/tools/definitions/ask-question.d.ts.map +1 -0
  113. package/dist/tools/definitions/ask-question.js +213 -0
  114. package/dist/tools/definitions/ask-question.js.map +1 -0
  115. package/dist/tools/definitions/content-generation.d.ts +52 -0
  116. package/dist/tools/definitions/content-generation.d.ts.map +1 -0
  117. package/dist/tools/definitions/content-generation.js +236 -0
  118. package/dist/tools/definitions/content-generation.js.map +1 -0
  119. package/dist/tools/definitions/notebook-crud.d.ts +9 -0
  120. package/dist/tools/definitions/notebook-crud.d.ts.map +1 -0
  121. package/dist/tools/definitions/notebook-crud.js +156 -0
  122. package/dist/tools/definitions/notebook-crud.js.map +1 -0
  123. package/dist/tools/definitions/notebook-management.d.ts +3 -0
  124. package/dist/tools/definitions/notebook-management.d.ts.map +1 -0
  125. package/dist/tools/definitions/notebook-management.js +243 -0
  126. package/dist/tools/definitions/notebook-management.js.map +1 -0
  127. package/dist/tools/definitions/research.d.ts +23 -0
  128. package/dist/tools/definitions/research.d.ts.map +1 -0
  129. package/dist/tools/definitions/research.js +108 -0
  130. package/dist/tools/definitions/research.js.map +1 -0
  131. package/dist/tools/definitions/session-management.d.ts +3 -0
  132. package/dist/tools/definitions/session-management.d.ts.map +1 -0
  133. package/dist/tools/definitions/session-management.js +41 -0
  134. package/dist/tools/definitions/session-management.js.map +1 -0
  135. package/dist/tools/definitions/source-management.d.ts +39 -0
  136. package/dist/tools/definitions/source-management.d.ts.map +1 -0
  137. package/dist/tools/definitions/source-management.js +224 -0
  138. package/dist/tools/definitions/source-management.js.map +1 -0
  139. package/dist/tools/definitions/studio.d.ts +36 -0
  140. package/dist/tools/definitions/studio.d.ts.map +1 -0
  141. package/dist/tools/definitions/studio.js +153 -0
  142. package/dist/tools/definitions/studio.js.map +1 -0
  143. package/dist/tools/definitions/system.d.ts +3 -0
  144. package/dist/tools/definitions/system.d.ts.map +1 -0
  145. package/dist/tools/definitions/system.js +143 -0
  146. package/dist/tools/definitions/system.js.map +1 -0
  147. package/dist/tools/definitions.d.ts +12 -0
  148. package/dist/tools/definitions.d.ts.map +1 -0
  149. package/dist/tools/definitions.js +36 -0
  150. package/dist/tools/definitions.js.map +1 -0
  151. package/dist/tools/handlers/content-handlers.d.ts +287 -0
  152. package/dist/tools/handlers/content-handlers.d.ts.map +1 -0
  153. package/dist/tools/handlers/content-handlers.js +244 -0
  154. package/dist/tools/handlers/content-handlers.js.map +1 -0
  155. package/dist/tools/handlers/notebook-crud-handlers.d.ts +69 -0
  156. package/dist/tools/handlers/notebook-crud-handlers.d.ts.map +1 -0
  157. package/dist/tools/handlers/notebook-crud-handlers.js +117 -0
  158. package/dist/tools/handlers/notebook-crud-handlers.js.map +1 -0
  159. package/dist/tools/handlers/research-handlers.d.ts +37 -0
  160. package/dist/tools/handlers/research-handlers.d.ts.map +1 -0
  161. package/dist/tools/handlers/research-handlers.js +87 -0
  162. package/dist/tools/handlers/research-handlers.js.map +1 -0
  163. package/dist/tools/handlers/source-handlers.d.ts +52 -0
  164. package/dist/tools/handlers/source-handlers.d.ts.map +1 -0
  165. package/dist/tools/handlers/source-handlers.js +177 -0
  166. package/dist/tools/handlers/source-handlers.js.map +1 -0
  167. package/dist/tools/handlers/studio-handlers.d.ts +125 -0
  168. package/dist/tools/handlers/studio-handlers.d.ts.map +1 -0
  169. package/dist/tools/handlers/studio-handlers.js +183 -0
  170. package/dist/tools/handlers/studio-handlers.js.map +1 -0
  171. package/dist/tools/handlers.d.ts +629 -0
  172. package/dist/tools/handlers.d.ts.map +1 -0
  173. package/dist/tools/handlers.js +833 -0
  174. package/dist/tools/handlers.js.map +1 -0
  175. package/dist/tools/index.d.ts +8 -0
  176. package/dist/tools/index.d.ts.map +1 -0
  177. package/dist/tools/index.js +8 -0
  178. package/dist/tools/index.js.map +1 -0
  179. package/dist/types.d.ts +82 -0
  180. package/dist/types.d.ts.map +1 -0
  181. package/dist/types.js +5 -0
  182. package/dist/types.js.map +1 -0
  183. package/dist/utils/cleanup-manager.d.ts +133 -0
  184. package/dist/utils/cleanup-manager.d.ts.map +1 -0
  185. package/dist/utils/cleanup-manager.js +673 -0
  186. package/dist/utils/cleanup-manager.js.map +1 -0
  187. package/dist/utils/cli-handler.d.ts +16 -0
  188. package/dist/utils/cli-handler.d.ts.map +1 -0
  189. package/dist/utils/cli-handler.js +102 -0
  190. package/dist/utils/cli-handler.js.map +1 -0
  191. package/dist/utils/logger.d.ts +61 -0
  192. package/dist/utils/logger.d.ts.map +1 -0
  193. package/dist/utils/logger.js +92 -0
  194. package/dist/utils/logger.js.map +1 -0
  195. package/dist/utils/page-utils.d.ts +54 -0
  196. package/dist/utils/page-utils.d.ts.map +1 -0
  197. package/dist/utils/page-utils.js +405 -0
  198. package/dist/utils/page-utils.js.map +1 -0
  199. package/dist/utils/settings-manager.d.ts +37 -0
  200. package/dist/utils/settings-manager.d.ts.map +1 -0
  201. package/dist/utils/settings-manager.js +120 -0
  202. package/dist/utils/settings-manager.js.map +1 -0
  203. package/dist/utils/stealth-utils.d.ts +135 -0
  204. package/dist/utils/stealth-utils.d.ts.map +1 -0
  205. package/dist/utils/stealth-utils.js +398 -0
  206. package/dist/utils/stealth-utils.js.map +1 -0
  207. package/package.json +63 -0
@@ -0,0 +1,833 @@
1
+ /**
2
+ * MCP Tool Handlers
3
+ *
4
+ * Implements the logic for all MCP tools.
5
+ */
6
+ import { CONFIG, applyBrowserOptions } from "../config.js";
7
+ import { log } from "../utils/logger.js";
8
+ import { RateLimitError } from "../errors.js";
9
+ import { CleanupManager } from "../utils/cleanup-manager.js";
10
+ import { createContentHandlers } from "./handlers/content-handlers.js";
11
+ import { createStudioHandlers } from "./handlers/studio-handlers.js";
12
+ import { createSourceHandlers } from "./handlers/source-handlers.js";
13
+ import { createResearchHandlers } from "./handlers/research-handlers.js";
14
+ import { createNotebookCRUDHandlers } from "./handlers/notebook-crud-handlers.js";
15
+ const FOLLOW_UP_REMINDER = "\n\nEXTREMELY IMPORTANT: Is that ALL you need to know? You can always ask another question using the same session ID! Think about it carefully: before you reply to the user, review their original request and this answer. If anything is still unclear or missing, ask me another question first.";
16
+ /**
17
+ * MCP Tool Handlers
18
+ */
19
+ export class ToolHandlers {
20
+ sessionManager;
21
+ authManager;
22
+ library;
23
+ contentHandlers;
24
+ studioHandlers;
25
+ researchHandlers;
26
+ sourceHandlers;
27
+ notebookCRUDHandlers;
28
+ constructor(sessionManager, authManager, library) {
29
+ this.sessionManager = sessionManager;
30
+ this.authManager = authManager;
31
+ this.library = library;
32
+ // Initialize content, studio, source, and notebook CRUD handlers
33
+ this.contentHandlers = createContentHandlers({ library });
34
+ this.researchHandlers = createResearchHandlers({ library });
35
+ this.studioHandlers = createStudioHandlers({ library });
36
+ this.sourceHandlers = createSourceHandlers({ library });
37
+ this.notebookCRUDHandlers = createNotebookCRUDHandlers({ library });
38
+ }
39
+ /**
40
+ * Handle ask_question tool
41
+ */
42
+ async handleAskQuestion(args, sendProgress) {
43
+ const { question, session_id, notebook_id, notebook_url, show_browser, browser_options } = args;
44
+ // Validate question
45
+ if (!question || typeof question !== 'string' || !question.trim()) {
46
+ return { success: false, error: 'Question is required and must be non-empty' };
47
+ }
48
+ log.info(`๐Ÿ”ง [TOOL] ask_question called`);
49
+ log.info(` Question: "${question.substring(0, 100)}"...`);
50
+ if (session_id) {
51
+ log.info(` Session ID: ${session_id}`);
52
+ }
53
+ if (notebook_id) {
54
+ log.info(` Notebook ID: ${notebook_id}`);
55
+ }
56
+ if (notebook_url) {
57
+ log.info(` Notebook URL: ${notebook_url}`);
58
+ }
59
+ try {
60
+ // Resolve notebook URL
61
+ let resolvedNotebookUrl = notebook_url;
62
+ if (!resolvedNotebookUrl && notebook_id) {
63
+ const notebook = this.library.incrementUseCount(notebook_id);
64
+ if (!notebook) {
65
+ throw new Error(`Notebook not found in library: ${notebook_id}`);
66
+ }
67
+ resolvedNotebookUrl = notebook.url;
68
+ log.info(` Resolved notebook: ${notebook.name}`);
69
+ }
70
+ else if (!resolvedNotebookUrl) {
71
+ const active = this.library.getActiveNotebook();
72
+ if (active) {
73
+ const notebook = this.library.incrementUseCount(active.id);
74
+ if (!notebook) {
75
+ throw new Error(`Active notebook not found: ${active.id}`);
76
+ }
77
+ resolvedNotebookUrl = notebook.url;
78
+ log.info(` Using active notebook: ${notebook.name}`);
79
+ }
80
+ }
81
+ // Validate URL scheme
82
+ if (resolvedNotebookUrl) {
83
+ try {
84
+ const parsed = new URL(resolvedNotebookUrl);
85
+ if (!['http:', 'https:'].includes(parsed.protocol)) {
86
+ throw new Error(`Invalid URL scheme: ${parsed.protocol}`);
87
+ }
88
+ }
89
+ catch (e) {
90
+ return { success: false, error: `Invalid notebook URL: ${e instanceof Error ? e.message : e}` };
91
+ }
92
+ }
93
+ // Progress: Getting or creating session
94
+ await sendProgress?.("Getting or creating browser session...", 1, 5);
95
+ // Apply browser options temporarily
96
+ const originalConfig = { ...CONFIG };
97
+ const effectiveConfig = applyBrowserOptions(browser_options, show_browser);
98
+ Object.assign(CONFIG, effectiveConfig);
99
+ // Calculate overrideHeadless parameter for session manager
100
+ // show_browser takes precedence over browser_options.headless
101
+ let overrideHeadless = undefined;
102
+ if (show_browser !== undefined) {
103
+ overrideHeadless = show_browser;
104
+ }
105
+ else if (browser_options?.show !== undefined) {
106
+ overrideHeadless = browser_options.show;
107
+ }
108
+ else if (browser_options?.headless !== undefined) {
109
+ overrideHeadless = !browser_options.headless;
110
+ }
111
+ try {
112
+ // Get or create session (with headless override to handle mode changes)
113
+ const session = await this.sessionManager.getOrCreateSession(session_id, resolvedNotebookUrl, overrideHeadless);
114
+ // Progress: Asking question
115
+ await sendProgress?.("Asking question to NotebookLM...", 2, 5);
116
+ // Ask the question (pass progress callback)
117
+ const rawAnswer = await session.ask(question, sendProgress);
118
+ const answer = `${rawAnswer.trimEnd()}${FOLLOW_UP_REMINDER}`;
119
+ // Get session info
120
+ const sessionInfo = session.getInfo();
121
+ const result = {
122
+ status: "success",
123
+ question,
124
+ answer,
125
+ session_id: session.sessionId,
126
+ notebook_url: session.notebookUrl,
127
+ session_info: {
128
+ age_seconds: sessionInfo.age_seconds,
129
+ message_count: sessionInfo.message_count,
130
+ last_activity: sessionInfo.last_activity,
131
+ },
132
+ };
133
+ // Progress: Complete
134
+ await sendProgress?.("Question answered successfully!", 5, 5);
135
+ log.success(`โœ… [TOOL] ask_question completed successfully`);
136
+ return {
137
+ success: true,
138
+ data: result,
139
+ };
140
+ }
141
+ finally {
142
+ // Restore original CONFIG
143
+ Object.assign(CONFIG, originalConfig);
144
+ }
145
+ }
146
+ catch (error) {
147
+ const errorMessage = error instanceof Error ? error.message : String(error);
148
+ // Special handling for rate limit errors
149
+ if (error instanceof RateLimitError || errorMessage.toLowerCase().includes("rate limit")) {
150
+ log.error(`๐Ÿšซ [TOOL] Rate limit detected`);
151
+ return {
152
+ success: false,
153
+ error: "NotebookLM rate limit reached (50 queries/day for free accounts).\n\n" +
154
+ "You can:\n" +
155
+ "1. Use the 're_auth' tool to login with a different Google account\n" +
156
+ "2. Wait until tomorrow for the quota to reset\n" +
157
+ "3. Upgrade to Google AI Pro/Ultra for 5x higher limits\n\n" +
158
+ `Original error: ${errorMessage}`,
159
+ };
160
+ }
161
+ log.error(`โŒ [TOOL] ask_question failed: ${errorMessage}`);
162
+ return {
163
+ success: false,
164
+ error: errorMessage,
165
+ };
166
+ }
167
+ }
168
+ /**
169
+ * Handle list_sessions tool
170
+ */
171
+ async handleListSessions() {
172
+ log.info(`๐Ÿ”ง [TOOL] list_sessions called`);
173
+ try {
174
+ const stats = this.sessionManager.getStats();
175
+ const sessions = this.sessionManager.getAllSessionsInfo();
176
+ const result = {
177
+ active_sessions: stats.active_sessions,
178
+ max_sessions: stats.max_sessions,
179
+ session_timeout: stats.session_timeout,
180
+ oldest_session_seconds: stats.oldest_session_seconds,
181
+ total_messages: stats.total_messages,
182
+ sessions: sessions.map((info) => ({
183
+ id: info.id,
184
+ created_at: info.created_at,
185
+ last_activity: info.last_activity,
186
+ age_seconds: info.age_seconds,
187
+ inactive_seconds: info.inactive_seconds,
188
+ message_count: info.message_count,
189
+ notebook_url: info.notebook_url,
190
+ })),
191
+ };
192
+ log.success(`โœ… [TOOL] list_sessions completed (${result.active_sessions} sessions)`);
193
+ return {
194
+ success: true,
195
+ data: result,
196
+ };
197
+ }
198
+ catch (error) {
199
+ const errorMessage = error instanceof Error ? error.message : String(error);
200
+ log.error(`โŒ [TOOL] list_sessions failed: ${errorMessage}`);
201
+ return {
202
+ success: false,
203
+ error: errorMessage,
204
+ };
205
+ }
206
+ }
207
+ /**
208
+ * Handle close_session tool
209
+ */
210
+ async handleCloseSession(args) {
211
+ const { session_id } = args;
212
+ log.info(`๐Ÿ”ง [TOOL] close_session called`);
213
+ log.info(` Session ID: ${session_id}`);
214
+ try {
215
+ const closed = await this.sessionManager.closeSession(session_id);
216
+ if (closed) {
217
+ log.success(`โœ… [TOOL] close_session completed`);
218
+ return {
219
+ success: true,
220
+ data: {
221
+ status: "success",
222
+ message: `Session ${session_id} closed successfully`,
223
+ session_id,
224
+ },
225
+ };
226
+ }
227
+ else {
228
+ log.warning(`โš ๏ธ [TOOL] Session ${session_id} not found`);
229
+ return {
230
+ success: false,
231
+ error: `Session ${session_id} not found`,
232
+ };
233
+ }
234
+ }
235
+ catch (error) {
236
+ const errorMessage = error instanceof Error ? error.message : String(error);
237
+ log.error(`โŒ [TOOL] close_session failed: ${errorMessage}`);
238
+ return {
239
+ success: false,
240
+ error: errorMessage,
241
+ };
242
+ }
243
+ }
244
+ /**
245
+ * Handle reset_session tool
246
+ */
247
+ async handleResetSession(args) {
248
+ const { session_id } = args;
249
+ log.info(`๐Ÿ”ง [TOOL] reset_session called`);
250
+ log.info(` Session ID: ${session_id}`);
251
+ try {
252
+ const session = this.sessionManager.getSession(session_id);
253
+ if (!session) {
254
+ log.warning(`โš ๏ธ [TOOL] Session ${session_id} not found`);
255
+ return {
256
+ success: false,
257
+ error: `Session ${session_id} not found`,
258
+ };
259
+ }
260
+ await session.reset();
261
+ log.success(`โœ… [TOOL] reset_session completed`);
262
+ return {
263
+ success: true,
264
+ data: {
265
+ status: "success",
266
+ message: `Session ${session_id} reset successfully`,
267
+ session_id,
268
+ },
269
+ };
270
+ }
271
+ catch (error) {
272
+ const errorMessage = error instanceof Error ? error.message : String(error);
273
+ log.error(`โŒ [TOOL] reset_session failed: ${errorMessage}`);
274
+ return {
275
+ success: false,
276
+ error: errorMessage,
277
+ };
278
+ }
279
+ }
280
+ /**
281
+ * Handle get_health tool
282
+ */
283
+ async handleGetHealth() {
284
+ log.info(`๐Ÿ”ง [TOOL] get_health called`);
285
+ try {
286
+ // Check authentication status
287
+ const statePath = await this.authManager.getValidStatePath();
288
+ const authenticated = statePath !== null;
289
+ // Get session stats
290
+ const stats = this.sessionManager.getStats();
291
+ const result = {
292
+ status: "ok",
293
+ authenticated,
294
+ notebook_url: CONFIG.notebookUrl || "not configured",
295
+ active_sessions: stats.active_sessions,
296
+ max_sessions: stats.max_sessions,
297
+ session_timeout: stats.session_timeout,
298
+ total_messages: stats.total_messages,
299
+ headless: CONFIG.headless,
300
+ auto_login_enabled: CONFIG.autoLoginEnabled,
301
+ stealth_enabled: CONFIG.stealthEnabled,
302
+ // Add troubleshooting tip if not authenticated
303
+ ...((!authenticated) && {
304
+ troubleshooting_tip: "For fresh start with clean browser session: Close all Chrome instances โ†’ " +
305
+ "cleanup_data(confirm=true, preserve_library=true) โ†’ setup_auth"
306
+ }),
307
+ };
308
+ log.success(`โœ… [TOOL] get_health completed`);
309
+ return {
310
+ success: true,
311
+ data: result,
312
+ };
313
+ }
314
+ catch (error) {
315
+ const errorMessage = error instanceof Error ? error.message : String(error);
316
+ log.error(`โŒ [TOOL] get_health failed: ${errorMessage}`);
317
+ return {
318
+ success: false,
319
+ error: errorMessage,
320
+ };
321
+ }
322
+ }
323
+ /**
324
+ * Handle setup_auth tool
325
+ *
326
+ * Opens a browser window for manual login with live progress updates.
327
+ * The operation waits synchronously for login completion (up to 10 minutes).
328
+ */
329
+ async handleSetupAuth(args, sendProgress) {
330
+ const { show_browser, browser_options } = args;
331
+ // CRITICAL: Send immediate progress to reset timeout from the very start
332
+ await sendProgress?.("Initializing authentication setup...", 0, 10);
333
+ log.info(`๐Ÿ”ง [TOOL] setup_auth called`);
334
+ if (show_browser !== undefined) {
335
+ log.info(` Show browser: ${show_browser}`);
336
+ }
337
+ const startTime = Date.now();
338
+ // Apply browser options temporarily
339
+ const originalConfig = { ...CONFIG };
340
+ const effectiveConfig = applyBrowserOptions(browser_options, show_browser);
341
+ Object.assign(CONFIG, effectiveConfig);
342
+ try {
343
+ // Progress: Starting
344
+ await sendProgress?.("Preparing authentication browser...", 1, 10);
345
+ log.info(` ๐ŸŒ Opening browser for interactive login...`);
346
+ // Progress: Opening browser
347
+ await sendProgress?.("Opening browser window...", 2, 10);
348
+ // Perform setup with progress updates (uses CONFIG internally)
349
+ const success = await this.authManager.performSetup(sendProgress);
350
+ const durationSeconds = (Date.now() - startTime) / 1000;
351
+ if (success) {
352
+ // Progress: Complete
353
+ await sendProgress?.("Authentication saved successfully!", 10, 10);
354
+ log.success(`โœ… [TOOL] setup_auth completed (${durationSeconds.toFixed(1)}s)`);
355
+ return {
356
+ success: true,
357
+ data: {
358
+ status: "authenticated",
359
+ message: "Successfully authenticated and saved browser state",
360
+ authenticated: true,
361
+ duration_seconds: durationSeconds,
362
+ },
363
+ };
364
+ }
365
+ else {
366
+ log.error(`โŒ [TOOL] setup_auth failed (${durationSeconds.toFixed(1)}s)`);
367
+ return {
368
+ success: false,
369
+ error: `Authentication failed or was cancelled (took ${durationSeconds.toFixed(1)}s). Check MCP server logs for details. Common causes: browser failed to launch (missing DISPLAY env var on Linux), Chrome profile locked by another process, or login page not reached.`,
370
+ };
371
+ }
372
+ }
373
+ catch (error) {
374
+ const errorMessage = error instanceof Error ? error.message : String(error);
375
+ const durationSeconds = (Date.now() - startTime) / 1000;
376
+ log.error(`โŒ [TOOL] setup_auth failed: ${errorMessage} (${durationSeconds.toFixed(1)}s)`);
377
+ return {
378
+ success: false,
379
+ error: errorMessage,
380
+ };
381
+ }
382
+ finally {
383
+ // Restore original CONFIG
384
+ Object.assign(CONFIG, originalConfig);
385
+ }
386
+ }
387
+ /**
388
+ * Handle re_auth tool
389
+ *
390
+ * Performs a complete re-authentication:
391
+ * 1. Closes all active browser sessions
392
+ * 2. Deletes all saved authentication data (cookies, Chrome profile)
393
+ * 3. Opens browser for fresh Google login
394
+ *
395
+ * Use for switching Google accounts or recovering from rate limits.
396
+ */
397
+ async handleReAuth(args, sendProgress) {
398
+ const { show_browser, browser_options } = args;
399
+ await sendProgress?.("Preparing re-authentication...", 0, 12);
400
+ log.info(`๐Ÿ”ง [TOOL] re_auth called`);
401
+ if (show_browser !== undefined) {
402
+ log.info(` Show browser: ${show_browser}`);
403
+ }
404
+ const startTime = Date.now();
405
+ // Apply browser options temporarily
406
+ const originalConfig = { ...CONFIG };
407
+ const effectiveConfig = applyBrowserOptions(browser_options, show_browser);
408
+ Object.assign(CONFIG, effectiveConfig);
409
+ try {
410
+ // 1. Close all active sessions
411
+ await sendProgress?.("Closing all active sessions...", 1, 12);
412
+ log.info(" ๐Ÿ›‘ Closing all sessions...");
413
+ await this.sessionManager.closeAllSessions();
414
+ log.success(" โœ… All sessions closed");
415
+ // 2. Clear all auth data
416
+ await sendProgress?.("Clearing authentication data...", 2, 12);
417
+ log.info(" ๐Ÿ—‘๏ธ Clearing all auth data...");
418
+ await this.authManager.clearAllAuthData();
419
+ log.success(" โœ… Auth data cleared");
420
+ // 3. Perform fresh setup
421
+ await sendProgress?.("Starting fresh authentication...", 3, 12);
422
+ log.info(" ๐ŸŒ Starting fresh authentication setup...");
423
+ const success = await this.authManager.performSetup(sendProgress);
424
+ const durationSeconds = (Date.now() - startTime) / 1000;
425
+ if (success) {
426
+ await sendProgress?.("Re-authentication complete!", 12, 12);
427
+ log.success(`โœ… [TOOL] re_auth completed (${durationSeconds.toFixed(1)}s)`);
428
+ return {
429
+ success: true,
430
+ data: {
431
+ status: "authenticated",
432
+ message: "Successfully re-authenticated with new account. All previous sessions have been closed.",
433
+ authenticated: true,
434
+ duration_seconds: durationSeconds,
435
+ },
436
+ };
437
+ }
438
+ else {
439
+ log.error(`โŒ [TOOL] re_auth failed (${durationSeconds.toFixed(1)}s)`);
440
+ return {
441
+ success: false,
442
+ error: "Re-authentication failed or was cancelled",
443
+ };
444
+ }
445
+ }
446
+ catch (error) {
447
+ const errorMessage = error instanceof Error ? error.message : String(error);
448
+ const durationSeconds = (Date.now() - startTime) / 1000;
449
+ log.error(`โŒ [TOOL] re_auth failed: ${errorMessage} (${durationSeconds.toFixed(1)}s)`);
450
+ return {
451
+ success: false,
452
+ error: errorMessage,
453
+ };
454
+ }
455
+ finally {
456
+ // Restore original CONFIG
457
+ Object.assign(CONFIG, originalConfig);
458
+ }
459
+ }
460
+ /**
461
+ * Handle add_notebook tool
462
+ */
463
+ async handleAddNotebook(args) {
464
+ log.info(`๐Ÿ”ง [TOOL] add_notebook called`);
465
+ log.info(` Name: ${args.name}`);
466
+ try {
467
+ const notebook = this.library.addNotebook(args);
468
+ log.success(`โœ… [TOOL] add_notebook completed: ${notebook.id}`);
469
+ return {
470
+ success: true,
471
+ data: { notebook },
472
+ };
473
+ }
474
+ catch (error) {
475
+ const errorMessage = error instanceof Error ? error.message : String(error);
476
+ log.error(`โŒ [TOOL] add_notebook failed: ${errorMessage}`);
477
+ return {
478
+ success: false,
479
+ error: errorMessage,
480
+ };
481
+ }
482
+ }
483
+ /**
484
+ * Handle list_notebooks tool
485
+ */
486
+ async handleListNotebooks() {
487
+ log.info(`๐Ÿ”ง [TOOL] list_notebooks called`);
488
+ try {
489
+ const notebooks = this.library.listNotebooks();
490
+ log.success(`โœ… [TOOL] list_notebooks completed (${notebooks.length} notebooks)`);
491
+ return {
492
+ success: true,
493
+ data: { notebooks },
494
+ };
495
+ }
496
+ catch (error) {
497
+ const errorMessage = error instanceof Error ? error.message : String(error);
498
+ log.error(`โŒ [TOOL] list_notebooks failed: ${errorMessage}`);
499
+ return {
500
+ success: false,
501
+ error: errorMessage,
502
+ };
503
+ }
504
+ }
505
+ /**
506
+ * Handle get_notebook tool
507
+ */
508
+ async handleGetNotebook(args) {
509
+ log.info(`๐Ÿ”ง [TOOL] get_notebook called`);
510
+ log.info(` ID: ${args.id}`);
511
+ try {
512
+ const notebook = this.library.getNotebook(args.id);
513
+ if (!notebook) {
514
+ log.warning(`โš ๏ธ [TOOL] Notebook not found: ${args.id}`);
515
+ return {
516
+ success: false,
517
+ error: `Notebook not found: ${args.id}`,
518
+ };
519
+ }
520
+ log.success(`โœ… [TOOL] get_notebook completed: ${notebook.name}`);
521
+ return {
522
+ success: true,
523
+ data: { notebook },
524
+ };
525
+ }
526
+ catch (error) {
527
+ const errorMessage = error instanceof Error ? error.message : String(error);
528
+ log.error(`โŒ [TOOL] get_notebook failed: ${errorMessage}`);
529
+ return {
530
+ success: false,
531
+ error: errorMessage,
532
+ };
533
+ }
534
+ }
535
+ /**
536
+ * Handle select_notebook tool
537
+ */
538
+ async handleSelectNotebook(args) {
539
+ log.info(`๐Ÿ”ง [TOOL] select_notebook called`);
540
+ log.info(` ID: ${args.id}`);
541
+ try {
542
+ const notebook = this.library.selectNotebook(args.id);
543
+ log.success(`โœ… [TOOL] select_notebook completed: ${notebook.name}`);
544
+ return {
545
+ success: true,
546
+ data: { notebook },
547
+ };
548
+ }
549
+ catch (error) {
550
+ const errorMessage = error instanceof Error ? error.message : String(error);
551
+ log.error(`โŒ [TOOL] select_notebook failed: ${errorMessage}`);
552
+ return {
553
+ success: false,
554
+ error: errorMessage,
555
+ };
556
+ }
557
+ }
558
+ /**
559
+ * Handle update_notebook tool
560
+ */
561
+ async handleUpdateNotebook(args) {
562
+ log.info(`๐Ÿ”ง [TOOL] update_notebook called`);
563
+ log.info(` ID: ${args.id}`);
564
+ try {
565
+ const notebook = this.library.updateNotebook(args);
566
+ log.success(`โœ… [TOOL] update_notebook completed: ${notebook.name}`);
567
+ return {
568
+ success: true,
569
+ data: { notebook },
570
+ };
571
+ }
572
+ catch (error) {
573
+ const errorMessage = error instanceof Error ? error.message : String(error);
574
+ log.error(`โŒ [TOOL] update_notebook failed: ${errorMessage}`);
575
+ return {
576
+ success: false,
577
+ error: errorMessage,
578
+ };
579
+ }
580
+ }
581
+ /**
582
+ * Handle remove_notebook tool
583
+ */
584
+ async handleRemoveNotebook(args) {
585
+ log.info(`๐Ÿ”ง [TOOL] remove_notebook called`);
586
+ log.info(` ID: ${args.id}`);
587
+ try {
588
+ const notebook = this.library.getNotebook(args.id);
589
+ if (!notebook) {
590
+ log.warning(`โš ๏ธ [TOOL] Notebook not found: ${args.id}`);
591
+ return {
592
+ success: false,
593
+ error: `Notebook not found: ${args.id}`,
594
+ };
595
+ }
596
+ const removed = this.library.removeNotebook(args.id);
597
+ if (removed) {
598
+ const closedSessions = await this.sessionManager.closeSessionsForNotebook(notebook.url);
599
+ log.success(`โœ… [TOOL] remove_notebook completed`);
600
+ return {
601
+ success: true,
602
+ data: { removed: true, closed_sessions: closedSessions },
603
+ };
604
+ }
605
+ else {
606
+ log.warning(`โš ๏ธ [TOOL] Notebook not found: ${args.id}`);
607
+ return {
608
+ success: false,
609
+ error: `Notebook not found: ${args.id}`,
610
+ };
611
+ }
612
+ }
613
+ catch (error) {
614
+ const errorMessage = error instanceof Error ? error.message : String(error);
615
+ log.error(`โŒ [TOOL] remove_notebook failed: ${errorMessage}`);
616
+ return {
617
+ success: false,
618
+ error: errorMessage,
619
+ };
620
+ }
621
+ }
622
+ /**
623
+ * Handle search_notebooks tool
624
+ */
625
+ async handleSearchNotebooks(args) {
626
+ log.info(`๐Ÿ”ง [TOOL] search_notebooks called`);
627
+ log.info(` Query: "${args.query}"`);
628
+ try {
629
+ const notebooks = this.library.searchNotebooks(args.query);
630
+ log.success(`โœ… [TOOL] search_notebooks completed (${notebooks.length} results)`);
631
+ return {
632
+ success: true,
633
+ data: { notebooks },
634
+ };
635
+ }
636
+ catch (error) {
637
+ const errorMessage = error instanceof Error ? error.message : String(error);
638
+ log.error(`โŒ [TOOL] search_notebooks failed: ${errorMessage}`);
639
+ return {
640
+ success: false,
641
+ error: errorMessage,
642
+ };
643
+ }
644
+ }
645
+ /**
646
+ * Handle get_library_stats tool
647
+ */
648
+ async handleGetLibraryStats() {
649
+ log.info(`๐Ÿ”ง [TOOL] get_library_stats called`);
650
+ try {
651
+ const stats = this.library.getStats();
652
+ log.success(`โœ… [TOOL] get_library_stats completed`);
653
+ return {
654
+ success: true,
655
+ data: stats,
656
+ };
657
+ }
658
+ catch (error) {
659
+ const errorMessage = error instanceof Error ? error.message : String(error);
660
+ log.error(`โŒ [TOOL] get_library_stats failed: ${errorMessage}`);
661
+ return {
662
+ success: false,
663
+ error: errorMessage,
664
+ };
665
+ }
666
+ }
667
+ /**
668
+ * Handle cleanup_data tool
669
+ *
670
+ * ULTRATHINK Deep Cleanup - scans entire system for ALL NotebookLM MCP files
671
+ */
672
+ async handleCleanupData(args) {
673
+ const { confirm, preserve_library = false } = args;
674
+ log.info(`๐Ÿ”ง [TOOL] cleanup_data called`);
675
+ log.info(` Confirm: ${confirm}`);
676
+ log.info(` Preserve Library: ${preserve_library}`);
677
+ const cleanupManager = new CleanupManager();
678
+ try {
679
+ // Always run in deep mode
680
+ const mode = "deep";
681
+ if (!confirm) {
682
+ // Preview mode - show what would be deleted
683
+ log.info(` ๐Ÿ“‹ Generating cleanup preview (mode: ${mode})...`);
684
+ const preview = await cleanupManager.getCleanupPaths(mode, preserve_library);
685
+ const platformInfo = cleanupManager.getPlatformInfo();
686
+ log.info(` Found ${preview.totalPaths.length} items (${cleanupManager.formatBytes(preview.totalSizeBytes)})`);
687
+ log.info(` Platform: ${platformInfo.platform}`);
688
+ return {
689
+ success: true,
690
+ data: {
691
+ status: "preview",
692
+ mode,
693
+ preview: {
694
+ categories: preview.categories,
695
+ totalPaths: preview.totalPaths.length,
696
+ totalSizeBytes: preview.totalSizeBytes,
697
+ },
698
+ },
699
+ };
700
+ }
701
+ else {
702
+ // Cleanup mode - actually delete files
703
+ log.info(` ๐Ÿ—‘๏ธ Performing cleanup (mode: ${mode})...`);
704
+ const result = await cleanupManager.performCleanup(mode, preserve_library);
705
+ if (result.success) {
706
+ log.success(`โœ… [TOOL] cleanup_data completed - deleted ${result.deletedPaths.length} items`);
707
+ }
708
+ else {
709
+ log.warning(`โš ๏ธ [TOOL] cleanup_data completed with ${result.failedPaths.length} errors`);
710
+ }
711
+ return {
712
+ success: result.success,
713
+ data: {
714
+ status: result.success ? "completed" : "partial",
715
+ mode,
716
+ result: {
717
+ deletedPaths: result.deletedPaths,
718
+ failedPaths: result.failedPaths,
719
+ totalSizeBytes: result.totalSizeBytes,
720
+ categorySummary: result.categorySummary,
721
+ },
722
+ },
723
+ };
724
+ }
725
+ }
726
+ catch (error) {
727
+ const errorMessage = error instanceof Error ? error.message : String(error);
728
+ log.error(`โŒ [TOOL] cleanup_data failed: ${errorMessage}`);
729
+ return {
730
+ success: false,
731
+ error: errorMessage,
732
+ };
733
+ }
734
+ }
735
+ // ==================== Content Generation Tools ====================
736
+ async handleGenerateFAQ(args, sendProgress) {
737
+ return this.contentHandlers.handleGenerateFAQ(args, sendProgress);
738
+ }
739
+ async handleGenerateBriefing(args, sendProgress) {
740
+ return this.contentHandlers.handleGenerateBriefing(args, sendProgress);
741
+ }
742
+ async handleGenerateTimeline(args, sendProgress) {
743
+ return this.contentHandlers.handleGenerateTimeline(args, sendProgress);
744
+ }
745
+ async handleGenerateOutline(args, sendProgress) {
746
+ return this.contentHandlers.handleGenerateOutline(args, sendProgress);
747
+ }
748
+ async handleGenerateStudyGuide(args, sendProgress) {
749
+ return this.contentHandlers.handleGenerateStudyGuide(args, sendProgress);
750
+ }
751
+ async handleGenerateFlashcards(args, sendProgress) {
752
+ return this.contentHandlers.handleGenerateFlashcards(args, sendProgress);
753
+ }
754
+ async handleGenerateQuiz(args, sendProgress) {
755
+ return this.contentHandlers.handleGenerateQuiz(args, sendProgress);
756
+ }
757
+ async handleGenerateMindMap(args, sendProgress) {
758
+ return this.contentHandlers.handleGenerateMindMap(args, sendProgress);
759
+ }
760
+ async handleSuggestQuestions(args, sendProgress) {
761
+ return this.contentHandlers.handleSuggestQuestions(args, sendProgress);
762
+ }
763
+ // ==================== Audio Studio Tools ====================
764
+ async handleGetAudioStatus(args, sendProgress) {
765
+ return this.studioHandlers.handleGetAudioStatus(args, sendProgress);
766
+ }
767
+ async handleCreateAudio(args, sendProgress) {
768
+ return this.studioHandlers.handleCreateAudio(args, sendProgress);
769
+ }
770
+ async handleUpdateAudio(args, sendProgress) {
771
+ return this.studioHandlers.handleUpdateAudio(args, sendProgress);
772
+ }
773
+ async handleDeleteAudio(args, sendProgress) {
774
+ return this.studioHandlers.handleDeleteAudio(args, sendProgress);
775
+ }
776
+ async handleDownloadAudio(args, sendProgress) {
777
+ return this.studioHandlers.handleDownloadAudio(args, sendProgress);
778
+ }
779
+ // ==================== Source Management Tools ====================
780
+ async handleListSources(args, sendProgress) {
781
+ return this.sourceHandlers.handleListSources(args, sendProgress);
782
+ }
783
+ async handleAddURLSource(args, sendProgress) {
784
+ return this.sourceHandlers.handleAddURLSource(args, sendProgress);
785
+ }
786
+ async handleAddTextSource(args, sendProgress) {
787
+ return this.sourceHandlers.handleAddTextSource(args, sendProgress);
788
+ }
789
+ async handleAddYouTubeSource(args, sendProgress) {
790
+ return this.sourceHandlers.handleAddYouTubeSource(args, sendProgress);
791
+ }
792
+ async handleAddDriveSource(args, sendProgress) {
793
+ return this.sourceHandlers.handleAddDriveSource(args, sendProgress);
794
+ }
795
+ async handleDeleteSource(args, sendProgress) {
796
+ return this.sourceHandlers.handleDeleteSource(args, sendProgress);
797
+ }
798
+ async handleSummarizeSource(args, sendProgress) {
799
+ return this.sourceHandlers.handleSummarizeSource(args, sendProgress);
800
+ }
801
+ // ==================== Research Tools ====================
802
+ async handleDiscoverSources(args, sendProgress) {
803
+ return this.researchHandlers.handleDiscoverSources(args, sendProgress);
804
+ }
805
+ async handleImportSource(args, sendProgress) {
806
+ return this.researchHandlers.handleImportSource(args, sendProgress);
807
+ }
808
+ async handleResearchTopic(args, sendProgress) {
809
+ return this.researchHandlers.handleResearchTopic(args, sendProgress);
810
+ }
811
+ // ==================== Notebook CRUD Tools ====================
812
+ async handleCreateNotebookRemote(args, sendProgress) {
813
+ return this.notebookCRUDHandlers.handleCreateNotebookRemote(args, sendProgress);
814
+ }
815
+ async handleRenameNotebookRemote(args, sendProgress) {
816
+ return this.notebookCRUDHandlers.handleRenameNotebookRemote(args, sendProgress);
817
+ }
818
+ async handleDeleteNotebookRemote(args, sendProgress) {
819
+ return this.notebookCRUDHandlers.handleDeleteNotebookRemote(args, sendProgress);
820
+ }
821
+ async handleAddFileSource(args, sendProgress) {
822
+ return this.notebookCRUDHandlers.handleAddFileSource(args, sendProgress);
823
+ }
824
+ /**
825
+ * Cleanup all resources (called on server shutdown)
826
+ */
827
+ async cleanup() {
828
+ log.info(`๐Ÿงน Cleaning up tool handlers...`);
829
+ await this.sessionManager.closeAllSessions();
830
+ log.success(`โœ… Tool handlers cleanup complete`);
831
+ }
832
+ }
833
+ //# sourceMappingURL=handlers.js.map