Initial commit

This commit is contained in:
Jordan
2026-04-01 23:16:45 +01:00
commit 91cfdaee72
200 changed files with 25589 additions and 0 deletions

View File

@@ -0,0 +1,270 @@
# Error Handling System for Tools
Centralizado error handling para todas las herramientas MCP del servidor.
## Características
**Manejo consistente de errores** - Todas las herramientas retornan el mismo formato
**Logging automático** - Todos los errores se registran en consola
**Validación de parámetros** - Validación requerida y de tipos
**Detección de errores API** - Identifica patrones comunes de error en respuestas
**Información contextual** - Cada error incluye el contexto de dónde ocurrió
## Funciones Disponibles
### `handleToolError(error, context, additionalInfo)`
Maneja cualquier error y retorna una respuesta formateada.
```javascript
import { handleToolError } from "../helpers/errorHandler.js";
try {
// tu código
} catch (error) {
return handleToolError(error, 'my_tool', { userId: 123 });
}
```
**Retorna:**
```json
{
"success": false,
"error": {
"code": "ECONNREFUSED",
"message": "connect ECONNREFUSED 127.0.0.1:3000",
"context": "my_tool",
"userId": 123
}
}
```
---
### `handleApiResponse(data, context)`
Detecta errores en respuestas de API (busca patrones comunes).
```javascript
const response = await axios.post(url, payload);
// Detecta automáticamente: error, Error, PHPSyntax, success: false, etc.
const apiError = handleApiResponse(response.data, 'save_module');
if (apiError) return apiError;
```
---
### `validateRequired(params, requiredFields, context)`
Valida que los parámetros requeridos estén presentes.
```javascript
const error = validateRequired(
{ name: "Juan", email: "" },
['name', 'email'],
'create_user'
);
// error porque email está vacío
```
---
### `validateTypes(params, schema, context)`
Valida tipos de datos.
```javascript
const error = validateTypes(
{ age: "25", active: true },
{ age: 'number', active: 'boolean' },
'create_user'
);
// error porque age es string, no number
```
---
### `createValidator(requiredFields, typeSchema)`
Crea una función validadora reutilizable.
```javascript
const validateUserInput = createValidator(
['name', 'email'],
{ age: 'number', active: 'boolean' }
);
// Usar en múltiples lugares
const error = validateUserInput(params, 'create_user');
if (error) return error;
```
---
### `withErrorHandling(handler, toolName)`
Envuelve un handler para manejar errores automáticamente.
```javascript
const safeHandler = withErrorHandling(
async (params, extra) => {
// tu código
},
'my_tool'
);
```
---
### `safeJsonParse(jsonString, context)`
Parse JSON seguro con manejo de errores.
```javascript
const result = safeJsonParse(jsonString, 'parse_config');
if (!result.success) {
// result.error contiene el error formateado
return result.error;
}
const data = result.data;
```
---
## Patrón Recomendado para Tools
```javascript
import { z } from "zod";
import axios from "axios";
import { withAuth, getSessionCredentials } from "../../auth/index.js";
import {
handleToolError,
handleApiResponse,
validateRequired
} from "../helpers/errorHandler.js";
export function registerMyTool(server) {
server.tool(
"my_tool",
"Descripción de la herramienta",
{
param1: z.string().describe("Parámetro 1"),
param2: z.number().describe("Parámetro 2"),
},
withAuth(async ({ param1, param2 }, extra) => {
try {
// 1. Validar parámetros requeridos
const validationError = validateRequired(
{ param1, param2 },
['param1', 'param2'],
'my_tool'
);
if (validationError) return validationError;
// 2. Obtener credenciales
const credentials = getSessionCredentials(extra.sessionId);
// 3. Hacer llamada API
const response = await axios.post(url, payload, {
headers: { /* ... */ }
});
// 4. Verificar respuesta de API
const apiError = handleApiResponse(response.data, 'my_tool');
if (apiError) return apiError;
// 5. Retornar resultado
return {
content: [{
type: "text",
text: JSON.stringify(response.data, null, 2)
}]
};
} catch (error) {
// Los errores se capturan y formatean automáticamente
return handleToolError(error, 'my_tool', { param1, param2 });
}
})
);
}
```
---
## Errores Detectados Automáticamente
`handleApiResponse()` detecta estos patrones en respuestas:
-`data.error` o `data.Error`
-`data.PHPSyntax` - Errores de sintaxis PHP
-`data.success === false` - Campo success explícito
- ✅ Strings con palabras clave: "error", "fatal", "undefined", "syntax"
- ✅ Respuestas vacías o null
---
## Formato de Error Consistente
Todos los errores retornan este formato:
```json
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Mensaje descriptivo del error",
"context": "nombre_del_tool",
"...": "información adicional"
}
}
```
---
## Migración de Tools Existentes
Para actualizar un tool existente:
1. Importar funciones de error handler
2. Reemplazar `try-catch` genérico con `handleToolError()`
3. Agregar validación con `validateRequired()`
4. Agregar `handleApiResponse()` después de llamadas API
5. Pasar información contextual útil a `handleToolError()`
**Ejemplo antes:**
```javascript
try {
// código
} catch (error) {
return {
content: [{ type: "text", text: "Error: " + error.message }],
isError: true
};
}
```
**Ejemplo después:**
```javascript
try {
// código
} catch (error) {
return handleToolError(error, 'my_tool', { extraInfo: value });
}
```
---
## Logging
Todos los errores se registran en stderr con contexto:
```
[Tool Error - save_module] Cannot read property 'website' of undefined
Stack: Error: Cannot read property 'website' of undefined
at registerSaveModuleTool (/Users/...save.js:45:20)
...
```
Esto facilita debug y auditoría de errores en producción.