-
Notifications
You must be signed in to change notification settings - Fork 523
feat: Implement a FastMCP server to expose NotebookLM functionalities for listing, creating, adding sources, and chatting. #156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,36 @@ | ||||||
| import asyncio | ||||||
| from fastmcp import FastMCP | ||||||
| from notebooklm import NotebookLMClient | ||||||
|
|
||||||
| mcp = FastMCP("NotebookLM") | ||||||
|
|
||||||
| @mcp.tool() | ||||||
| async def list_notebooks(): | ||||||
| """List all NotebookLM notebooks available in the account.""" | ||||||
| async with await NotebookLMClient.from_storage() as client: | ||||||
| notebooks = await client.notebooks.list() | ||||||
| return [{"id": nb.id, "title": nb.title} for nb in notebooks] | ||||||
|
|
||||||
| @mcp.tool() | ||||||
| async def create_notebook(title: str): | ||||||
| """Create a new NotebookLM notebook.""" | ||||||
| async with await NotebookLMClient.from_storage() as client: | ||||||
| nb = await client.notebooks.create(title) | ||||||
| return {"id": nb.id, "title": nb.title} | ||||||
|
|
||||||
| @mcp.tool() | ||||||
| async def add_source_url(notebook_id: str, url: str): | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||||||
| """Add a web URL source to the NotebookLM notebook.""" | ||||||
| async with await NotebookLMClient.from_storage() as client: | ||||||
| await client.sources.add_url(notebook_id, url, wait=True) | ||||||
| return {"status": "success", "url": url} | ||||||
|
|
||||||
| @mcp.tool() | ||||||
| async def chat_ask(notebook_id: str, message: str): | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||||||
| """Ask a question to the NotebookLM notebook and get an answer based on its sources.""" | ||||||
| async with await NotebookLMClient.from_storage() as client: | ||||||
| result = await client.chat.ask(notebook_id, message) | ||||||
| return {"answer": result.text if hasattr(result, 'text') else result.answer} | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The expression
Suggested change
|
||||||
|
|
||||||
| if __name__ == "__main__": | ||||||
| mcp.run() | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pattern
async with await NotebookLMClient.from_storage() as client:is repeated in every tool function. This is inefficient for a server application because it creates a newNotebookLMClientinstance for every API call. This involves I/O for reading storage state and setting up a new HTTP client each time. ANotebookLMClientis designed to be long-lived and should be reused across requests.Consider creating a single client instance when the application starts and closing it on shutdown. This will significantly improve performance and resource management. You can likely achieve this using your server framework's startup and shutdown lifecycle events.