diff --git a/mcp-gitea-server/src/index.ts b/mcp-gitea-server/src/index.ts index 8fee3fc..cc30832 100644 --- a/mcp-gitea-server/src/index.ts +++ b/mcp-gitea-server/src/index.ts @@ -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());