notebooklm-mcp-cli

repository·main·Indexed 26 days ago

https://github.com/jacob-bd/notebooklm-mcp-cli

A unified CLI and Model Context Protocol (MCP) server for Google NotebookLM (Gemini Notebook). It provides programmatic access to automate notebook creation, source management, audio generation, and artifact downloading. The tool allows users to connect NotebookLM capabilities to AI agents such as Claude, Cursor, Gemini, and GitHub Copilot via the `nlm` command and `notebooklm-mcp` server.

Tokens
71K
Snippets
155
Records
423
Agent score
88%

What's inside notebooklm-mcp-cli

  1. Understand the User Identity Challenge in MCP Servers

    main

    When using an MCP server with an interface like Open WebUI, the MCP server itself does not inherently know which end-user is making a request. While the frontend (Open WebUI) maintains user identity, the MCP server receives requests without built-in user context.

    To achieve multi-user support, the MCP server must implement a mapping layer to associate requests with specific users to ensure conversation isolation.

  2. Install AI Assistant Skills

    main

    Install specialized skill/reference documentation for AI tools that do not use MCP using nlm skill install.

    Supported Tools: claude-code, cursor, agents, gemini-cli, codex, opencode, antigravity, cline, openclaw, alef-agent, other.

    Installation Targets:

    • Generic/Codex/Gemini-CLI: Installs to ~/.agents/skills/nlm-skill/.
    • Alef Agent: Installs to ~/.alef-agent/workspace/skills/nlm-skill/.

    Commands:

    • nlm skill install claude-code
    • nlm skill install agents (Alias for claude-code, codex, or gemini-cli targets).
    • nlm skill install alef-agent
    nlm skill list                           # Show installation status
    nlm skill install claude-code            # Install for Claude Code
    nlm skill install cursor                 # Install for Cursor AI
    nlm skill install <tool> --level project # Install at project level
    nlm skill uninstall <tool>               # Remove skill
    nlm skill show                           # View skill content
    
    # Verb-first alternatives
    nlm install skill claude-code            
    nlm list skills
    
    # Generic/Alias targets
    nlm skill install agents      # Generic name
    nlm skill install codex       # Alias for OpenAI Codex CLI
    nlm skill install gemini-cli   # Alias for Google Gemini CLI
    
    # Alef Agent
    nlm skill install alef-agent
  3. Create Flashcards with Studio Prompts

    main

    Use specific prompt patterns to generate different types of flashcards from your uploaded sources in Gemini Notebook.

    • Mixed exam deck (medium): Mixes definitions, cause-effect, comparisons, and application scenarios.
    • Scenario decisions (hard): Focuses on decision-making in real situations rather than pure definitions.
    • Confused terminology (medium): Targets specific terms you find confusing (e.g., [TERM A vs B vs C]) to explain differences.
    • Beginner vocabulary (easy): Focuses on definitions and one example per term for a specific topic.
    • Certification cram (hard): Prioritizes exam rules, thresholds, and exception cases.
  4. Authenticate Gemini Notebook in WSL2 using the --wsl flag

    main

    When running in Windows Subsystem for Linux (WSL2), use the --wsl flag to perform authentication. This method launches the Windows version of Chrome to avoid terminal display corruption and uses a network bridge to extract cookies.

    Prerequisites:

    1. Google Chrome must be installed on the Windows side.
    2. Close all Chrome windows on Windows before starting to ensure a fresh instance for remote debugging.

    Steps:

    1. Set up the Windows port proxy (see Set up the WSL2 port proxy).
    2. Run the login command in your WSL terminal:
      nlm login --wsl
    3. Follow the prompts in the Chrome window to log in to Gemini Notebook.
    4. Once complete, verify the setup with:
      nlm login --check
      nlm notebook list
    nlm login --wsl
  5. Authenticate the nlm CLI and MCP server

    main

    Authentication is shared between the CLI and the MCP server. Use nlm login to set up credentials or recover from expired sessions.

    CLI Authentication

    • nlm login: Launches a browser to extract cookies (primary method).
    • nlm login --check: Validates the current session.
    • nlm login --profile <name>: Uses a named profile for multiple Google accounts.
    • nlm login switch <profile>: Switches the default profile (this also updates the account used by the MCP server).
    • nlm login profile list: Lists all profiles and their associated email addresses.

    MCP Authentication Recovery

    If you encounter authentication errors while using MCP tools:

    1. Run nlm login in your terminal.
    2. Refresh the tokens in MCP using mcp__notebooklm-mcp__refresh_auth().

    If mcp__notebooklm-mcp__refresh_auth() returns expired, you must run nlm login.

    nlm login
    nlm login switch <profile>
  6. Construct effective Studio prompts using the Universal Prompt Framework

    main

    To ensure high-quality outputs from Gemini Notebook Studio, all prompts (sent via focus_prompt, custom_prompt, or description) should follow a structured framework.

    The Grounding Anchor

    Include this in EVERY prompt to prevent hallucinations: Use only uploaded sources. Do not invent statistics, quotes, names, or examples not in the sources.

    Five-Block Anatomy

    For complex (Guided) prompts, use these five blocks:

    1. Audience: Who consumes this (e.g., "Non-technical executives").
    2. Goal: The desired outcome (e.g., "Prep for midterm on thermodynamics").
    3. Scope: What to include or exclude (e.g., "Chapter 4 only; skip historical background").
    4. Structure: Sections, beats, or layout (e.g., "Problem → 3 findings → recommendation").
    5. Constraints: Tone, length, or language (e.g., "Conversational; ~10 min; English only").

    Prompt Templates

    Fast-track minimal (1–3 sentences): [Audience]. Focus on [2-3 themes from sources]. [Structure or tone hint]. Use only uploaded sources.

    Guided full skeleton: Audience: [who]. Goal: [outcome]. Focus: [themes]. Exclude: [skip]. Structure: [sections]. Tone: [register]. Use only uploaded sources.

  7. Critical Safety Rules for Gemini Notebook Automation

    main

    When automating Gemini Notebook via CLI or MCP, adhere to these rules:

    1. Mandatory Confirmation for Deletions: Always ask the user for explicit confirmation before executing any delete command. Deletions are irreversible.
    2. Mandatory Approval for Generation: Always obtain approval before triggering studio_create or deletion operations. Even if the tool has a confirm=True parameter, the agent must maintain an approval gate.
    3. Avoid REPLs: Do NOT use nlm chat start. It opens an interactive REPL that cannot be controlled by AI tools. Use nlm notebook query for one-shot Q&A instead.
    4. Capture IDs: Commands that create or start processes return IDs. You must capture these IDs to use them in subsequent operations (e.g., passing --notebook-id <id>).
    5. Use Aliases for Convenience: Use nlm alias set <name> <uuid> to simplify long UUIDs, and check nlm alias list before creating new ones to avoid conflicts.
  8. Integrate with Open WebUI using Function Wrappers

    main

    To enable multi-user isolation in Open WebUI, create a custom Function that injects the Open WebUI __user__ context into MCP calls. This ensures that each user's conversation history is isolated even when using a shared Gemini Notebook account.

    Implementation Steps:

    1. Navigate to Workspace → Functions → Create in Open WebUI.
    2. Paste the Python function implementation (see code example).
    3. Save and enable the function.

    Note: The function relies on Open WebUI's ability to automatically inject a __user__ dictionary containing id, email, name, and role into the function call.

    import httpx
    
    class Tools:
        def __init__(self):
            # Adjust to your MCP server URL
            self.mcp_url = "http://localhost:8000"
        
        async def query_notebook(
            self, 
            notebook_id: str, 
            question: str, 
            __user__: dict = {}
        ) -> str:
            """Ask a question about a NotebookLM notebook."""
            user_id = __user__.get("id", "anonymous")
            
            async with httpx.AsyncClient(timeout=120) as client:
                response = await client.post(
                    f"{self.mcp_url}/mcp",
                    json={
                        "tool": "notebook_query",
                        "arguments": {
                            "notebook_id": notebook_id,
                            "query": question,
                            "user_id": user_id,
                        }
                    }
                )
                result = response.json()
                if result.get("status") == "success":
                    return result.get("answer", "No answer generated")
                else:
                    return f"Error: {result.get('error', 'Unknown error')}"
    
        # Additional methods like list_notebooks, new_conversation, and check_rate_limit 
        # follow the same pattern of extracting user_id from __user__.
  9. Automate CLI with --quiet and --json

    main

    When scripting, use specific flags to avoid complex string parsing:

    Getting IDs for piping

    Use --quiet to output exactly one ID per line. This allows you to capture IDs directly into shell variables.

    Parsing structured data

    Use --json to get full object details. Always parse the resulting JSON using a proper JSON library (like json.loads in Python) rather than attempting to split strings.

    Python Example:

    import json
    import subprocess
    
    result = subprocess.run(
        ["nlm", "notebook", "list", "--json"],
        capture_output=True, text=True
    )
    notebooks = json.loads(result.stdout)
    notebook_id = notebooks[0]["id"]   # UUID like "abc12345-..."
    # Grab the first notebook ID in a shell script
    notebook_id=$(nlm notebook list --quiet | head -1)
    lm notebook query "$notebook_id" "Summarize key points"
  10. Set up the WSL2 port proxy (one-time)

    main

    Because Chrome (v136+) binds the DevTools Protocol to 127.0.0.1 only, you must configure a Windows port proxy to forward traffic from the WSL virtual network to Chrome's localhost listener.

    Run the following command in an elevated PowerShell (Run as Administrator):

    netsh interface portproxy add v4tov4 listenport=9222 listenaddress=0.0.0.0 connectport=9223 connectaddress=127.0.0.1

    This forwards traffic from port 9222 (accessible from WSL) to port 9223 (where Chrome listens). You can verify the proxy configuration with:

    netsh interface portproxy show v4tov4
  11. Upgrade notebooklm-mcp-cli

    main

    To upgrade the package, use your preferred package manager:

    • uv: uv tool upgrade notebooklm-mcp-cli
    • pip: pip install --upgrade notebooklm-mcp-cli
    • pipx: pipx upgrade notebooklm-mcp-cli

    Note: After upgrading, you must restart your AI tool (Claude Code, Cursor, etc.) to reconnect to the updated MCP server.

    # Using uv
    uv tool upgrade notebooklm-mcp-cli
    
    # Using pip
    pip install --upgrade notebooklm-mcp-cli
    
    # Using pipx
    pipx upgrade notebooklm-mcp-cli