# Jupyter Notebook Tools Cinco funciones Python para operar notebooks Jupyter programaticamente via API REST y WebSocket colaborativo (CRDT/Y.js). Reemplazan al MCP jupyter y funcionan desde cualquier directorio. ## Flujo tipico ``` discover → read → write/exec ``` 1. **Descubrir** que Jupyter esta corriendo y en que puerto 2. **Leer** celdas del notebook (estado en memoria, no disco) 3. **Escribir** celdas nuevas o **ejecutar** codigo ```bash PYTHON="python/.venv/bin/python3" # 1. Descubrir instancias activas $PYTHON python/functions/notebook/jupyter_discover.py --json # 2. Leer notebook $PYTHON python/functions/notebook/jupyter_read.py notebooks/01.ipynb --json # 3. Crear notebook nuevo (si no existe) $PYTHON python/functions/notebook/jupyter_write.py create notebooks/02.ipynb # 4. Escribir celdas en batch $PYTHON python/functions/notebook/jupyter_write.py batch notebooks/02.ipynb --from cells.json # 5. Ejecutar celda $PYTHON python/functions/notebook/jupyter_exec.py cell notebooks/02.ipynb 0 ``` ## Funciones ### jupyter_discover Descubre instancias de Jupyter Lab activas. Escanea `.jupyter-port` en `analysis/` y puertos 8888-8892. Detecta el `root_dir` real parseando `/proc/{pid}/cmdline`. | Subcomando | Descripcion | |---|---| | *(sin subcomando)* | Lista instancias con puerto, analysis, root_dir, kernels, sesiones | ```bash $PYTHON jupyter_discover.py --json $PYTHON jupyter_discover.py --port 8888 --port 8889 ``` Retorna por instancia: `url`, `port`, `analysis`, `root_dir`, `collaborative`, `kernels`, `sessions`. ### jupyter_read Lee celdas de un notebook via protocolo CRDT (estado en memoria, incluye cambios no guardados). | Subcomando | Descripcion | |---|---| | *(sin subcomando)* | Lee todas las celdas (formato legible) | | `--cell N` | Lee solo la celda N | | `--info` | Solo metadata (total celdas, conteo por tipo) | | `--json` | Salida JSON | ```bash $PYTHON jupyter_read.py notebooks/01.ipynb --json $PYTHON jupyter_read.py notebooks/01.ipynb --cell 3 $PYTHON jupyter_read.py notebooks/01.ipynb --info ``` ### jupyter_write Operaciones de escritura sobre celdas via WebSocket colaborativo. NO ejecuta celdas. | Subcomando | Descripcion | |---|---| | `create` | Crea un notebook .ipynb nuevo (API REST PUT) | | `append-code` | Anade celda de codigo al final | | `append-markdown` | Anade celda markdown al final | | `insert` | Inserta celda en posicion especifica | | `edit` | Sobrescribe contenido de celda existente | | `delete` | Elimina una celda | | `batch` | Escribe multiples celdas en una sola conexion WebSocket | ```bash # Crear notebook $PYTHON jupyter_write.py create notebooks/02.ipynb $PYTHON jupyter_write.py create notebooks/02.ipynb --kernel python3 --force # Celdas individuales $PYTHON jupyter_write.py append-code notebooks/02.ipynb "import pandas as pd" $PYTHON jupyter_write.py append-markdown notebooks/02.ipynb "## Titulo" $PYTHON jupyter_write.py insert notebooks/02.ipynb 0 "x = 42" --type code $PYTHON jupyter_write.py edit notebooks/02.ipynb 0 "# Titulo actualizado" $PYTHON jupyter_write.py delete notebooks/02.ipynb 3 # Batch (una sola conexion para N celdas) $PYTHON jupyter_write.py batch notebooks/02.ipynb --from cells.json cat cells.json | $PYTHON jupyter_write.py batch notebooks/02.ipynb --from - ``` Formato `cells.json`: ```json [ {"type": "markdown", "source": "# Titulo"}, {"type": "code", "source": "import pandas as pd"}, {"type": "code", "source": "df = pd.read_csv('data.csv')"} ] ``` ### jupyter_exec Ejecuta codigo en kernels de Jupyter via WebSocket. | Subcomando | Descripcion | |---|---| | `append` | Anade celda al notebook y la ejecuta | | `cell` | Ejecuta celda existente por indice | | `kernel` | Ejecuta en el kernel sin tocar notebook | ```bash $PYTHON jupyter_exec.py append notebooks/01.ipynb "df.describe()" $PYTHON jupyter_exec.py cell notebooks/01.ipynb 3 $PYTHON jupyter_exec.py kernel "print(df.shape)" ``` Normaliza automaticamente celdas sin `outputs` o `execution_count` (comun en notebooks creados programaticamente). ### jupyter_kernel CRUD de kernels Jupyter via API REST. | Subcomando | Descripcion | |---|---| | `list` | Lista kernels activos | | `start` | Inicia kernel nuevo | | `restart` | Reinicia kernel | | `interrupt` | Interrumpe ejecucion | | `shutdown` | Apaga y elimina kernel | | `sessions` | Lista sesiones (mapeo notebook-kernel) | ```bash $PYTHON jupyter_kernel.py list $PYTHON jupyter_kernel.py start --name python3 $PYTHON jupyter_kernel.py restart $PYTHON jupyter_kernel.py shutdown $PYTHON jupyter_kernel.py sessions ``` ## Troubleshooting ### WebSocket 4404 — notebook no existe El servidor no puede abrir un documento CRDT para un archivo que no existe en disco. **Solucion:** Crear el notebook primero con `jupyter_write.py create`. ```bash $PYTHON jupyter_write.py create notebooks/nuevo.ipynb $PYTHON jupyter_write.py append-code notebooks/nuevo.ipynb "print('hola')" ``` ### KeyError 'outputs' — celda sin estructura completa Notebooks creados manualmente (no via Jupyter UI) pueden tener celdas de codigo sin los campos `outputs` y `execution_count` que el protocolo CRDT requiere. **Solucion:** `jupyter_exec.py` normaliza automaticamente estas celdas antes de ejecutar. Si el problema persiste, recrear la celda con `jupyter_write.py edit`. ### "Kernel does not exist" — sesion stale El kernel referenciado ya no existe (fue apagado o el servidor se reinicio). **Solucion:** ```bash # Ver kernels activos $PYTHON jupyter_kernel.py list # Ver sesiones (mapeo notebook-kernel) $PYTHON jupyter_kernel.py sessions # Reiniciar kernel si necesario $PYTHON jupyter_kernel.py restart ``` ### "Document not yet synced" — timing de colaboracion El cliente WebSocket no pudo sincronizar el documento CRDT a tiempo. **Solucion:** Reintentar. Si persiste, verificar que el servidor tiene `jupyter-collaboration` activo: ```bash $PYTHON jupyter_discover.py --json | python3 -c "import sys,json; [print(i['collaborative']) for i in json.load(sys.stdin)]" ``` ### Discover muestra analysis incorrecto Versiones anteriores podian confundir instancias. La deteccion actual parsea `--ServerApp.root_dir` del cmdline del proceso via `/proc/{pid}/cmdline`. **Solucion:** Actualizar a la version actual de `jupyter_discover.py`. ## Parametros comunes Todos los subcomandos aceptan: | Flag | Default | Descripcion | |---|---|---| | `--server` | `http://localhost:8888` | URL del servidor Jupyter | | `--token` | `""` (vacio) | Token de autenticacion | Los paths de notebooks son siempre **relativos a la raiz del servidor Jupyter** (normalmente `analysis/{tema}/`). ## Dependencias | Paquete | Usado por | Para que | |---|---|---| | `jupyter_nbmodel_client` | write, exec, read | WebSocket colaborativo (CRDT/Y.js) | | `jupyter_kernel_client` | exec | Ejecucion de codigo en kernels | | stdlib (`urllib`, `json`) | discover, kernel, write (create) | API REST | ## Diferencias con MCP jupyter | Aspecto | MCP jupyter | Estas funciones | |---|---|---| | Requiere registro | Si (.mcp.json) | No | | Funciona desde cualquier dir | No (solo desde el dir del MCP) | Si | | Protocolo | MCP sobre stdio | HTTP REST + WebSocket directo | | Crear notebooks | No | Si (`write create`) | | Batch de celdas | No | Si (`write batch`) | | Multi-instancia | No | Si (discover detecta todas) | ## Limitaciones - Requiere Jupyter Lab >= 4 con `jupyter-collaboration` para las funciones que usan WebSocket (write, exec, read) - Las funciones REST (discover, kernel) funcionan con cualquier Jupyter Lab 3.x/4.x y Notebook 6.x/7.x - La deteccion de root_dir via `/proc` solo funciona en Linux - No soportan autenticacion por cookie, solo por token - `jupyter_write batch` requiere JSON como entrada (no YAML)