Files
egutierrez dbf5b45acd chore: auto-commit (7 archivos)
- .mcp.json
- bash/functions/pipelines/full_git_push.sh
- python/pyproject.toml
- python/uv.lock
- bash/functions/infra/jupyter_mcp_serve.md
- bash/functions/infra/jupyter_mcp_serve.sh
- dev/issues/0166-app-to-app-dependencies-tracking.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 01:29:45 +02:00

3.6 KiB

name, kind, lang, domain, version, purity, error_type, signature, description, tags, uses_functions, uses_types, params, output
name kind lang domain version purity error_type signature description tags uses_functions uses_types params output
jupyter_mcp_serve function bash infra 1.0.0 impure error_go_core jupyter_mcp_serve.sh [--dry-run] Arranca (o reusa) un Jupyter Lab colaborativo en un puerto propio y lanza el Jupyter MCP server enganchado por stdio. Entrypoint robusto para la entrada 'jupyter' de .mcp.json: garantiza que el MCP SIEMPRE tiene servidor al que conectarse, sin depender de que haya un jupyter en 8888.
notebook
jupyter
mcp
infra
launcher-glue
name desc
--dry-run Opcional. Arranca/verifica jupyter pero NO hace exec del MCP; loguea el comando elegido. Para tests.
Proceso jupyter-mcp-server enganchado por stdio a un Jupyter Lab colaborativo local (127.0.0.1, puerto JUPYTER_MCP_PORT, default 8899). Logs en ~/.fn_jupyter_mcp/. stdout reservado al protocolo MCP.

Que hace

El MCP de Jupyter (datalayer jupyter-mcp-server) no arranca jupyter, solo se conecta a uno existente. Si la URL configurada no tiene jupyter detras, el MCP nunca conecta. En esta maquina localhost:8888 es el proxy HTTP del contenedor VPN gluetun, no un jupyter — por eso el MCP fallaba siempre.

Este wrapper resuelve la cadena entera:

  1. Localiza el venv (python/.venv) y los binarios jupyter + jupyter-mcp-server.
  2. Si ya hay un jupyter gestionado vivo en 127.0.0.1:$PORT (/api/status = 200) lo reusa.
  3. Si no, arranca jupyter lab colaborativo detached (RTC via jupyter-collaboration), en JUPYTER_MCP_ROOT (default = raiz del repo, asi cualquier notebook del arbol es lanzable).
  4. Detecta el dialecto de CLI del MCP (--document-url nuevo / --jupyter-url viejo / env vars) y hace exec del MCP por --transport stdio.

Self-adapting: funciona aunque cambie la version de jupyter-mcp-server.

Ejemplo

# Como lo usa Claude Code (entrada en .mcp.json):
#   "jupyter": { "command": "bash", "args": ["bash/functions/infra/jupyter_mcp_serve.sh"] }

# Test manual (arranca jupyter en 8899, no lanza el MCP):
bash bash/functions/infra/jupyter_mcp_serve.sh --dry-run
curl -s http://127.0.0.1:8899/api/status        # {"started":..., "version":...}

# Cambiar puerto / raiz de notebooks:
JUPYTER_MCP_PORT=8900 JUPYTER_MCP_ROOT=/home/enmanuel/fn_registry/analysis \
  bash bash/functions/infra/jupyter_mcp_serve.sh --dry-run

Cuando usarla

Cuando quieras que el MCP de Jupyter de Claude Code siempre tenga servidor: es el command de la entrada jupyter en .mcp.json. No la invoques a mano salvo para depurar (--dry-run) o para levantar el jupyter colaborativo sin el MCP.

Gotchas

  • stdout reservado: el MCP habla por stdout (protocolo stdio). El wrapper jamas escribe a stdout — todo log va a stderr y ~/.fn_jupyter_mcp/wrapper.log. No metas echo a stdout aqui o rompes el handshake del MCP.
  • Puerto 8888 ocupado por gluetun en esta maquina. Por eso el default es 8899. Si 8899 tambien se ocupa, exporta JUPYTER_MCP_PORT.
  • Token vacio: solo escucha en 127.0.0.1 con disable_check_xsrf + allow_origin '*'. Aceptable en local; NO exponer el puerto a la red.
  • venv requerido: necesita python/.venv con jupyterlab, jupyter-collaboration y jupyter-mcp-server. Reconstruir: cd python && uv sync --extra jupyter.
  • El jupyter arrancado queda detached (nohup): persiste entre invocaciones del MCP. Para pararlo: python/.venv/bin/jupyter server stop 8899 o pkill -f 'jupyter-lab.*8899'.

Capability growth log

v1.0.0 (2026-06-01) — version inicial. Wrapper auto-start: reusa/levanta jupyter colaborativo en puerto propio (8899) y autodetecta el dialecto de CLI del MCP.