Skip to main content
Glama

Figma MCP Server

by xxflux
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Figma MCP Plugin</title> <style> body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 10px; background-color: #404040; font-size: 12px; } #status { padding: 8px; border-radius: 4px; margin-bottom: 10px; background-color: #eee; display: flex; justify-content: space-between; align-items: center; } .connected { background-color: #e6ffe6 !important; color: #006600; } .disconnected { background-color: #ffe6e6 !important; color: #660000; } .reconnecting { background-color: #fff6e6 !important; color: #665500; animation: pulse 1.5s infinite; } @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.7; } 100% { opacity: 1; } } .log { font-family: monospace; height: 200px; overflow-y: auto; background-color: #1e1e1e; color: #e0e0e0; padding: 8px; font-size: 10px; border-radius: 4px; line-height: 1.3; } .log div { margin-bottom: 2px; } .log .timestamp { color: #8a8a8a; margin-right: 5px; } .log .message-plugin { color: #6a9eff; } .log .message-server { color: #6aff9e; } .log .message-error { color: #ff6a6a; } h3 { margin: 8px 0 5px 0; font-size: 13px; } .server-input { margin-top: 8px; gap: 6px; display: flex; background-color: #e0e0e0; } input { flex: 1; padding: 6px; font-size: 11px; border: 1px solid #ccc; border-radius: 4px; } .disabled { opacity: 0.5; pointer-events: none; } </style> </head> <body> <div id="status"> <span id="status-text">Waiting to connect to MCP server...</span> </div> <div class="server-input"> <input type="text" id="server-url" value="ws://localhost:8080" placeholder="WebSocket URL" disabled> </div> <h3>Console log:</h3> <div id="log" class="log"></div> <script> let ws; const status = document.getElementById('status'); const statusText = document.getElementById('status-text'); const log = document.getElementById('log'); const serverUrlInput = document.getElementById('server-url'); let serverUrl = 'ws://localhost:8080'; let connectionCheckInterval; let reconnectAttempts = 0; const maxReconnectAttempts = 5; let reconnectTimeout; // Listen for messages from the plugin code onmessage = (event) => { const msg = event.data.pluginMessage; if (msg.type === 'connect-to-server') { serverUrl = msg.serverUrl; serverUrlInput.value = serverUrl; reconnectAttempts = 0; // Reset reconnect attempts when manually connecting connectWebSocket(serverUrl); } else { logMessage(`Plugin: ${JSON.stringify(msg)}`, 'plugin'); // If ws is connected, forward the message to server if (ws && ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify(msg)); } } }; // Check connection status and update UI function checkConnectionStatus() { if (!ws) { updateConnectionStatus('disconnected', 'No connection to server'); attemptReconnect(); return; } switch (ws.readyState) { case WebSocket.CONNECTING: updateConnectionStatus('connecting', `Connecting to ${serverUrl}...`); break; case WebSocket.OPEN: updateConnectionStatus('connected', `Connected to MCP server`); reconnectAttempts = 0; // Reset reconnect attempts when connected break; case WebSocket.CLOSING: updateConnectionStatus('disconnecting', `Disconnecting from MCP server...`); break; case WebSocket.CLOSED: updateConnectionStatus('disconnected', `Disconnected from MCP server`); attemptReconnect(); break; default: updateConnectionStatus('disconnected', `Unknown connection state`); attemptReconnect(); } } // Attempt to reconnect to the server function attemptReconnect() { if (reconnectTimeout) { clearTimeout(reconnectTimeout); reconnectTimeout = null; } if (reconnectAttempts >= maxReconnectAttempts) { logMessage(`Maximum reconnection attempts (${maxReconnectAttempts}) reached. Please check server status.`, 'error'); return; } reconnectAttempts++; const delay = Math.min(1000 * Math.pow(2, reconnectAttempts - 1), 30000); // Exponential backoff with 30s max updateConnectionStatus('reconnecting', `Reconnecting (${reconnectAttempts}/${maxReconnectAttempts})...`); logMessage(`Attempting to reconnect (${reconnectAttempts}/${maxReconnectAttempts}) in ${delay/1000}s...`, 'server'); reconnectTimeout = setTimeout(() => { if (ws && ws.readyState !== WebSocket.CLOSED) { ws.close(); } logMessage(`Reconnecting to ${serverUrl}...`, 'server'); connectWebSocket(serverUrl); }, delay); } // Update connection status UI function updateConnectionStatus(state, message) { statusText.textContent = message; // Update status class status.className = ''; if (state === 'connected') { status.classList.add('connected'); serverUrlInput.classList.add('disabled'); } else if (state === 'disconnected' || state === 'error') { status.classList.add('disconnected'); serverUrlInput.classList.remove('disabled'); } else if (state === 'connecting' || state === 'reconnecting') { status.classList.add('reconnecting'); } } // Connect to WebSocket server function connectWebSocket(url) { try { // Clear existing interval if (connectionCheckInterval) { clearInterval(connectionCheckInterval); } // Close existing connection if any if (ws) { ws.close(); } updateConnectionStatus('connecting', `Connecting to ${url}...`); ws = new WebSocket(url); ws.onopen = () => { updateConnectionStatus('connected', 'Connected to MCP server'); // Send ready message to server ws.send(JSON.stringify({ type: 'plugin-ready' })); logMessage('Connected to MCP server', 'server'); // Notify plugin code about connection status parent.postMessage({ pluginMessage: { type: 'connection-status', status: 'connected', url: url } }, '*'); }; ws.onmessage = (event) => { const data = JSON.parse(event.data); logMessage(`Server: ${event.data}`, 'server'); // Forward message to plugin code parent.postMessage({ pluginMessage: data }, '*'); }; ws.onclose = () => { updateConnectionStatus('disconnected', 'Disconnected from MCP server'); logMessage('Disconnected from MCP server', 'error'); // Notify plugin code about connection status parent.postMessage({ pluginMessage: { type: 'connection-status', status: 'disconnected', url: url } }, '*'); }; ws.onerror = (error) => { updateConnectionStatus('error', 'Error connecting to MCP server'); logMessage(`WebSocket error: ${error}`, 'error'); // Notify plugin code about connection status parent.postMessage({ pluginMessage: { type: 'connection-status', status: 'error', url: url, error: String(error) } }, '*'); }; // Start connection check interval (check every 5 seconds) connectionCheckInterval = setInterval(checkConnectionStatus, 5000); } catch (error) { updateConnectionStatus('error', `Error: ${error.message}`); logMessage(`Error: ${error.message}`, 'error'); // Notify plugin code about connection status parent.postMessage({ pluginMessage: { type: 'connection-status', status: 'error', url: url, error: error.message } }, '*'); } } // Add message to log function logMessage(message, type = 'default') { const entry = document.createElement('div'); const timestamp = document.createElement('span'); timestamp.className = 'timestamp'; timestamp.textContent = `${new Date().toLocaleTimeString()}`; const messageSpan = document.createElement('span'); messageSpan.className = `message-${type}`; messageSpan.textContent = message; entry.appendChild(timestamp); entry.appendChild(messageSpan); log.appendChild(entry); log.scrollTop = log.scrollHeight; // Limit log entries to prevent memory issues if (log.children.length > 100) { log.removeChild(log.children[0]); } } </script> </body> </html>

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/xxflux/figma_MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server