notebooklm-connector 0.2.0__tar.gz
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.
- notebooklm_connector-0.2.0/.gitignore +16 -0
- notebooklm_connector-0.2.0/.mcpbignore +8 -0
- notebooklm_connector-0.2.0/.python-version +1 -0
- notebooklm_connector-0.2.0/LICENSE +21 -0
- notebooklm_connector-0.2.0/PKG-INFO +74 -0
- notebooklm_connector-0.2.0/README.md +58 -0
- notebooklm_connector-0.2.0/assets/hero.png +0 -0
- notebooklm_connector-0.2.0/assets/hero.svg +102 -0
- notebooklm_connector-0.2.0/install.sh +36 -0
- notebooklm_connector-0.2.0/main.py +6 -0
- notebooklm_connector-0.2.0/manifest.json +43 -0
- notebooklm_connector-0.2.0/pyproject.toml +33 -0
- notebooklm_connector-0.2.0/src/notebooklm_connector/__init__.py +3 -0
- notebooklm_connector-0.2.0/src/notebooklm_connector/client.py +97 -0
- notebooklm_connector-0.2.0/src/notebooklm_connector/server.py +819 -0
- notebooklm_connector-0.2.0/uv.lock +601 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Asim Hafeez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: notebooklm-connector
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Lean MCP server connecting Google NotebookLM to Claude — grounded Q&A, sources, and Studio generation
|
|
5
|
+
Project-URL: Homepage, https://github.com/asimhafeezz/notebooklm-connector
|
|
6
|
+
Project-URL: Repository, https://github.com/asimhafeezz/notebooklm-connector
|
|
7
|
+
Project-URL: Issues, https://github.com/asimhafeezz/notebooklm-connector/issues
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Python: <3.13,>=3.12
|
|
11
|
+
Requires-Dist: mcp>=1.28.1
|
|
12
|
+
Requires-Dist: notebooklm-py[cookies]>=0.7.3
|
|
13
|
+
Provides-Extra: interactive-login
|
|
14
|
+
Requires-Dist: notebooklm-py[browser]>=0.7.3; extra == 'interactive-login'
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# NotebookLM Connector
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
Talk to your **Google NotebookLM** notebooks from inside **Claude**. Ask questions answered only from your own sources (with citations), add sources, and generate Audio Overviews, reports, quizzes, and more — all from a normal chat.
|
|
22
|
+
|
|
23
|
+
## ⬇️ Install (Claude Desktop)
|
|
24
|
+
|
|
25
|
+
### [**Download NotebookLM-Connector.mcpb**](https://github.com/asimhafeezz/notebooklm-connector/releases/latest)
|
|
26
|
+
|
|
27
|
+
1. **Download** the file above.
|
|
28
|
+
2. **Double-click** it → Claude Desktop opens → click **Install**.
|
|
29
|
+
3. In a chat, type **“Connect my NotebookLM”** → pick your Google account when asked.
|
|
30
|
+
4. Type **“List my notebooks.”** That’s it.
|
|
31
|
+
|
|
32
|
+
> **Needs Python 3.12** on your computer first.
|
|
33
|
+
> Mac: `brew install python@3.12` · Windows: [python.org](https://www.python.org/downloads/). Nothing else to set up.
|
|
34
|
+
>
|
|
35
|
+
> No password is ever typed — the connector uses the Google account you’re already signed into in your browser. On Mac, click **Allow** on the one-time Keychain popup.
|
|
36
|
+
|
|
37
|
+
## What you can ask Claude to do
|
|
38
|
+
|
|
39
|
+
- *“Ask my Thesis notebook: what counterarguments do the sources discuss?”*
|
|
40
|
+
- *“Create a notebook called ‘Competitor research’ and add these three URLs as sources.”*
|
|
41
|
+
- *“Make an audio overview of my Onboarding notebook about deployment, then save it to my Desktop.”*
|
|
42
|
+
- *“Give me a quiz from my Biology notebook.”*
|
|
43
|
+
|
|
44
|
+
Under the hood that’s **13 tools**: connect/login, list & create notebooks, add sources (URLs, YouTube, text, files), ask questions with citations, and generate + download Studio content (audio, video, reports, quizzes, flashcards, mind maps, slide decks, infographics, data tables).
|
|
45
|
+
|
|
46
|
+
## Good to know
|
|
47
|
+
|
|
48
|
+
- **Sessions last ~2–4 weeks.** When it stops working, just say “Connect my NotebookLM” again.
|
|
49
|
+
- **Free NotebookLM accounts** allow about 50 questions per day.
|
|
50
|
+
- **It’s your own account** — use it as you normally would.
|
|
51
|
+
- **Unofficial** — this uses NotebookLM’s internal API (Google has no public one). It’s reliable but can break if Google changes things; updating fixes it.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Other apps
|
|
56
|
+
|
|
57
|
+
**Claude Code:** run `./install.sh` in this folder — it installs everything and registers the server.
|
|
58
|
+
|
|
59
|
+
**Cursor, Codex, Antigravity, and other MCP clients:** add this server with the command
|
|
60
|
+
`uv --directory /path/to/notebooklm-connector run notebooklm-connector`.
|
|
61
|
+
*(A simpler `uvx notebooklm-connector` one-liner is coming once it’s published to PyPI.)*
|
|
62
|
+
|
|
63
|
+
## For developers
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
uv sync # install
|
|
67
|
+
uv run notebooklm-connector # run the server
|
|
68
|
+
npx @modelcontextprotocol/inspector uv run notebooklm-connector # test tools interactively
|
|
69
|
+
npx @anthropic-ai/mcpb pack . dist/NotebookLM-Connector.mcpb # rebuild the installer
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**How it works:** Claude ↔ this MCP server ↔ [notebooklm-py](https://github.com/teng-lin/notebooklm-py) ↔ NotebookLM’s internal API. Auth is your browser’s existing Google session, read locally; nothing is sent anywhere except to NotebookLM. Multiple Google accounts: `uv run notebooklm login --profile work`, then set `NOTEBOOKLM_PROFILE=work` in the server’s env.
|
|
73
|
+
|
|
74
|
+
MIT licensed.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# NotebookLM Connector
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Talk to your **Google NotebookLM** notebooks from inside **Claude**. Ask questions answered only from your own sources (with citations), add sources, and generate Audio Overviews, reports, quizzes, and more — all from a normal chat.
|
|
6
|
+
|
|
7
|
+
## ⬇️ Install (Claude Desktop)
|
|
8
|
+
|
|
9
|
+
### [**Download NotebookLM-Connector.mcpb**](https://github.com/asimhafeezz/notebooklm-connector/releases/latest)
|
|
10
|
+
|
|
11
|
+
1. **Download** the file above.
|
|
12
|
+
2. **Double-click** it → Claude Desktop opens → click **Install**.
|
|
13
|
+
3. In a chat, type **“Connect my NotebookLM”** → pick your Google account when asked.
|
|
14
|
+
4. Type **“List my notebooks.”** That’s it.
|
|
15
|
+
|
|
16
|
+
> **Needs Python 3.12** on your computer first.
|
|
17
|
+
> Mac: `brew install python@3.12` · Windows: [python.org](https://www.python.org/downloads/). Nothing else to set up.
|
|
18
|
+
>
|
|
19
|
+
> No password is ever typed — the connector uses the Google account you’re already signed into in your browser. On Mac, click **Allow** on the one-time Keychain popup.
|
|
20
|
+
|
|
21
|
+
## What you can ask Claude to do
|
|
22
|
+
|
|
23
|
+
- *“Ask my Thesis notebook: what counterarguments do the sources discuss?”*
|
|
24
|
+
- *“Create a notebook called ‘Competitor research’ and add these three URLs as sources.”*
|
|
25
|
+
- *“Make an audio overview of my Onboarding notebook about deployment, then save it to my Desktop.”*
|
|
26
|
+
- *“Give me a quiz from my Biology notebook.”*
|
|
27
|
+
|
|
28
|
+
Under the hood that’s **13 tools**: connect/login, list & create notebooks, add sources (URLs, YouTube, text, files), ask questions with citations, and generate + download Studio content (audio, video, reports, quizzes, flashcards, mind maps, slide decks, infographics, data tables).
|
|
29
|
+
|
|
30
|
+
## Good to know
|
|
31
|
+
|
|
32
|
+
- **Sessions last ~2–4 weeks.** When it stops working, just say “Connect my NotebookLM” again.
|
|
33
|
+
- **Free NotebookLM accounts** allow about 50 questions per day.
|
|
34
|
+
- **It’s your own account** — use it as you normally would.
|
|
35
|
+
- **Unofficial** — this uses NotebookLM’s internal API (Google has no public one). It’s reliable but can break if Google changes things; updating fixes it.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Other apps
|
|
40
|
+
|
|
41
|
+
**Claude Code:** run `./install.sh` in this folder — it installs everything and registers the server.
|
|
42
|
+
|
|
43
|
+
**Cursor, Codex, Antigravity, and other MCP clients:** add this server with the command
|
|
44
|
+
`uv --directory /path/to/notebooklm-connector run notebooklm-connector`.
|
|
45
|
+
*(A simpler `uvx notebooklm-connector` one-liner is coming once it’s published to PyPI.)*
|
|
46
|
+
|
|
47
|
+
## For developers
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
uv sync # install
|
|
51
|
+
uv run notebooklm-connector # run the server
|
|
52
|
+
npx @modelcontextprotocol/inspector uv run notebooklm-connector # test tools interactively
|
|
53
|
+
npx @anthropic-ai/mcpb pack . dist/NotebookLM-Connector.mcpb # rebuild the installer
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**How it works:** Claude ↔ this MCP server ↔ [notebooklm-py](https://github.com/teng-lin/notebooklm-py) ↔ NotebookLM’s internal API. Auth is your browser’s existing Google session, read locally; nothing is sent anywhere except to NotebookLM. Multiple Google accounts: `uv run notebooklm login --profile work`, then set `NOTEBOOKLM_PROFILE=work` in the server’s env.
|
|
57
|
+
|
|
58
|
+
MIT licensed.
|
|
Binary file
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<svg width="1280" height="620" viewBox="0 0 1280 620" fill="none" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1280" y2="620" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop offset="0" stop-color="#f7f8ff"/>
|
|
5
|
+
<stop offset="1" stop-color="#eaeefb"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<filter id="shadow" x="-20%" y="-20%" width="140%" height="150%">
|
|
8
|
+
<feDropShadow dx="0" dy="6" stdDeviation="12" flood-color="#3b3f66" flood-opacity="0.10"/>
|
|
9
|
+
</filter>
|
|
10
|
+
</defs>
|
|
11
|
+
|
|
12
|
+
<rect width="1280" height="620" rx="0" fill="url(#bg)"/>
|
|
13
|
+
|
|
14
|
+
<!-- Header -->
|
|
15
|
+
<text x="64" y="82" font-size="46" font-weight="700" fill="#1a1c2e">NotebookLM Connector</text>
|
|
16
|
+
<text x="66" y="122" font-size="22" font-weight="400" fill="#5b6079">Your Google NotebookLM notebooks — right inside Claude.</text>
|
|
17
|
+
|
|
18
|
+
<!-- badge -->
|
|
19
|
+
<rect x="960" y="48" width="256" height="40" rx="20" fill="#eef0fe" stroke="#d9ddfa"/>
|
|
20
|
+
<circle cx="986" cy="68" r="5" fill="#16a34a"/>
|
|
21
|
+
<text x="1002" y="74" font-size="16" font-weight="600" fill="#4f46e5">Claude Desktop extension</text>
|
|
22
|
+
|
|
23
|
+
<!-- ============ STEP CARDS ============ -->
|
|
24
|
+
<!-- card 1 -->
|
|
25
|
+
<g filter="url(#shadow)">
|
|
26
|
+
<rect x="64" y="176" width="352" height="182" rx="20" fill="#ffffff" stroke="#e7e9f3"/>
|
|
27
|
+
</g>
|
|
28
|
+
<circle cx="104" cy="216" r="20" fill="#4f46e5"/>
|
|
29
|
+
<text x="104" y="223" font-size="20" font-weight="700" fill="#ffffff" text-anchor="middle">1</text>
|
|
30
|
+
<!-- download icon -->
|
|
31
|
+
<g stroke="#4f46e5" stroke-width="3.4" stroke-linecap="round" stroke-linejoin="round" fill="none">
|
|
32
|
+
<path d="M300 210 v34"/>
|
|
33
|
+
<path d="M288 232 l12 12 12 -12"/>
|
|
34
|
+
<path d="M282 256 h36"/>
|
|
35
|
+
</g>
|
|
36
|
+
<text x="96" y="296" font-size="24" font-weight="700" fill="#1a1c2e">Download</text>
|
|
37
|
+
<text x="96" y="328" font-size="18" fill="#6b7089">Grab the one file and</text>
|
|
38
|
+
<text x="96" y="352" font-size="18" fill="#6b7089">double-click to install.</text>
|
|
39
|
+
|
|
40
|
+
<!-- arrow 1->2 -->
|
|
41
|
+
<path d="M430 267 h32" stroke="#b9bede" stroke-width="3.2" stroke-linecap="round"/>
|
|
42
|
+
<path d="M456 259 l10 8 -10 8" stroke="#b9bede" stroke-width="3.2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
|
43
|
+
|
|
44
|
+
<!-- card 2 -->
|
|
45
|
+
<g filter="url(#shadow)">
|
|
46
|
+
<rect x="464" y="176" width="352" height="182" rx="20" fill="#ffffff" stroke="#e7e9f3"/>
|
|
47
|
+
</g>
|
|
48
|
+
<circle cx="504" cy="216" r="20" fill="#4f46e5"/>
|
|
49
|
+
<text x="504" y="223" font-size="20" font-weight="700" fill="#ffffff" text-anchor="middle">2</text>
|
|
50
|
+
<!-- account/check icon -->
|
|
51
|
+
<g fill="none">
|
|
52
|
+
<circle cx="700" cy="224" r="15" stroke="#4f46e5" stroke-width="3.4"/>
|
|
53
|
+
<circle cx="700" cy="219" r="5.5" fill="#4f46e5"/>
|
|
54
|
+
<path d="M690 236 a10 8 0 0 1 20 0" stroke="#4f46e5" stroke-width="3.4" stroke-linecap="round"/>
|
|
55
|
+
<circle cx="716" cy="238" r="9" fill="#16a34a"/>
|
|
56
|
+
<path d="M711 238 l3.5 3.5 6 -7" stroke="#ffffff" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>
|
|
57
|
+
</g>
|
|
58
|
+
<text x="496" y="296" font-size="24" font-weight="700" fill="#1a1c2e">Connect</text>
|
|
59
|
+
<text x="496" y="328" font-size="18" fill="#6b7089">Say “Connect my</text>
|
|
60
|
+
<text x="496" y="352" font-size="18" fill="#6b7089">NotebookLM,” pick account.</text>
|
|
61
|
+
|
|
62
|
+
<!-- arrow 2->3 -->
|
|
63
|
+
<path d="M830 267 h32" stroke="#b9bede" stroke-width="3.2" stroke-linecap="round"/>
|
|
64
|
+
<path d="M856 259 l10 8 -10 8" stroke="#b9bede" stroke-width="3.2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
|
65
|
+
|
|
66
|
+
<!-- card 3 -->
|
|
67
|
+
<g filter="url(#shadow)">
|
|
68
|
+
<rect x="864" y="176" width="352" height="182" rx="20" fill="#ffffff" stroke="#e7e9f3"/>
|
|
69
|
+
</g>
|
|
70
|
+
<circle cx="904" cy="216" r="20" fill="#d97757"/>
|
|
71
|
+
<text x="904" y="223" font-size="20" font-weight="700" fill="#ffffff" text-anchor="middle">3</text>
|
|
72
|
+
<!-- chat icon -->
|
|
73
|
+
<g fill="none" stroke="#d97757" stroke-width="3.4" stroke-linejoin="round">
|
|
74
|
+
<path d="M1082 206 h30 a10 10 0 0 1 10 10 v20 a10 10 0 0 1 -10 10 h-20 l-14 12 v-12 a10 10 0 0 1 4 -40 z"/>
|
|
75
|
+
</g>
|
|
76
|
+
<text x="896" y="296" font-size="24" font-weight="700" fill="#1a1c2e">Ask</text>
|
|
77
|
+
<text x="896" y="328" font-size="18" fill="#6b7089">Chat with your notebooks —</text>
|
|
78
|
+
<text x="896" y="352" font-size="18" fill="#6b7089">answers cite your sources.</text>
|
|
79
|
+
|
|
80
|
+
<!-- ============ MINI CHAT DEMO ============ -->
|
|
81
|
+
<g filter="url(#shadow)">
|
|
82
|
+
<rect x="64" y="398" width="1152" height="182" rx="20" fill="#ffffff" stroke="#e7e9f3"/>
|
|
83
|
+
</g>
|
|
84
|
+
|
|
85
|
+
<!-- user bubble -->
|
|
86
|
+
<rect x="856" y="422" width="336" height="46" rx="14" fill="#4f46e5"/>
|
|
87
|
+
<text x="1170" y="451" font-size="18" font-weight="500" fill="#ffffff" text-anchor="end">List my notebooks</text>
|
|
88
|
+
|
|
89
|
+
<!-- assistant bubble -->
|
|
90
|
+
<rect x="88" y="482" width="720" height="76" rx="14" fill="#f3f4f9" stroke="#e7e9f3"/>
|
|
91
|
+
<text x="112" y="512" font-size="18" font-weight="700" fill="#1a1c2e">You have 6 notebooks</text>
|
|
92
|
+
<text x="112" y="540" font-size="16" fill="#6b7089">Duffel Flight Offers · Hotel Search API · Air-Quality Analytics …</text>
|
|
93
|
+
|
|
94
|
+
<!-- citation chip -->
|
|
95
|
+
<rect x="828" y="500" width="158" height="40" rx="20" fill="#eef8f0" stroke="#c9ead2"/>
|
|
96
|
+
<circle cx="854" cy="520" r="9" fill="#16a34a"/>
|
|
97
|
+
<path d="M849.5 520 l3 3 5.5 -6" stroke="#ffffff" stroke-width="2.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
98
|
+
<text x="872" y="526" font-size="15" font-weight="600" fill="#16a34a">cited sources</text>
|
|
99
|
+
|
|
100
|
+
<!-- no-password note -->
|
|
101
|
+
<text x="112" y="452" font-size="16" fill="#8a8fa8">In any Claude chat — no password, ever.</text>
|
|
102
|
+
</svg>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# NotebookLM Connector — installer for Claude Code (CLI) users.
|
|
3
|
+
# Usage: ./install.sh (run from the project directory)
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
|
|
8
|
+
echo "==> NotebookLM Connector installer"
|
|
9
|
+
|
|
10
|
+
if ! command -v uv >/dev/null 2>&1; then
|
|
11
|
+
echo "==> Installing uv (Python package manager)..."
|
|
12
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
13
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
echo "==> Installing dependencies..."
|
|
17
|
+
(cd "$DIR" && uv sync)
|
|
18
|
+
|
|
19
|
+
if command -v claude >/dev/null 2>&1; then
|
|
20
|
+
echo "==> Registering MCP server with Claude Code (user scope)..."
|
|
21
|
+
claude mcp add --scope user notebooklm -- uv --directory "$DIR" run notebooklm-connector || true
|
|
22
|
+
else
|
|
23
|
+
echo "!! Claude Code CLI not found — register manually later with:"
|
|
24
|
+
echo " claude mcp add --scope user notebooklm -- uv --directory \"$DIR\" run notebooklm-connector"
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
cat <<'DONE'
|
|
28
|
+
|
|
29
|
+
==> Installed.
|
|
30
|
+
|
|
31
|
+
Next step — authenticate (pick one):
|
|
32
|
+
a) Just ask Claude: "log in to NotebookLM" (reads your browser's Google session)
|
|
33
|
+
b) Or run: uv run notebooklm login (opens a sign-in window)
|
|
34
|
+
|
|
35
|
+
Then ask Claude: "check my NotebookLM auth status".
|
|
36
|
+
DONE
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": "0.4",
|
|
3
|
+
"name": "notebooklm-connector",
|
|
4
|
+
"display_name": "NotebookLM Connector",
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"description": "Connect Google NotebookLM to Claude: grounded Q&A with citations, source management, and Studio content generation.",
|
|
7
|
+
"long_description": "Gives Claude direct access to your Google NotebookLM account. Ask questions answered exclusively from your notebook sources (with citations), create notebooks, add sources (URLs, YouTube, text, files), and generate Studio content — Audio Overviews, reports, quizzes, flashcards, mind maps, slide decks, infographics — then download the results. Log in by telling Claude 'log in to NotebookLM': it reads your existing Google session from your browser, no password required. Uses NotebookLM's internal API via the notebooklm-py library; sessions last ~2-4 weeks.",
|
|
8
|
+
"author": {
|
|
9
|
+
"name": "Asim Hafeez",
|
|
10
|
+
"url": "https://github.com/asimhafeezz/notebooklm-connector"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["notebooklm", "google", "research", "rag", "citations", "notebooks"],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"server": {
|
|
15
|
+
"type": "uv",
|
|
16
|
+
"entry_point": "main.py",
|
|
17
|
+
"mcp_config": {
|
|
18
|
+
"command": "uv",
|
|
19
|
+
"args": ["run", "--directory", "${__dirname}", "main.py"]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"compatibility": {
|
|
23
|
+
"platforms": ["darwin", "win32", "linux"],
|
|
24
|
+
"runtimes": {
|
|
25
|
+
"python": ">=3.12,<3.13"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"tools": [
|
|
29
|
+
{ "name": "notebooklm_auth_status", "description": "Check whether a valid NotebookLM session exists" },
|
|
30
|
+
{ "name": "notebooklm_list_google_accounts", "description": "List Google accounts signed in to the browser, so the user can pick which to connect" },
|
|
31
|
+
{ "name": "notebooklm_login", "description": "Log in as a specific Google account using the browser's existing session (or an interactive sign-in window)" },
|
|
32
|
+
{ "name": "notebooklm_list_notebooks", "description": "List all notebooks in the account" },
|
|
33
|
+
{ "name": "notebooklm_create_notebook", "description": "Create a new notebook" },
|
|
34
|
+
{ "name": "notebooklm_get_notebook", "description": "Notebook overview: AI summary plus sources with IDs and status" },
|
|
35
|
+
{ "name": "notebooklm_add_source", "description": "Add a URL, pasted text, or local file as a source" },
|
|
36
|
+
{ "name": "notebooklm_ask", "description": "Ask a question answered only from the notebook's sources, with citations" },
|
|
37
|
+
{ "name": "notebooklm_generate", "description": "Generate Studio content: audio overview, video, report, quiz, flashcards, mind map, infographic, slide deck, data table" },
|
|
38
|
+
{ "name": "notebooklm_generation_status", "description": "Poll a generation task" },
|
|
39
|
+
{ "name": "notebooklm_list_artifacts", "description": "List generated Studio artifacts" },
|
|
40
|
+
{ "name": "notebooklm_download_artifact", "description": "Download a finished artifact to a local file" },
|
|
41
|
+
{ "name": "notebooklm_delete", "description": "Delete a notebook, source, or artifact" }
|
|
42
|
+
]
|
|
43
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "notebooklm-connector"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "Lean MCP server connecting Google NotebookLM to Claude — grounded Q&A, sources, and Studio generation"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
# Pinned to 3.12: rookiepy ships prebuilt wheels only up to cp312 — on 3.13+
|
|
7
|
+
# uv falls back to a Rust source build that is slow and often fails.
|
|
8
|
+
requires-python = ">=3.12,<3.13"
|
|
9
|
+
license = "MIT"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"mcp>=1.28.1",
|
|
12
|
+
"notebooklm-py[cookies]>=0.7.3",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.urls]
|
|
16
|
+
Homepage = "https://github.com/asimhafeezz/notebooklm-connector"
|
|
17
|
+
Repository = "https://github.com/asimhafeezz/notebooklm-connector"
|
|
18
|
+
Issues = "https://github.com/asimhafeezz/notebooklm-connector/issues"
|
|
19
|
+
|
|
20
|
+
[project.optional-dependencies]
|
|
21
|
+
# Only needed for the interactive sign-in window fallback (notebooklm_login
|
|
22
|
+
# method='interactive'); the default browser-cookie login works without it.
|
|
23
|
+
interactive-login = ["notebooklm-py[browser]>=0.7.3"]
|
|
24
|
+
|
|
25
|
+
[project.scripts]
|
|
26
|
+
notebooklm-connector = "notebooklm_connector.server:main"
|
|
27
|
+
|
|
28
|
+
[build-system]
|
|
29
|
+
requires = ["hatchling"]
|
|
30
|
+
build-backend = "hatchling.build"
|
|
31
|
+
|
|
32
|
+
[tool.hatch.build.targets.wheel]
|
|
33
|
+
packages = ["src/notebooklm_connector"]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Shared NotebookLM client lifecycle and error handling.
|
|
2
|
+
|
|
3
|
+
A single NotebookLMClient is created lazily on first tool call and reused for
|
|
4
|
+
the lifetime of the MCP server process. Auth tokens come from the storage
|
|
5
|
+
written by `notebooklm login` (the notebooklm-py CLI bundled with this project).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
import os
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
from notebooklm import (
|
|
15
|
+
AuthError,
|
|
16
|
+
ConfigurationError,
|
|
17
|
+
NotebookLMClient,
|
|
18
|
+
NotFoundError,
|
|
19
|
+
RateLimitError,
|
|
20
|
+
RPCError,
|
|
21
|
+
SourceProcessingError,
|
|
22
|
+
WaitTimeoutError,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
_client: NotebookLMClient | None = None
|
|
26
|
+
_client_cm: Any = None
|
|
27
|
+
_lock = asyncio.Lock()
|
|
28
|
+
|
|
29
|
+
LOGIN_HINT = (
|
|
30
|
+
"No valid NotebookLM session. To connect: call notebooklm_list_google_accounts to see "
|
|
31
|
+
"which Google accounts are signed in to the user's browser, ask the user which one to "
|
|
32
|
+
"use, then call notebooklm_login with that email as `account`. No password is needed — "
|
|
33
|
+
"the session is read from the browser. Sessions last roughly 2-4 weeks."
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def profile() -> str | None:
|
|
38
|
+
"""Named auth profile, for people with multiple Google accounts."""
|
|
39
|
+
return os.environ.get("NOTEBOOKLM_PROFILE") or None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
async def get_client() -> NotebookLMClient:
|
|
43
|
+
"""Return the shared client, creating it from stored auth on first use."""
|
|
44
|
+
global _client, _client_cm
|
|
45
|
+
async with _lock:
|
|
46
|
+
if _client is None:
|
|
47
|
+
cm = NotebookLMClient.from_storage(profile=profile())
|
|
48
|
+
_client = await cm.__aenter__()
|
|
49
|
+
_client_cm = cm
|
|
50
|
+
return _client
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async def reset_client() -> None:
|
|
54
|
+
"""Drop the shared client so the next call re-reads stored auth."""
|
|
55
|
+
global _client, _client_cm
|
|
56
|
+
async with _lock:
|
|
57
|
+
if _client_cm is not None:
|
|
58
|
+
try:
|
|
59
|
+
await _client_cm.__aexit__(None, None, None)
|
|
60
|
+
except Exception:
|
|
61
|
+
pass
|
|
62
|
+
_client = None
|
|
63
|
+
_client_cm = None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def format_error(e: Exception) -> str:
|
|
67
|
+
"""Map notebooklm-py exceptions to actionable messages for the agent."""
|
|
68
|
+
if isinstance(e, (AuthError, ConfigurationError)) or isinstance(e, FileNotFoundError):
|
|
69
|
+
return f"Error: authentication problem ({type(e).__name__}). {LOGIN_HINT}"
|
|
70
|
+
if isinstance(e, RateLimitError):
|
|
71
|
+
return (
|
|
72
|
+
"Error: NotebookLM rate limit hit. Free accounts allow roughly 50 "
|
|
73
|
+
"chat queries per day. Wait before retrying, or continue tomorrow."
|
|
74
|
+
)
|
|
75
|
+
if isinstance(e, NotFoundError):
|
|
76
|
+
return (
|
|
77
|
+
f"Error: not found ({e}). Check the notebook/source/artifact ID — "
|
|
78
|
+
"use notebooklm_list_notebooks or notebooklm_get_notebook to look up valid IDs."
|
|
79
|
+
)
|
|
80
|
+
if isinstance(e, SourceProcessingError):
|
|
81
|
+
return (
|
|
82
|
+
f"Error: NotebookLM failed to process the source ({e}). The document may be "
|
|
83
|
+
"unsupported, paywalled, or too large. Try a different URL or upload the file directly."
|
|
84
|
+
)
|
|
85
|
+
if isinstance(e, WaitTimeoutError):
|
|
86
|
+
return (
|
|
87
|
+
f"Error: timed out waiting ({e}). The operation is likely still running inside "
|
|
88
|
+
"NotebookLM — check again shortly (sources: notebooklm_get_notebook; "
|
|
89
|
+
"generations: notebooklm_generation_status)."
|
|
90
|
+
)
|
|
91
|
+
if isinstance(e, RPCError):
|
|
92
|
+
return (
|
|
93
|
+
f"Error: NotebookLM internal API call failed ({type(e).__name__}: {e}). "
|
|
94
|
+
"This connector relies on undocumented Google APIs; if this persists, "
|
|
95
|
+
"the API may have changed — try `uv sync --upgrade` to update notebooklm-py."
|
|
96
|
+
)
|
|
97
|
+
return f"Error: {type(e).__name__}: {e}"
|