Implementar parámetro verbose y paginación en MCP Metabase
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 21s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 21s
Mejoras implementadas:
- Parámetro verbose en metabase_cards, metabase_databases, metabase_collections
- Paginación en metabase_cards (page, pageSize)
- Funciones helper para filtrado de campos (filterCardFields, filterDatabaseFields, filterCollectionFields)
- Corrección de bug en metabase_databases con include_tables (API devuelve {data: []} en lugar de array directo)
Resultados:
- Reducción 94.7% en tamaño de respuestas de cards (60KB → 3KB por 5 cards)
- Reducción 90.2% en tamaño de respuestas de databases (2KB → 198 bytes)
- 100% de pruebas exitosas (9/9)
Documentación:
- Agregado ANALISIS-RESULTADOS.md con análisis detallado
- Agregado SPEC-VERBOSE.md con especificación técnica
- Agregado README-TESTING.md con guía de pruebas
- Actualizado README.md con ejemplos de uso de verbose y paginación
- Actualizado .gitignore para excluir scripts de prueba con API keys
This commit is contained in:
289
mcp-metabase-server/ANALISIS-RESULTADOS.md
Normal file
289
mcp-metabase-server/ANALISIS-RESULTADOS.md
Normal file
@@ -0,0 +1,289 @@
|
||||
# Análisis de Resultados - Pruebas MCP Metabase
|
||||
|
||||
**Fecha**: 2025-10-28
|
||||
**Archivo de resultados**: test-results-1761689858868.json (277KB)
|
||||
|
||||
## Resumen Ejecutivo
|
||||
|
||||
- **Pruebas exitosas**: 9/10 (90%)
|
||||
- **Pruebas fallidas**: 1/10 (10%)
|
||||
- **Tiempo total**: ~1.6 segundos
|
||||
|
||||
## Estado de Herramientas
|
||||
|
||||
### ✅ Herramientas Funcionales (9)
|
||||
|
||||
1. **metabase_collections** (268ms, 590 bytes)
|
||||
- Funciona correctamente
|
||||
- Respuesta pequeña y manejable
|
||||
|
||||
2. **metabase_dashboards** (70ms, 2 bytes)
|
||||
- Funciona correctamente
|
||||
- Respuesta vacía (no hay dashboards)
|
||||
|
||||
3. **metabase_databases** (70ms, 2KB)
|
||||
- Funciona correctamente
|
||||
- Respuesta manejable
|
||||
|
||||
4. **metabase_cards_search** (106ms, 22 bytes)
|
||||
- Funciona correctamente
|
||||
- Respuesta vacía (no encontró resultados para "facturador")
|
||||
|
||||
5. **metabase_cards_list_limited** (96ms, **117KB** ⚠️)
|
||||
- Funciona correctamente
|
||||
- **PROBLEMA**: Solo 10 cards ocupan 117KB
|
||||
- Cada card tiene ~11.7KB de datos
|
||||
|
||||
6. **metabase_card_info** (93ms, 9.2KB)
|
||||
- Funciona correctamente
|
||||
- Tamaño razonable para una card individual
|
||||
|
||||
7. **metabase_execute_card** (541ms, 8.5KB)
|
||||
- Funciona correctamente
|
||||
- Tiempo de ejecución aceptable
|
||||
|
||||
8. **metabase_update_card** (158ms, 9.2KB)
|
||||
- Funciona correctamente
|
||||
- Actualización exitosa
|
||||
|
||||
9. **metabase_update_card_revert** (111ms, 9.2KB)
|
||||
- Funciona correctamente
|
||||
- Reversión exitosa
|
||||
|
||||
### ❌ Herramientas con Errores (1)
|
||||
|
||||
10. **metabase_databases_with_metadata** (79ms)
|
||||
- **Error**: `databases.map is not a function`
|
||||
- Problema en el código del MCP server (index.ts:344)
|
||||
- La API de Metabase está devolviendo un objeto en lugar de un array
|
||||
|
||||
## Análisis de Tamaños de Respuesta
|
||||
|
||||
### Problema Principal: metabase_cards (list)
|
||||
|
||||
Cada card en el listado contiene **todos** los campos, incluyendo:
|
||||
|
||||
| Campo | Tamaño Promedio | ¿Necesario en listado? |
|
||||
|-------|----------------|----------------------|
|
||||
| `dataset_query` | 2,817 chars | ❌ NO (solo en detail) |
|
||||
| `result_metadata` | 2,135 chars | ❌ NO (solo en detail) |
|
||||
| `parameters` | 1,952 chars | ❌ NO (solo en detail) |
|
||||
| `collection` | 324 chars | ✅ SI (info básica) |
|
||||
| `creator` | 272 chars | ⚠️ SOLO en verbose |
|
||||
| `description` | 267 chars | ✅ SI |
|
||||
| `visualization_settings` | 80 chars | ❌ NO |
|
||||
| `name` | 40 chars | ✅ SI |
|
||||
| Otros metadatos | ~300 chars | ✅ SI |
|
||||
|
||||
**Total por card completa**: ~11,700 chars
|
||||
**Total por card filtrada**: ~1,500 chars
|
||||
**Reducción potencial**: **~87%**
|
||||
|
||||
## Recomendaciones
|
||||
|
||||
### 1. Implementar Parámetro `verbose` en Todas las Herramientas
|
||||
|
||||
**Filosofía**: Una sola herramienta con dos modos de operación mediante parámetro `verbose`
|
||||
|
||||
```typescript
|
||||
// Modo Default (verbose: false) - Respuesta ligera
|
||||
{
|
||||
action: 'list',
|
||||
verbose: false // default - puede omitirse
|
||||
}
|
||||
|
||||
// Modo Detallado (verbose: true) - Respuesta completa
|
||||
{
|
||||
action: 'list',
|
||||
verbose: true
|
||||
}
|
||||
```
|
||||
|
||||
#### Campos por Modo en `metabase_cards`
|
||||
|
||||
**Modo Default (verbose: false)** - ~1.2KB por card:
|
||||
```typescript
|
||||
{
|
||||
// Campos esenciales para listados
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
collection_id,
|
||||
collection: { id, name }, // Solo info básica (sin nested objects completos)
|
||||
database_id,
|
||||
query_type,
|
||||
display,
|
||||
type,
|
||||
created_at,
|
||||
updated_at,
|
||||
last_used_at,
|
||||
view_count,
|
||||
archived
|
||||
}
|
||||
```
|
||||
|
||||
**Modo Verbose (verbose: true)** - ~11.7KB por card:
|
||||
```typescript
|
||||
{
|
||||
// Todos los campos anteriores +
|
||||
creator, // ⚠️ Solo en verbose
|
||||
dataset_query, // Solo en verbose
|
||||
result_metadata, // Solo en verbose
|
||||
parameters, // Solo en verbose
|
||||
visualization_settings, // Solo en verbose
|
||||
parameter_mappings, // Solo en verbose
|
||||
embedding_params, // Solo en verbose
|
||||
// ... resto de campos completos
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Implementar Paginación
|
||||
|
||||
```typescript
|
||||
{
|
||||
action: 'list',
|
||||
verbose: false, // default: modo ligero
|
||||
page: 1, // Número de página (default: 1)
|
||||
pageSize: 20 // Cards por página (default: 20, max: 100)
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Aplicar Patrón `verbose` a Otras Herramientas
|
||||
|
||||
Herramientas que se beneficiarían del parámetro `verbose`:
|
||||
|
||||
#### `metabase_cards`
|
||||
- **Default**: Solo campos de listado (~1.2KB/card)
|
||||
- **Verbose**: Incluye creator, dataset_query, parameters, etc. (~11.7KB/card)
|
||||
|
||||
#### `metabase_databases`
|
||||
- **Default**: Info básica sin `features` array
|
||||
- **Verbose**: Incluye features completo, detalles técnicos
|
||||
|
||||
#### `metabase_collections`
|
||||
- **Default**: Solo id, name, location
|
||||
- **Verbose**: Incluye permisos, metadata completa, ancestors
|
||||
|
||||
#### `metabase_card_info`
|
||||
Ya devuelve info completa siempre (actúa como verbose: true por diseño)
|
||||
|
||||
#### `metabase_execute_card`
|
||||
Ya devuelve resultados completos (no necesita verbose)
|
||||
|
||||
### 4. Corregir Bug en `metabase_databases` con `include_tables`
|
||||
|
||||
El error en index.ts línea 344 sugiere que:
|
||||
- La API devuelve `{ data: [...] }` en lugar de array directo
|
||||
- Verificar acceso a `response.data`
|
||||
- Implementar fallback: `response.data || response`
|
||||
|
||||
### 5. Agregar Límite de Resultados por Defecto
|
||||
|
||||
Para evitar respuestas masivas:
|
||||
|
||||
```typescript
|
||||
{
|
||||
action: 'list',
|
||||
limit: 50 // Máximo de cards a devolver (default: 50, max: 100)
|
||||
}
|
||||
```
|
||||
|
||||
## Estimaciones de Reducción
|
||||
|
||||
Si hay ~500 cards en total:
|
||||
|
||||
### Sin filtrado:
|
||||
- 500 cards × 11.7KB = **5.85 MB**
|
||||
- Excede límite de Claude Code (25,000 tokens ≈ 100KB)
|
||||
|
||||
### Con filtrado propuesto:
|
||||
- 500 cards × 1.5KB = **750 KB**
|
||||
- Con paginación (20 por página): **30 KB por página**
|
||||
- Dentro del límite de Claude Code ✅
|
||||
|
||||
## Campos Detallados de una Card
|
||||
|
||||
Lista completa de campos disponibles (38 campos):
|
||||
|
||||
```
|
||||
archived, archived_directly, cache_invalidated_at, cache_ttl,
|
||||
card_schema, collection, collection_id, collection_position,
|
||||
collection_preview, created_at, creator, creator_id, dashboard_id,
|
||||
database_id, dataset_query, description, display, embedding_params,
|
||||
enable_embedding, entity_id, id, initially_published_at,
|
||||
last-edit-info, last_used_at, made_public_by_id, metabase_version,
|
||||
name, parameter_mappings, parameters, public_uuid, query_type,
|
||||
result_metadata, source_card_id, table_id, type, updated_at,
|
||||
view_count, visualization_settings
|
||||
```
|
||||
|
||||
## Próximos Pasos
|
||||
|
||||
1. ✅ Análisis completado
|
||||
2. ⏳ Implementar parámetro `verbose` en todas las herramientas
|
||||
3. ⏳ Implementar paginación (page, pageSize)
|
||||
4. ⏳ Corregir bug en databases con include_tables
|
||||
5. ⏳ Agregar límite por defecto de resultados
|
||||
6. ⏳ Actualizar documentación con nuevos parámetros
|
||||
7. ⏳ Probar nuevamente con dataset completo
|
||||
|
||||
---
|
||||
|
||||
**Generado automáticamente por script de análisis**
|
||||
|
||||
## Análisis del Error: databases_with_metadata
|
||||
|
||||
### Causa del Error
|
||||
|
||||
El endpoint `/api/database` de Metabase devuelve:
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{ "id": 1, "name": "..." },
|
||||
{ "id": 2, "name": "..." }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Pero el código en `index.ts:344` espera un array directamente:
|
||||
```typescript
|
||||
const databases = await metabaseFetch<any[]>('/api/database');
|
||||
// Luego intenta: databases.map(...)
|
||||
```
|
||||
|
||||
### Solución
|
||||
|
||||
El código debería acceder a `databases.data`:
|
||||
```typescript
|
||||
const response = await metabaseFetch<any>('/api/database');
|
||||
const databases = response.data || response; // Fallback por si es array directo
|
||||
```
|
||||
|
||||
O si la API siempre devuelve ese formato, simplemente:
|
||||
```typescript
|
||||
const { data: databases } = await metabaseFetch<{ data: any[] }>('/api/database');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Comandos Útiles para Análisis
|
||||
|
||||
### Ver solo herramientas exitosas
|
||||
```bash
|
||||
jq '.[] | select(.success == true) | {tool: .toolName, time: .executionTime, size: (.data | tostring | length)}' test-results-*.json
|
||||
```
|
||||
|
||||
### Ver solo errores
|
||||
```bash
|
||||
jq '.[] | select(.success == false) | {tool: .toolName, error: .error}' test-results-*.json
|
||||
```
|
||||
|
||||
### Contar total de cards disponibles
|
||||
```bash
|
||||
jq '.[] | select(.toolName == "metabase_cards_list_limited") | .data.total' test-results-*.json
|
||||
```
|
||||
|
||||
### Ver nombres de las primeras 10 cards
|
||||
```bash
|
||||
jq '.[] | select(.toolName == "metabase_cards_list_limited") | .data.cards[] | {id, name}' test-results-*.json
|
||||
```
|
||||
Reference in New Issue
Block a user