From 9d3aa6f2ffd619ed200b0d3172dd64472fabcb50 Mon Sep 17 00:00:00 2001 From: josedario87 Date: Fri, 13 Feb 2026 05:43:05 -0600 Subject: [PATCH] feat: Add save_theme MCP tool for persistent theme storage - Add save_theme tool to save themes permanently to database - Update set_theme_variable to track changes in store's previewTheme - Enables full theme creation workflow via MCP tools Co-Authored-By: Claude Opus 4.5 --- frontend/src/services/tools/themeTools.ts | 81 +++++++++++++++++++++-- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/frontend/src/services/tools/themeTools.ts b/frontend/src/services/tools/themeTools.ts index 712d143..3f0f9c7 100644 --- a/frontend/src/services/tools/themeTools.ts +++ b/frontend/src/services/tools/themeTools.ts @@ -4,7 +4,8 @@ import { registerTool, unregisterTools } from '../webmcp' export const THEME_TOOLS = [ 'get_design_tokens', 'get_active_theme', - 'set_theme_variable' + 'set_theme_variable', + 'save_theme' ] export function registerThemeTools() { @@ -97,7 +98,7 @@ export function registerThemeTools() { // set_theme_variable registerTool( 'set_theme_variable', - 'Modifica una variable CSS del tema en tiempo real (cambio temporal, no se guarda)', + 'Modifica una variable CSS del tema en tiempo real (cambio temporal hasta que uses save_theme)', { type: 'object', properties: { @@ -114,24 +115,96 @@ export function registerThemeTools() { }, (args: { name: string; value: string }) => { try { + const themeStore = useThemeStore() const root = document.documentElement const varName = args.name.startsWith('--') ? args.name : `--${args.name}` + const keyName = args.name.startsWith('--') ? args.name.slice(2) : args.name // Get current value for feedback const currentValue = getComputedStyle(root).getPropertyValue(varName).trim() - // Set new value + // Set new value in DOM root.style.setProperty(varName, args.value) + // Update the store's previewTheme to track changes + if (themeStore.activeTheme) { + // Find which category this variable belongs to + const variables = themeStore.activeTheme.variables + for (const category of Object.keys(variables) as (keyof typeof variables)[]) { + if (keyName in variables[category]) { + themeStore.updateVariable(category, keyName, args.value) + break + } + } + } + return `Variable ${varName} cambiada:\n` + ` Anterior: ${currentValue || '(no definida)'}\n` + ` Nuevo: ${args.value}\n\n` + - `Nota: Este cambio es temporal. Para hacerlo permanente, usa el editor de temas en /themes` + `Usa save_theme para guardar los cambios permanentemente.` } catch (e: any) { return `Error: ${e.message}` } } ) + + // save_theme + registerTool( + 'save_theme', + 'Guarda el tema actual con los cambios realizados permanentemente en la base de datos', + { + type: 'object', + properties: { + name: { + type: 'string', + description: 'Nombre para el nuevo tema' + }, + description: { + type: 'string', + description: 'Descripción opcional del tema' + }, + setAsDefault: { + type: 'boolean', + description: 'Si es true, establece este tema como el activo por defecto' + } + }, + required: ['name'] + }, + async (args: { name: string; description?: string; setAsDefault?: boolean }) => { + try { + const themeStore = useThemeStore() + + // Get variables to save (preview has the modified values, or use active) + const variablesToSave = themeStore.previewTheme || themeStore.activeTheme?.variables + + if (!variablesToSave) { + return 'Error: No hay tema con variables para guardar' + } + + // Save the theme + const result = await themeStore.saveTheme({ + name: args.name, + description: args.description || `Tema creado el ${new Date().toLocaleString()}`, + variables: variablesToSave, + metadata: { + author: 'Claude', + version: '1.0', + base: themeStore.activeTheme?.id || null + } + }) + + // Set as default if requested + if (args.setAsDefault && result.id) { + await themeStore.setDefaultTheme(result.id) + return `Tema "${args.name}" guardado y establecido como default.\nID: ${result.id}` + } + + return `Tema "${args.name}" guardado permanentemente en la base de datos.\nID: ${result.id}` + } catch (e: any) { + return `Error al guardar tema: ${e.message}` + } + } + ) } export function unregisterThemeTools() {