feat: Add dynamic MCP tool registration per page

- webmcp.ts: Add tool tracking, unregisterTool(), clearAllTools()
- tools/canvasTools.ts: render_html, render_vue_component
- tools/componentTools.ts: save/load/list/delete_vue_component
- tools/themeTools.ts: get_design_tokens, get_active_theme, set_theme_variable, save_theme
- tools/globalTools.ts: get_current_page, navigate_to, list_available_tools
- toolRegistry.ts: Orchestrates tool registration per page
- App.vue: Initializes WebMCP once, watches route for tool changes
- Canvas.vue: Removed tool registration (now handled by registry)

Tools are now registered when entering a page and unregistered when leaving.
Refresh initializes tools correctly for the current page.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 05:42:17 -06:00
parent 3c38b75040
commit acde6b37d6
11 changed files with 759 additions and 325 deletions

View File

@@ -0,0 +1,143 @@
import { clearAllTools } from './webmcp'
import {
registerCanvasTools,
unregisterCanvasTools,
CANVAS_TOOLS
} from './tools/canvasTools'
import {
registerComponentTools,
unregisterComponentTools,
COMPONENT_TOOLS
} from './tools/componentTools'
import {
registerThemeTools,
unregisterThemeTools,
THEME_TOOLS
} from './tools/themeTools'
import {
registerGlobalTools,
setRouter,
GLOBAL_TOOLS
} from './tools/globalTools'
type PageName = 'canvas' | 'components' | 'themes'
interface PageToolSet {
register: () => void
unregister: () => void
toolNames: string[]
}
const pageTools: Record<PageName, PageToolSet> = {
canvas: {
register: () => {
registerCanvasTools()
registerComponentTools() // Canvas también puede guardar/cargar
},
unregister: () => {
unregisterCanvasTools()
unregisterComponentTools()
},
toolNames: [...CANVAS_TOOLS, ...COMPONENT_TOOLS]
},
components: {
register: registerComponentTools,
unregister: unregisterComponentTools,
toolNames: COMPONENT_TOOLS
},
themes: {
register: registerThemeTools,
unregister: unregisterThemeTools,
toolNames: THEME_TOOLS
}
}
let currentPage: PageName | null = null
let isInitialized = false
/**
* Inicializa el registry con el router de Vue
*/
export function initToolRegistry(router: any) {
setRouter(router)
isInitialized = true
}
/**
* Activa las tools para una página específica.
* Desregistra las tools de otras páginas primero.
*/
export function activatePageTools(pageName: PageName) {
if (!isInitialized) {
console.warn('[ToolRegistry] Not initialized. Call initToolRegistry first.')
return
}
// Si ya estamos en esta página, no hacer nada
if (currentPage === pageName) {
console.log(`[ToolRegistry] Already on page "${pageName}", skipping`)
return
}
console.log(`[ToolRegistry] Switching from "${currentPage}" to "${pageName}"`)
// Desregistrar tools de la página anterior
if (currentPage && pageTools[currentPage]) {
pageTools[currentPage].unregister()
}
// Registrar tools de la nueva página
if (pageTools[pageName]) {
pageTools[pageName].register()
}
// Asegurar que las tools globales estén registradas
registerGlobalTools()
currentPage = pageName
console.log(`[ToolRegistry] Page "${pageName}" tools activated`)
}
/**
* Inicializa las tools para un refresh de página.
* Limpia todo y registra las tools correctas.
*/
export function initToolsOnRefresh(pageName: PageName) {
if (!isInitialized) {
console.warn('[ToolRegistry] Not initialized. Call initToolRegistry first.')
return
}
console.log(`[ToolRegistry] Initializing on refresh for page "${pageName}"`)
// Limpiar todas las tools existentes
clearAllTools()
// Reset current page tracking
currentPage = null
// Activar tools de la página actual
activatePageTools(pageName)
}
/**
* Obtiene el nombre de la página actual
*/
export function getCurrentPage(): PageName | null {
return currentPage
}
/**
* Obtiene los nombres de las tools para una página
*/
export function getPageToolNames(pageName: PageName): string[] {
return [...(pageTools[pageName]?.toolNames || []), ...GLOBAL_TOOLS]
}
/**
* Verifica si el registry está inicializado
*/
export function isRegistryInitialized(): boolean {
return isInitialized
}