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 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,8 @@ import { registerTool, unregisterTools } from '../webmcp'
|
|||||||
export const THEME_TOOLS = [
|
export const THEME_TOOLS = [
|
||||||
'get_design_tokens',
|
'get_design_tokens',
|
||||||
'get_active_theme',
|
'get_active_theme',
|
||||||
'set_theme_variable'
|
'set_theme_variable',
|
||||||
|
'save_theme'
|
||||||
]
|
]
|
||||||
|
|
||||||
export function registerThemeTools() {
|
export function registerThemeTools() {
|
||||||
@@ -97,7 +98,7 @@ export function registerThemeTools() {
|
|||||||
// set_theme_variable
|
// set_theme_variable
|
||||||
registerTool(
|
registerTool(
|
||||||
'set_theme_variable',
|
'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',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
@@ -114,24 +115,96 @@ export function registerThemeTools() {
|
|||||||
},
|
},
|
||||||
(args: { name: string; value: string }) => {
|
(args: { name: string; value: string }) => {
|
||||||
try {
|
try {
|
||||||
|
const themeStore = useThemeStore()
|
||||||
const root = document.documentElement
|
const root = document.documentElement
|
||||||
const varName = args.name.startsWith('--') ? args.name : `--${args.name}`
|
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
|
// Get current value for feedback
|
||||||
const currentValue = getComputedStyle(root).getPropertyValue(varName).trim()
|
const currentValue = getComputedStyle(root).getPropertyValue(varName).trim()
|
||||||
|
|
||||||
// Set new value
|
// Set new value in DOM
|
||||||
root.style.setProperty(varName, args.value)
|
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` +
|
return `Variable ${varName} cambiada:\n` +
|
||||||
` Anterior: ${currentValue || '(no definida)'}\n` +
|
` Anterior: ${currentValue || '(no definida)'}\n` +
|
||||||
` Nuevo: ${args.value}\n\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) {
|
} catch (e: any) {
|
||||||
return `Error: ${e.message}`
|
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() {
|
export function unregisterThemeTools() {
|
||||||
|
|||||||
Reference in New Issue
Block a user