09e9f3545f
Test / Code Quality (push) Has been cancelled
Test / Test (macos-latest, Python 3.10) (push) Has been cancelled
Test / Test (macos-latest, Python 3.11) (push) Has been cancelled
Test / Test (macos-latest, Python 3.12) (push) Has been cancelled
Test / Test (macos-latest, Python 3.13) (push) Has been cancelled
Test / Test (macos-latest, Python 3.14) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.10) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.11) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.12) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.13) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.14) (push) Has been cancelled
Test / Test (windows-latest, Python 3.10) (push) Has been cancelled
Test / Test (windows-latest, Python 3.11) (push) Has been cancelled
Test / Test (windows-latest, Python 3.12) (push) Has been cancelled
Test / Test (windows-latest, Python 3.13) (push) Has been cancelled
Test / Test (windows-latest, Python 3.14) (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
dependency-audit / pip-audit (push) Has been cancelled
51 lines
2.4 KiB
Docker
51 lines
2.4 KiB
Docker
# Remote notebooklm-mcp server — single-tenant, bearer-gated, streamable-HTTP.
|
|
#
|
|
# The image is stateless: the profile (incl. master_token.json) is mounted at
|
|
# runtime, never baked in. Run behind a Cloudflare Tunnel (or any TLS reverse
|
|
# proxy) — see deploy/README.md.
|
|
#
|
|
# Two install modes (the compose build context is the repo root):
|
|
# * DEV / from-source (DEFAULT): installs THIS checkout, so `docker compose up`
|
|
# deploys exactly the code in this repo. Leave NOTEBOOKLM_SPEC empty.
|
|
# * PRODUCTION / from PyPI: build with a release spec, e.g.
|
|
# docker compose build --build-arg NOTEBOOKLM_SPEC="notebooklm-py[mcp,headless]==<version>"
|
|
# (or set it under build.args in docker-compose.yml).
|
|
FROM python:3.12-slim
|
|
|
|
ARG NOTEBOOKLM_SPEC=""
|
|
|
|
# Copy the repo source (build context = repo root; see .dockerignore for excludes).
|
|
COPY . /src
|
|
|
|
# Empty NOTEBOOKLM_SPEC → install the copied source (dev). Non-empty → install
|
|
# that spec from PyPI (production) and ignore the copied source.
|
|
RUN if [ -n "$NOTEBOOKLM_SPEC" ]; then \
|
|
pip install --no-cache-dir "$NOTEBOOKLM_SPEC"; \
|
|
else \
|
|
pip install --no-cache-dir "/src[mcp,headless]"; \
|
|
fi
|
|
|
|
# Run as a non-root user; the mounted profile dir must be writable by this uid
|
|
# (keepalive/recovery rotates cookies into storage_state.json).
|
|
RUN useradd --create-home --uid 10001 app
|
|
USER app
|
|
|
|
ENV NOTEBOOKLM_MCP_HOST=0.0.0.0 \
|
|
NOTEBOOKLM_MCP_PORT=9420 \
|
|
NOTEBOOKLM_PROFILE=server
|
|
|
|
EXPOSE 9420
|
|
|
|
# Liveness: stdlib-only TCP connect to the listener over loopback. No curl/wget/nc
|
|
# needed, and it never touches the auth-gated /mcp route. The python process reads
|
|
# NOTEBOOKLM_MCP_PORT from its own env at runtime (a program sees its environment
|
|
# even in exec-form — only shell `$VAR` substitution doesn't), so overriding the
|
|
# port keeps the healthcheck in sync. Host is always loopback: the server binds
|
|
# 0.0.0.0, which you connect to via 127.0.0.1 from inside the container.
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
|
CMD ["python", "-c", "import os,socket,sys; p=int(os.environ.get('NOTEBOOKLM_MCP_PORT','9420')); s=socket.socket(); s.settimeout(2); sys.exit(0 if s.connect_ex(('127.0.0.1',p))==0 else 1)"]
|
|
|
|
# --host 0.0.0.0 is non-loopback, so NOTEBOOKLM_MCP_ALLOW_EXTERNAL_BIND=1 AND a
|
|
# NOTEBOOKLM_MCP_TOKEN are MANDATORY (the entrypoint refuses to start otherwise).
|
|
CMD ["notebooklm-mcp", "--transport", "http"]
|