Mejorar herramientas MCP Gitea con auto-creación y transferencia de repos
All checks were successful
build-and-deploy / build (push) Successful in 12s
build-and-deploy / deploy (push) Successful in 3s

- gitea_variables: Ahora crea automáticamente variables que no existen
- gitea_secrets: Ahora crea automáticamente secrets que no existen
- Ambas herramientas notifican si crearon o actualizaron
- Nueva herramienta gitea_transfer_repo para transferir ownership de repos
- Mejoras en manejo de errores y mensajes de notificación
This commit is contained in:
2025-10-16 16:52:22 -06:00
parent e639a15e1e
commit 2aa9b8e4bb

View File

@@ -284,10 +284,35 @@ server.registerTool(
case 'set':
if (!name) throw new Error('name es requerido para set');
if (!value) throw new Error('value es requerido para set');
result = await giteaRequest(`${basePath}/${name}`, {
method: 'PUT',
body: JSON.stringify({ data: value }),
});
// Para secrets, intentamos PUT primero (actualizar)
// Si falla con 404, hacemos POST (crear)
let secretNotificationMessage = '';
try {
result = await giteaRequest(`${basePath}/${name}`, {
method: 'PUT',
body: JSON.stringify({ data: value }),
});
secretNotificationMessage = `✓ Secret '${name}' actualizado exitosamente`;
} catch (error) {
const errorMsg = error instanceof Error ? error.message : '';
// Si es 404, el secret no existe, intentar crearlo con POST
if (errorMsg.includes('404')) {
result = await giteaRequest(basePath, {
method: 'POST',
body: JSON.stringify({ name, data: value }),
});
secretNotificationMessage = `✓ Secret '${name}' creado exitosamente (no existía previamente)`;
} else {
// Re-lanzar el error si no es 404
throw error;
}
}
// Agregar el mensaje de notificación al resultado
result = typeof result === 'object' && result !== null
? { ...result, _notification: secretNotificationMessage }
: { success: true, _notification: secretNotificationMessage };
break;
case 'delete':
@@ -357,19 +382,36 @@ server.registerTool(
if (!name) throw new Error('name es requerido para set');
if (!value) throw new Error('value es requerido para set');
// Intentar actualizar (PUT) primero, si falla crear (POST)
// Verificar si la variable ya existe
let variableExists = false;
let notificationMessage = '';
try {
await giteaRequest(`${basePath}/${name}`);
variableExists = true;
} catch (error) {
// Variable no existe, será creada
variableExists = false;
}
// Crear o actualizar según corresponda
if (variableExists) {
result = await giteaRequest(`${basePath}/${name}`, {
method: 'PUT',
body: JSON.stringify({ value }),
});
} catch (error) {
// Si el PUT falla (variable no existe), intentar POST
result = await giteaRequest(`${basePath}/${name}`, {
notificationMessage = `✓ Variable '${name}' actualizada exitosamente`;
} else {
result = await giteaRequest(basePath, {
method: 'POST',
body: JSON.stringify({ value }),
body: JSON.stringify({ name, value }),
});
notificationMessage = `✓ Variable '${name}' creada exitosamente (no existía previamente)`;
}
// Agregar el mensaje de notificación al resultado
result = typeof result === 'object' && result !== null
? { ...result, _notification: notificationMessage }
: { success: true, _notification: notificationMessage };
break;
case 'delete':
@@ -394,6 +436,51 @@ server.registerTool(
}
);
// ==================== HERRAMIENTA 6: gitea_transfer_repo ====================
server.registerTool(
'gitea_transfer_repo',
{
title: 'Transferir Repositorio Gitea',
description: 'Transfiere la propiedad (ownership) de un repositorio a otro usuario u organización. Requiere owner, repo y new_owner.',
inputSchema: {
owner: z.string().describe('Propietario actual del repo'),
repo: z.string().describe('Nombre del repo a transferir'),
new_owner: z.string().describe('Nuevo propietario del repo (usuario u organización)'),
},
outputSchema: {
result: z.any().describe('Resultado de la operación')
}
},
async ({ owner, repo, new_owner }) => {
try {
const result = await giteaRequest(`/repos/${owner}/${repo}/transfer`, {
method: 'POST',
body: JSON.stringify({ new_owner }),
});
const transferResult = typeof result === 'object' && result !== null
? { ...result, _notification: `✓ Repositorio '${owner}/${repo}' transferido exitosamente a '${new_owner}'` }
: { success: true, _notification: `✓ Repositorio '${owner}/${repo}' transferido exitosamente a '${new_owner}'` };
return {
content: [{
type: 'text',
text: JSON.stringify(transferResult, null, 2)
}],
structuredContent: {
result: transferResult
}
};
} catch (error) {
const errorMsg = error instanceof Error ? error.message : 'Error desconocido';
return {
content: [{ type: 'text', text: `Error: ${errorMsg}` }],
isError: true
};
}
}
);
// ==================== SERVIDOR EXPRESS ====================
const app = express();
app.use(express.json());