import { useCanvasStore } from '../stores/canvas' let webmcpInstance: any = null const registeredTools = new Set() const eventUnsubscribers: Array<() => void> = [] const API_BASE = 'http://localhost:4101' let tokenPollingInterval: number | null = null export async function initWebMCP() { if (webmcpInstance) return webmcpInstance const WebMCPModule = await import('@nucleoriofrio/webmcp/src/webmcp.js') const WebMCP = WebMCPModule.default || WebMCPModule webmcpInstance = new WebMCP({ headless: true, inactivityTimeout: 60 * 60 * 1000 // 1 hora }) setupEventHandlers() // Check initial connection state if (webmcpInstance.isConnected) { const canvasStore = useCanvasStore() canvasStore.setConnected(true) updateConnectionInfo() } // Expose globally for debug ;(window as any).webmcp = webmcpInstance return webmcpInstance } function setupEventHandlers() { // Skip if instance doesn't support events if (typeof webmcpInstance.on !== 'function') { console.warn('[WebMCP] Event emitter not available') return } const canvasStore = useCanvasStore() // Connection events eventUnsubscribers.push( webmcpInstance.on('connected', () => { console.log('[WebMCP] Connected') canvasStore.setConnected(true) canvasStore.setReconnecting(false) canvasStore.setConnectionError(null) updateConnectionInfo() }) ) eventUnsubscribers.push( webmcpInstance.on('disconnected', () => { console.log('[WebMCP] Disconnected') canvasStore.setConnected(false) canvasStore.setReconnecting(false) canvasStore.setConnectionInfo(null) }) ) eventUnsubscribers.push( webmcpInstance.on('reconnecting', () => { console.log('[WebMCP] Reconnecting...') canvasStore.setReconnecting(true) }) ) // Status changes eventUnsubscribers.push( webmcpInstance.on('statusChange', (data: { status: string }) => { canvasStore.setConnectionStatus(data.status) }) ) // Error handling eventUnsubscribers.push( webmcpInstance.on('error', (data: { message: string }) => { console.error('[WebMCP] Error:', data.message) canvasStore.setConnectionError(data.message) canvasStore.showNotification(data.message, 'error') }) ) // Tool events eventUnsubscribers.push( webmcpInstance.on('toolRegistered', (data: { name: string }) => { console.log('[WebMCP] Tool registered by server:', data.name) updateConnectionInfo() }) ) eventUnsubscribers.push( webmcpInstance.on('toolCreated', (data: { name: string }) => { console.log('[WebMCP] Tool created:', data.name) registeredTools.add(data.name) updateConnectionInfo() }) ) eventUnsubscribers.push( webmcpInstance.on('toolRemoved', (data: { name: string }) => { if (data.name === '*') { console.log('[WebMCP] All tools removed') registeredTools.clear() } else { console.log('[WebMCP] Tool removed:', data.name) registeredTools.delete(data.name) } updateConnectionInfo() }) ) } function updateConnectionInfo() { if (!webmcpInstance) return const canvasStore = useCanvasStore() const info = webmcpInstance.getConnectionInfo?.() if (info) { canvasStore.setConnectionInfo({ isConnected: info.isConnected, channel: info.channel, server: info.server, status: info.status, tools: info.tools || [], prompts: info.prompts || [], resources: info.resources || [] }) } } export function getConnectionInfo() { return webmcpInstance?.getConnectionInfo?.() || null } export function getWebMCP() { return webmcpInstance } export function registerTool( name: string, description: string, schema: object, handler: Function ) { if (!webmcpInstance) { console.warn('[WebMCP] Instance not initialized') return false } if (registeredTools.has(name)) { console.warn(`[WebMCP] Tool "${name}" already registered, skipping`) return false } webmcpInstance.registerTool(name, description, schema, handler) registeredTools.add(name) console.log(`[WebMCP] Tool registered: ${name}`) return true } export function unregisterTool(name: string) { if (!webmcpInstance) { console.warn('[WebMCP] Instance not initialized') return false } if (!registeredTools.has(name)) { return false } webmcpInstance.unregisterTool(name) registeredTools.delete(name) console.log(`[WebMCP] Tool unregistered: ${name}`) return true } export function unregisterTools(names: string[]) { for (const name of names) { unregisterTool(name) } } export function clearAllTools() { if (!webmcpInstance) return for (const name of registeredTools) { webmcpInstance.unregisterTool(name) } console.log(`[WebMCP] Cleared ${registeredTools.size} tools`) registeredTools.clear() } export function destroyWebMCP() { // Unsubscribe all event handlers for (const unsub of eventUnsubscribers) { unsub() } eventUnsubscribers.length = 0 // Clear tools clearAllTools() // Disconnect if connected if (webmcpInstance?.disconnect) { webmcpInstance.disconnect() } webmcpInstance = null ;(window as any).webmcp = null console.log('[WebMCP] Instance destroyed') } export function getRegisteredTools(): string[] { return [...registeredTools] } export function isToolRegistered(name: string): boolean { return registeredTools.has(name) } // Token polling functions export async function checkForToken(): Promise { try { const res = await fetch(`${API_BASE}/api/webmcp-token`) const data = await res.json() return data.token || null } catch (e) { return null } } export async function clearToken(): Promise { try { await fetch(`${API_BASE}/api/webmcp-token`, { method: 'DELETE' }) } catch (e) { // ignore } } export function startTokenPolling(onToken: (token: string) => void, intervalMs: number = 2000) { if (tokenPollingInterval) return console.log('[WebMCP] Starting token polling...') tokenPollingInterval = window.setInterval(async () => { const token = await checkForToken() if (token) { console.log('[WebMCP] Token detected!') stopTokenPolling() onToken(token) } }, intervalMs) } export function stopTokenPolling() { if (tokenPollingInterval) { window.clearInterval(tokenPollingInterval) tokenPollingInterval = null console.log('[WebMCP] Token polling stopped') } } export function parseToken(token: string): { server: string; token: string } | null { try { const decoded = atob(token) return JSON.parse(decoded) } catch (e) { console.error('[WebMCP] Failed to parse token:', e) return null } } export async function connectWithToken(token: string): Promise { if (!webmcpInstance) { console.error('[WebMCP] Instance not initialized') return false } if (typeof webmcpInstance.connect !== 'function') { console.error('[WebMCP] connect method not available') return false } console.log('[WebMCP] Connecting with token...') // Clear the pending token from server await clearToken() // Connect passing the token directly try { await webmcpInstance.connect(token) return true } catch (e) { console.error('[WebMCP] Failed to connect:', e) return false } }