c65f1698ae
El .mcp.json generado ahora apunta al wrapper jupyter_mcp_serve.sh con env overrides (JUPYTER_MCP_VENV/ROOT/PORT/TOKEN) en vez del console-script jupyter-mcp-server directo. Antes: el .mcp.json solo CONECTABA a un Jupyter ya existente y, si se abria Claude desde la raiz del repo, el MCP usaba el venv canonico python/.venv (sin las deps del analisis). Ahora el wrapper arranca (o reusa) un Jupyter con el venv del propio analisis, asi que abrir Claude desde el directorio del analisis basta y cada analisis ejecuta con sus dependencias sin contaminar python/.venv. Bump v1.2.0. Declara dependencia jupyter_mcp_serve_bash_infra. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
105 lines
4.2 KiB
Bash
105 lines
4.2 KiB
Bash
# write_mcp_jupyter_config
|
|
# -------------------------
|
|
# Genera o actualiza .mcp.json con la configuracion de jupyter-mcp-server para un
|
|
# analisis/proyecto. La entrada `jupyter` usa el wrapper `jupyter_mcp_serve.sh`
|
|
# (no el console-script directo), de modo que el MCP SIEMPRE tiene servidor: el
|
|
# wrapper arranca (o reusa) un Jupyter Lab en el puerto indicado usando el venv
|
|
# del propio analisis y lo engancha al MCP por stdio.
|
|
#
|
|
# Por que el wrapper y no el console-script directo: el console-script
|
|
# `jupyter-mcp-server --jupyter-url http://localhost:PORT` solo se CONECTA, no
|
|
# arranca Jupyter. Si el server no esta levantado, el MCP responde `initialize`
|
|
# pero no hay kernel y toda operacion sobre notebooks falla. El wrapper levanta el
|
|
# server con el venv correcto (JUPYTER_MCP_VENV) antes de exec del MCP, asi que
|
|
# abrir Claude desde el analisis basta — no hace falta lanzar run-jupyter-lab.sh
|
|
# aparte. Si ya hay un Jupyter en ese puerto (p.ej. run-jupyter-lab.sh), lo reusa.
|
|
#
|
|
# Env overrides que se inyectan al wrapper (ver jupyter_mcp_serve.sh):
|
|
# JUPYTER_MCP_VENV venv del analisis (su .venv, con jupyter + jupyter-mcp-server)
|
|
# JUPYTER_MCP_ROOT root de notebooks = directorio del analisis
|
|
# JUPYTER_MCP_PORT puerto del Jupyter gestionado
|
|
# JUPYTER_MCP_TOKEN token (vacio: solo escucha en 127.0.0.1)
|
|
#
|
|
# GOTCHA (2026-05-28): `python -m jupyter_mcp_server.server` NO arranca nada —
|
|
# server.py no tiene bloque __main__. El entrypoint real es el console-script
|
|
# `jupyter-mcp-server` (que el wrapper localiza dentro del venv del analisis).
|
|
#
|
|
# USO (sourced):
|
|
# source write_mcp_jupyter_config.sh
|
|
# write_mcp_jupyter_config /path/to/analysis 8890
|
|
|
|
write_mcp_jupyter_config() {
|
|
local project_dir="${1:-.}"
|
|
local port="${2:-8888}"
|
|
local mcp_file="${project_dir}/.mcp.json"
|
|
local abs_project
|
|
abs_project="$(cd "$project_dir" && pwd)"
|
|
|
|
local python_bin="${abs_project}/.venv/bin/python"
|
|
local mcp_bin="${abs_project}/.venv/bin/jupyter-mcp-server"
|
|
if [ ! -f "$python_bin" ]; then
|
|
echo "write_mcp_jupyter_config: python no encontrado en ${python_bin}" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Verificar que el console-script esta instalado en el venv del analisis
|
|
if [ ! -x "$mcp_bin" ]; then
|
|
echo "write_mcp_jupyter_config: jupyter-mcp-server no instalado en el venv (${mcp_bin}). Instala con: uv pip install jupyter-mcp-server" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Localizar el wrapper jupyter_mcp_serve.sh subiendo desde el directorio del
|
|
# analisis hasta la raiz del repo. Fallback a FN_REGISTRY_ROOT.
|
|
local wrapper="" d="$abs_project"
|
|
local i
|
|
for i in 1 2 3 4 5 6 7 8; do
|
|
if [ -f "$d/bash/functions/infra/jupyter_mcp_serve.sh" ]; then
|
|
wrapper="$d/bash/functions/infra/jupyter_mcp_serve.sh"
|
|
break
|
|
fi
|
|
d="$(dirname "$d")"
|
|
[ "$d" = "/" ] && break
|
|
done
|
|
if [ -z "$wrapper" ] && [ -n "${FN_REGISTRY_ROOT:-}" ] && [ -f "${FN_REGISTRY_ROOT}/bash/functions/infra/jupyter_mcp_serve.sh" ]; then
|
|
wrapper="${FN_REGISTRY_ROOT}/bash/functions/infra/jupyter_mcp_serve.sh"
|
|
fi
|
|
if [ -z "$wrapper" ]; then
|
|
echo "write_mcp_jupyter_config: no encuentro bash/functions/infra/jupyter_mcp_serve.sh subiendo desde ${abs_project} ni en FN_REGISTRY_ROOT" >&2
|
|
return 1
|
|
fi
|
|
|
|
local new_config
|
|
new_config=$(cat << EOF
|
|
{
|
|
"mcpServers": {
|
|
"jupyter": {
|
|
"command": "bash",
|
|
"args": [
|
|
"${wrapper}"
|
|
],
|
|
"env": {
|
|
"JUPYTER_MCP_VENV": "${abs_project}/.venv",
|
|
"JUPYTER_MCP_ROOT": "${abs_project}",
|
|
"JUPYTER_MCP_PORT": "${port}",
|
|
"JUPYTER_MCP_TOKEN": ""
|
|
}
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
)
|
|
|
|
if [ -f "$mcp_file" ] && command -v jq &>/dev/null; then
|
|
# Merge conservando otros servidores MCP. Usa `+` (shallow) en el mapa de
|
|
# servidores para REEMPLAZAR la entrada `jupyter` entera — `*` (deep) dejaba
|
|
# keys huerfanas de configs viejas (ej. flags `args` obsoletos).
|
|
jq -s '.[0] * {mcpServers: ((.[0].mcpServers // {}) + (.[1].mcpServers // {}))}' \
|
|
"$mcp_file" <(echo "$new_config") > "${mcp_file}.tmp"
|
|
mv "${mcp_file}.tmp" "$mcp_file"
|
|
else
|
|
echo "$new_config" > "$mcp_file"
|
|
fi
|
|
|
|
echo "$mcp_file"
|
|
}
|