From 9f88010eb5e22051d0cba556a6702ec6990cf9c3 Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Mon, 23 Mar 2026 13:02:55 +0100 Subject: [PATCH 1/2] refactor: eliminar MCP servers y usar Python nativo en db-reader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Se remueven las dependencias de mcp-server-sqlite y mcp-server-duckdb. Ahora el agente usa Python directamente con sqlite3 y duckdb. Se agregan reglas críticas para evitar crear archivos con variables de entorno literales. Se documentan ejemplos correctos de rutas absolutas y relativas. Co-Authored-By: Claude Opus 4.5 --- .claude/agents/db-reader/SKILL.md | 104 ++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 33 deletions(-) diff --git a/.claude/agents/db-reader/SKILL.md b/.claude/agents/db-reader/SKILL.md index 6dc5ffc..f612732 100644 --- a/.claude/agents/db-reader/SKILL.md +++ b/.claude/agents/db-reader/SKILL.md @@ -3,21 +3,6 @@ name: db-reader description: Agente especializado en bases de datos SQLite y DuckDB. Puede crear, consultar, insertar y analizar datos. model: sonnet tools: Read, Write, Bash, Glob, Grep -mcpServers: - - sqlite: - type: stdio - command: uvx - args: - - mcp-server-sqlite - - --db-path - - "${SQLITE_DB_PATH:-./data.sqlite}" - - duckdb: - type: stdio - command: uvx - args: - - mcp-server-duckdb - - --db-path - - "${DUCKDB_DB_PATH:-./data.duckdb}" --- # Agente DB Reader @@ -43,22 +28,60 @@ Eres un experto en bases de datos SQLite y DuckDB. Tu rol es ayudar al usuario a ## Flujo de trabajo 1. **Identificar la base de datos**: Pregunta al usuario qué DB usar (sqlite o duckdb) -2. **Verificar conexión**: Usa las herramientas MCP para conectar -3. **Ejecutar operación**: CREATE, INSERT, SELECT, UPDATE, DELETE -4. **Mostrar resultados**: Formatea los resultados de forma legible +2. **Determinar la ruta**: Usa la ruta proporcionada por el usuario o el directorio de trabajo actual +3. **Crear la base de datos**: Usa Python con los módulos `sqlite3` o `duckdb` +4. **Ejecutar operaciones**: CREATE, INSERT, SELECT, UPDATE, DELETE +5. **Mostrar resultados**: Formatea los resultados de forma legible -## Herramientas MCP disponibles +## REGLAS CRÍTICAS - RUTAS DE ARCHIVOS -### SQLite (mcp-server-sqlite) -- `read_query`: Ejecutar SELECT queries -- `write_query`: Ejecutar INSERT/UPDATE/DELETE -- `create_table`: Crear nuevas tablas -- `list_tables`: Listar tablas existentes -- `describe_table`: Ver esquema de una tabla -- `append_insight`: Guardar análisis +**NUNCA** crees archivos o directorios con nombres que contengan: +- Variables de entorno: `${VAR}`, `$VAR`, `${VAR:-default}` +- Caracteres especiales: `{`, `}`, `$` -### DuckDB (mcp-server-duckdb) -- `query`: Ejecutar cualquier query SQL +**SIEMPRE**: +- Usa rutas absolutas expandidas (ej: `/home/user/proyecto/data.duckdb`) +- O rutas relativas simples sin variables (ej: `./data.duckdb`) +- Si el usuario proporciona una ruta con variables, **expándela primero** usando `echo` o Python + +**Ejemplo CORRECTO**: +```bash +# Obtener ruta absoluta del directorio de trabajo +DB_PATH="$(pwd)/data.duckdb" +echo "Base de datos: $DB_PATH" +``` + +**Ejemplo INCORRECTO** (NUNCA hacer esto): +```bash +# PROHIBIDO - crea archivos con nombres literales de variables +mkdir "${DUCKDB_DB_PATH:-." +touch "${SQLITE_DB_PATH:-./data.sqlite}" +``` + +## Herramientas disponibles + +### Python + SQLite (sqlite3) +```python +import sqlite3 +con = sqlite3.connect('/ruta/absoluta/data.sqlite') +cursor = con.cursor() +cursor.execute("SELECT * FROM tabla") +results = cursor.fetchall() +con.close() +``` + +### Python + DuckDB +```python +import duckdb +con = duckdb.connect('/ruta/absoluta/data.duckdb') +results = con.execute("SELECT * FROM tabla").fetchall() +con.close() +``` + +### Instalación de dependencias +```bash +pip install duckdb # DuckDB (sqlite3 viene incluido en Python) +``` ## Convenciones @@ -96,13 +119,28 @@ GROUP BY 1 ORDER BY 1; ``` -## Variables de entorno +## Rutas de bases de datos -- `SQLITE_DB_PATH`: Ruta a la base de datos SQLite (default: ./data.sqlite) -- `DUCKDB_DB_PATH`: Ruta a la base de datos DuckDB (default: ./data.duckdb) +Por defecto, crear las bases de datos en el directorio de trabajo actual: +- SQLite: `{directorio_trabajo}/data.sqlite` +- DuckDB: `{directorio_trabajo}/data.duckdb` + +**IMPORTANTE**: Siempre construir rutas usando Python o comandos bash expandidos: + +```python +import os +# CORRECTO - ruta absoluta +db_path = os.path.join(os.getcwd(), "data.duckdb") +print(f"Creando DB en: {db_path}") + +# CORRECTO - con ruta del usuario +user_path = "/home/lucas/proyecto" +db_path = os.path.join(user_path, "data.duckdb") +``` ## Notas -- DuckDB es mejor para análisis de datos grandes -- SQLite es mejor para datos transaccionales +- DuckDB es mejor para análisis de datos grandes (OLAP) +- SQLite es mejor para datos transaccionales (OLTP) - Ambos soportan SQL estándar +- **NUNCA** usar strings con `${...}` como nombres de archivo From 4bf7f516134af2ba543928ffa869d6c84ef3494d Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Mon, 23 Mar 2026 13:03:00 +0100 Subject: [PATCH 2/2] feat: mejorar init-jupyter para detectar notebooks existentes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ahora el skill detecta si ya hay archivos .ipynb en el repo o carpeta notebooks. Si existen, simplemente inicia Jupyter via MCP sin reinicializar el proyecto. Se garantiza que siempre use MCP para la integración con Claude. Se agrega Glob a las herramientas permitidas para la detección. Co-Authored-By: Claude Opus 4.5 --- .claude/skills/init-jupyter/SKILL.md | 136 +++++++++++++++++---------- 1 file changed, 86 insertions(+), 50 deletions(-) diff --git a/.claude/skills/init-jupyter/SKILL.md b/.claude/skills/init-jupyter/SKILL.md index 0f8cb5f..0ab26d5 100644 --- a/.claude/skills/init-jupyter/SKILL.md +++ b/.claude/skills/init-jupyter/SKILL.md @@ -1,80 +1,116 @@ --- name: init-jupyter -description: Inicializa un proyecto Python con uv, Jupyter Lab y configura MCP para Claude +description: Inicializa o inicia Jupyter Lab via MCP. Detecta notebooks existentes automáticamente. argument-hint: [ruta-proyecto] disable-model-invocation: true user-invocable: true -allowed-tools: Bash, Read, Write, Edit +allowed-tools: Bash, Read, Write, Edit, Glob --- -# Inicializar Proyecto Jupyter +# Inicializar/Iniciar Proyecto Jupyter via MCP -Este skill automatiza la configuración completa de un entorno de análisis de datos con Jupyter Lab integrado con Claude via MCP. +Este skill gestiona entornos Jupyter Lab integrados con Claude via MCP. Detecta automáticamente si ya existe un proyecto configurado. -## Pasos a ejecutar +## Flujo de decisión -1. **Validar ubicación** - - Si se proporciona `$1`, usar esa ruta - - Si no, usar el directorio actual +### 1. Detectar notebooks existentes -2. **Inicializar proyecto con uv** - ```bash - cd [ruta] && uv init - ``` +Buscar archivos `.ipynb` en: +- Raíz del proyecto +- Carpeta `notebooks/` +- Cualquier subcarpeta -3. **Crear entorno virtual** - ```bash - uv venv - ``` +```bash +find [ruta] -name "*.ipynb" -type f 2>/dev/null | head -5 +``` -4. **Instalar dependencias** - ```bash - uv add jupyter jupyter-collaboration - ``` +### 2. Si HAY notebooks existentes → Iniciar directamente -5. **Instalar jupyter-mcp-server** - ```bash - uv tool install jupyter-mcp-server - ``` +**2a. Verificar que MCP está configurado** +- Comprobar si existe `.claude/settings.local.json` con configuración de jupyter +- Si no existe, crearlo (ver paso 6 del flujo de inicialización) -6. **Configurar MCP para Claude** - - Crear o actualizar `.claude/settings.local.json` con la configuración del servidor MCP de Jupyter: - ```json - { - "mcpServers": { - "jupyter": { - "command": "jupyter-mcp-server", - "args": [] - } - } - } - ``` +**2b. Verificar que jupyter-mcp-server está instalado** +```bash +which jupyter-mcp-server || uv tool install jupyter-mcp-server +``` -7. **Crear script de lanzamiento** `start-jupyter.sh`: - ```bash - #!/bin/bash - source .venv/bin/activate - .venv/bin/jupyter lab --no-browser --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.disable_check_xsrf=True - ``` +**2c. Iniciar Jupyter via MCP** +```bash +source .venv/bin/activate 2>/dev/null || true +jupyter lab --no-browser --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.disable_check_xsrf=True +``` -8. **Mostrar resumen al usuario** con los comandos para: - - Activar el entorno: `source .venv/bin/activate` - - Lanzar Jupyter: `./start-jupyter.sh` o el comando directo +**2d. Informar al usuario** que Jupyter está corriendo y puede usar las herramientas MCP de Jupyter desde Claude. + +### 3. Si NO hay notebooks → Inicializar proyecto completo + +Seguir estos pasos: + +**3a. Validar ubicación** +- Si se proporciona `$1`, usar esa ruta +- Si no, usar el directorio actual + +**3b. Inicializar proyecto con uv** (si no existe pyproject.toml) +```bash +cd [ruta] && uv init +``` + +**3c. Crear entorno virtual** +```bash +uv venv +``` + +**3d. Instalar dependencias** +```bash +uv add jupyter jupyter-collaboration +``` + +**3e. Instalar jupyter-mcp-server** +```bash +uv tool install jupyter-mcp-server +``` + +**3f. Configurar MCP para Claude** +Crear o actualizar `.claude/settings.local.json`: +```json +{ + "mcpServers": { + "jupyter": { + "command": "jupyter-mcp-server", + "args": [] + } + } +} +``` + +**3g. Crear carpeta notebooks** (opcional) +```bash +mkdir -p notebooks +``` + +**3h. Iniciar Jupyter via MCP** +```bash +source .venv/bin/activate +jupyter lab --no-browser --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.disable_check_xsrf=True +``` ## Ejemplos de uso -**Inicializar en directorio actual:** +**Iniciar/inicializar en directorio actual:** ```bash /init-jupyter ``` -**Inicializar en ruta específica:** +**Iniciar/inicializar en ruta específica:** ```bash /init-jupyter ~/proyectos/mi-analisis ``` -## Notas +## Notas importantes -- Si el proyecto ya tiene `pyproject.toml`, preguntar antes de sobrescribir -- El script `start-jupyter.sh` se crea con permisos de ejecución +- **Siempre usa MCP**: Jupyter se ejecuta siempre de forma que Claude pueda interactuar via MCP +- Si detecta notebooks existentes, NO reinicializa el proyecto, solo inicia Jupyter +- Si el proyecto ya tiene `pyproject.toml`, no ejecuta `uv init` - La configuración MCP se guarda en `.claude/settings.local.json` del proyecto +- El servidor MCP permite a Claude crear, editar y ejecutar celdas de notebooks