- .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>
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. |
|
|
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:
- Localiza el venv (
python/.venv) y los binariosjupyter+jupyter-mcp-server. - Si ya hay un jupyter gestionado vivo en
127.0.0.1:$PORT(/api/status= 200) lo reusa. - Si no, arranca
jupyter labcolaborativo detached (RTC viajupyter-collaboration), enJUPYTER_MCP_ROOT(default = raiz del repo, asi cualquier notebook del arbol es lanzable). - Detecta el dialecto de CLI del MCP (
--document-urlnuevo /--jupyter-urlviejo / env vars) y haceexecdel 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 metasechoa 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.1condisable_check_xsrf+allow_origin '*'. Aceptable en local; NO exponer el puerto a la red. - venv requerido: necesita
python/.venvconjupyterlab,jupyter-collaborationyjupyter-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 8899opkill -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.