diff --git a/.claude/skills/init-jupyter/SKILL.md b/.claude/skills/init-jupyter/SKILL.md index e081c63..128685e 100644 --- a/.claude/skills/init-jupyter/SKILL.md +++ b/.claude/skills/init-jupyter/SKILL.md @@ -11,13 +11,20 @@ allowed-tools: Bash, Read, Write, Edit, Glob Skill para preparar cualquier repo para exploración de datos con Jupyter + Claude colaborando en kernel compartido. +## ⚠️ REGLA CRÍTICA: MCP SIEMPRE LOCAL + +**NUNCA instalar jupyter-mcp-server globalmente.** Siempre: +- Instalar en `.venv/bin/` del proyecto con `uv add jupyter-mcp-server` +- Usar ruta ABSOLUTA en `.claude/settings.local.json` +- Si existe instalación global (`~/.local/bin/jupyter-mcp-server`), eliminarla con `uv tool uninstall jupyter-mcp-server` + ## PASO 0: Verificar estado actual del repo **Ejecutar estas comprobaciones primero:** ```bash -# 1. ¿MCP instalado globalmente? -which jupyter-mcp-server && echo "MCP_OK" || echo "MCP_NO" +# 1. ¿MCP instalado en el venv LOCAL del proyecto? +[ -f .venv/bin/jupyter-mcp-server ] && echo "MCP_OK" || echo "MCP_NO" # 2. ¿Repo ya configurado para Jupyter? [ -f .claude/settings.local.json ] && grep -q "jupyter" .claude/settings.local.json && echo "REPO_CONFIG_OK" || echo "REPO_NO_CONFIG" @@ -27,21 +34,53 @@ pgrep -af "jupyter" | grep "$(pwd)" && echo "JUPYTER_RUNNING" || echo "JUPYTER_S # 4. ¿CLAUDE.md tiene reglas Jupyter? [ -f .claude/CLAUDE.md ] && grep -q "JUPYTER HABILITADO" .claude/CLAUDE.md && echo "RULES_OK" || echo "RULES_NO" + +# 5. ¿Puerto guardado está sincronizado con Jupyter real? +if [ -f .jupyter-port ]; then + PORT=$(cat .jupyter-port) + if lsof -i:$PORT 2>/dev/null | grep -q jupyter; then + echo "PORT_SYNC_OK" + else + echo "PORT_DESYNC (archivo dice $PORT pero no hay Jupyter ahí)" + fi +fi + +# 6. ¿Existe instalación GLOBAL de jupyter-mcp-server? (problemática) +[ -f ~/.local/bin/jupyter-mcp-server ] && echo "GLOBAL_MCP_EXISTS (eliminar)" || echo "NO_GLOBAL_MCP" ``` +### Resultado: Instalación GLOBAL detectada (GLOBAL_MCP_EXISTS) + +**Eliminar inmediatamente para evitar conflictos:** + +```bash +# Eliminar instalación global +uv tool uninstall jupyter-mcp-server 2>/dev/null || pip uninstall -y jupyter-mcp-server 2>/dev/null +rm -f ~/.local/bin/jupyter-mcp-server + +# Verificar eliminación +[ -f ~/.local/bin/jupyter-mcp-server ] && echo "ERROR: No se pudo eliminar" || echo "Instalación global eliminada OK" +``` + +Continuar con instalación local. + ### Resultado: MCP NO instalado +**IMPORTANTE: NUNCA instalar jupyter-mcp-server globalmente. Siempre en el venv local.** + ```bash -uv tool install jupyter-mcp-server +# Crear venv si no existe +[ -d .venv ] || uv venv + +# Instalar MCP en el venv local del proyecto +source .venv/bin/activate +uv add jupyter-mcp-server || pip install jupyter-mcp-server + +# Verificar instalación local exitosa +[ -f .venv/bin/jupyter-mcp-server ] && echo "MCP instalado localmente OK" || echo "ERROR: MCP no instalado" ``` -Informar: -``` -MCP jupyter-mcp-server instalado. -Ejecuta /exit y vuelve a entrar para recargar. -Después ejecuta /init-jupyter de nuevo. -``` -**DETENER AQUÍ** +Continuar con los siguientes pasos para configurar el MCP local. ### Resultado: Repo YA configurado + Jupyter corriendo @@ -61,6 +100,19 @@ Ejecuta ./run-jupyter-lab.sh en otra terminal para iniciarlo. ``` **DETENER AQUÍ** +### Resultado: Puerto DESINCRONIZADO (PORT_DESYNC) + +El archivo `.jupyter-port` dice un puerto pero Jupyter no está corriendo ahí. + +**Opciones:** +1. Si Jupyter está corriendo en otro puerto → actualizar `.jupyter-port` y `.claude/settings.local.json` +2. Si Jupyter no está corriendo → ejecutar `./run-jupyter-lab.sh` (actualizará el puerto automáticamente) + +```bash +# Buscar en qué puerto está Jupyter realmente +pgrep -af "jupyter" | grep -oP 'port[= ]\K\d+' || echo "Jupyter no está corriendo" +``` + ### Resultado: Repo NO configurado → Continuar con PASO 1 --- @@ -164,27 +216,50 @@ SCRIPT chmod +x run-jupyter-lab.sh ``` -### 4c. Crear/Actualizar `.claude/settings.local.json` +### 4c. Crear/Actualizar `.claude/settings.local.json` (con MERGE) -Usar el PUERTO detectado: +**IMPORTANTE: Usar ruta ABSOLUTA al ejecutable del venv local.** +**IMPORTANTE: Hacer MERGE para preservar otros MCPs existentes.** + +Usar el PUERTO detectado y la ruta absoluta: ```bash -cat > .claude/settings.local.json << EOF +# Obtener ruta absoluta del proyecto +PROJECT_PATH=$(pwd) +PUERTO=8888 # Reemplazar con el puerto detectado en Paso 3 + +# Crear config de jupyter como JSON temporal +cat > /tmp/jupyter-mcp.json << EOF { "mcpServers": { "jupyter": { - "command": "jupyter-mcp-server", + "command": "${PROJECT_PATH}/.venv/bin/jupyter-mcp-server", "args": [ - "--jupyter-url", "http://localhost:PUERTO", + "--jupyter-url", "http://localhost:${PUERTO}", "--start-new-runtime", "false" ] } } } EOF + +# Merge: si existe settings.local.json, combinar; si no, crear nuevo +if [ -f .claude/settings.local.json ]; then + # Merge profundo: preserva otros MCPs, actualiza/añade jupyter + jq -s '.[0] * .[1] | .mcpServers = (.[0].mcpServers // {}) * (.[1].mcpServers // {})' \ + .claude/settings.local.json /tmp/jupyter-mcp.json > .claude/settings.local.json.tmp + mv .claude/settings.local.json.tmp .claude/settings.local.json + echo "settings.local.json actualizado (merge con config existente)" +else + # No existe, crear nuevo + mv /tmp/jupyter-mcp.json .claude/settings.local.json + echo "settings.local.json creado" +fi + +rm -f /tmp/jupyter-mcp.json ``` -(Reemplazar PUERTO por el valor real detectado) +**NOTA:** La ruta absoluta es crítica. Si usas solo `jupyter-mcp-server`, Claude buscará en PATH global y fallará. ### 4d. Añadir/Actualizar instrucciones en `.claude/CLAUDE.md` @@ -269,11 +344,16 @@ uv init 2>/dev/null || true uv venv 2>/dev/null || true ``` -### 5b. Instalar dependencias de Jupyter: +### 5b. Instalar dependencias de Jupyter (incluyendo MCP): + +**IMPORTANTE: jupyter-mcp-server SIEMPRE se instala en el venv local, NUNCA global.** ```bash source .venv/bin/activate 2>/dev/null || true -uv add jupyter jupyterlab pandas numpy matplotlib 2>/dev/null || pip install jupyter jupyterlab pandas numpy matplotlib +uv add jupyter jupyterlab jupyter-mcp-server pandas numpy matplotlib 2>/dev/null || pip install jupyter jupyterlab jupyter-mcp-server pandas numpy matplotlib + +# Verificar que MCP quedó instalado localmente +[ -f .venv/bin/jupyter-mcp-server ] && echo "MCP instalado en venv local OK" || echo "ERROR: MCP no instalado" ``` --- @@ -288,17 +368,40 @@ Mostrar: ═══════════════════════════════════════════════════════════════ Puerto asignado: [PUERTO] + MCP: .venv/bin/jupyter-mcp-server (LOCAL al proyecto) - Para empezar: - 1. En otra terminal ejecuta: ./run-jupyter-lab.sh - 2. Abre http://localhost:[PUERTO] en tu navegador - 3. Crea o abre un notebook - 4. Yo me conecto automáticamente al kernel compartido + ┌─────────────────────────────────────────────────────────┐ + │ PASOS PARA ACTIVAR (orden importante): │ + │ │ + │ 1. SALIR de Claude Code: /exit o Ctrl+C │ + │ (necesario para que cargue el nuevo MCP) │ + │ │ + │ 2. En OTRA terminal, ejecuta: │ + │ cd [RUTA] && ./run-jupyter-lab.sh │ + │ │ + │ 3. Volver a entrar a Claude: │ + │ cd [RUTA] && claude │ + │ (ahora detectará el MCP de Jupyter) │ + │ │ + │ 4. Abre en navegador: http://localhost:[PUERTO] │ + │ │ + │ 5. Crea o abre un notebook y empieza a trabajar │ + └─────────────────────────────────────────────────────────┘ Archivos creados/actualizados: - - run-jupyter-lab.sh (lanzador) - - .claude/settings.local.json (config MCP) - - .claude/CLAUDE.md (reglas de trabajo) + ✓ run-jupyter-lab.sh (lanzador con autodetección de puerto) + ✓ .claude/settings.local.json (config MCP - merge con existente) + ✓ .claude/CLAUDE.md (reglas de trabajo al principio) + ✓ .venv/bin/jupyter-mcp-server (ejecutable MCP local) + + Verificación rápida del MCP: + $ ls -la .venv/bin/jupyter-mcp-server + + Si el MCP no funciona después de reiniciar Claude: + 1. Verifica que Jupyter está corriendo: pgrep -af jupyter + 2. Verifica puerto: cat .jupyter-port + 3. Verifica MCP existe: ls .venv/bin/jupyter-mcp-server + 4. Revisa config: cat .claude/settings.local.json ═══════════════════════════════════════════════════════════════ ```