Skip to main content
Glama
mcp.ts8.7 kB
import { queryClient } from "./queryClient"; import { WebSocketMessage } from "./types"; import { apiRequest } from "./queryClient"; import { useToast } from "@/hooks/use-toast"; // Server types and model options export const SERVER_TYPES = [ { value: "local", label: "Local Server" }, { value: "remote", label: "Remote Server" }, { value: "docker", label: "Docker Container" }, { value: "cloud", label: "Cloud Instance" } ]; export const MODEL_OPTIONS = [ { value: "Claude-3-Opus", label: "Claude-3-Opus" }, { value: "Claude-3-Sonnet", label: "Claude-3-Sonnet" }, { value: "Claude-3-Haiku", label: "Claude-3-Haiku" }, { value: "GPT-4", label: "GPT-4" }, { value: "GPT-3.5-Turbo", label: "GPT-3.5-Turbo" }, { value: "Llama-3", label: "Llama-3" } ]; // WebSocket connection let ws: WebSocket | null = null; export function setupWebSocket() { const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const wsUrl = `${protocol}//${window.location.host}/ws`; // Close existing connection if present if (ws && ws.readyState === WebSocket.OPEN) { ws.close(); } ws = new WebSocket(wsUrl); ws.onopen = () => { console.log('WebSocket connection established'); // Send a ping to verify connection if (ws && ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ command: 'ping', timestamp: new Date().toISOString() })); } }; ws.onmessage = (event) => { try { const message: WebSocketMessage = JSON.parse(event.data); handleWebSocketMessage(message); // Log connection confirmation if (message.type === 'connection_established') { console.log('Server confirmed WebSocket connection at:', message.data.timestamp); } } catch (error) { console.error('Error parsing WebSocket message:', error); } }; ws.onclose = () => { console.log('WebSocket connection closed'); // Attempt to reconnect after a delay setTimeout(() => { setupWebSocket(); }, 5000); }; ws.onerror = (error) => { console.error('WebSocket error:', error); }; } function handleWebSocketMessage(message: WebSocketMessage) { console.log('Received WebSocket message:', message); switch (message.type) { case 'server_created': case 'server_updated': case 'server_deleted': queryClient.invalidateQueries({ queryKey: ['/api/servers'] }); queryClient.invalidateQueries({ queryKey: ['/api/stats'] }); break; case 'app_created': case 'app_updated': case 'app_deleted': queryClient.invalidateQueries({ queryKey: ['/api/apps'] }); break; case 'activity_created': queryClient.invalidateQueries({ queryKey: ['/api/activities'] }); break; case 'sync_completed': queryClient.invalidateQueries({ queryKey: ['/api/servers'] }); queryClient.invalidateQueries({ queryKey: ['/api/apps'] }); queryClient.invalidateQueries({ queryKey: ['/api/activities'] }); queryClient.invalidateQueries({ queryKey: ['/api/stats'] }); break; } } // Server API functions export async function syncAllServers() { // Try WebSocket if available, fall back to HTTP API if (ws && ws.readyState === WebSocket.OPEN) { return new Promise((resolve, reject) => { // Create a unique ID for this request const requestId = `sync_${Date.now()}`; // Set up a one-time message handler to catch the response const messageHandler = (event: MessageEvent) => { try { const response = JSON.parse(event.data); if (response.type === 'sync_completed') { // Remove the message listener to avoid memory leaks ws?.removeEventListener('message', messageHandler); resolve(response.data); } else if (response.type === 'error' && response.data.command === 'sync_servers') { // Remove the message listener to avoid memory leaks ws?.removeEventListener('message', messageHandler); reject(new Error(response.data.message)); } } catch (error) { console.error('Error parsing WebSocket response:', error); } }; // Add the temporary message handler if (ws) { ws.addEventListener('message', messageHandler); // Send the command ws.send(JSON.stringify({ command: 'sync_servers', requestId })); } // Set a timeout to clean up the handler and reject the promise if no response setTimeout(() => { ws?.removeEventListener('message', messageHandler); reject(new Error('WebSocket sync operation timed out')); }, 10000); }); } else { // Fall back to HTTP API return apiRequest('POST', '/api/sync'); } } export async function toggleWorkerMode(serverId: number) { // Try WebSocket if available, fall back to HTTP API if (ws && ws.readyState === WebSocket.OPEN) { return new Promise((resolve, reject) => { // Create a unique ID for this request const requestId = `toggle_worker_${Date.now()}`; // Set up a one-time message handler to catch the response const messageHandler = (event: MessageEvent) => { try { const response = JSON.parse(event.data); if (response.type === 'server_updated' && response.data.id === serverId) { // Remove the message listener to avoid memory leaks ws?.removeEventListener('message', messageHandler); resolve(response.data); } else if (response.type === 'error' && response.data.command === 'toggle_worker') { // Remove the message listener to avoid memory leaks ws?.removeEventListener('message', messageHandler); reject(new Error(response.data.message)); } } catch (error) { console.error('Error parsing WebSocket response:', error); } }; // Add the temporary message handler if (ws) { ws.addEventListener('message', messageHandler); // Send the command ws.send(JSON.stringify({ command: 'toggle_worker', serverId, requestId })); } // Set a timeout to clean up the handler and reject the promise if no response setTimeout(() => { ws?.removeEventListener('message', messageHandler); reject(new Error('WebSocket toggle worker operation timed out')); }, 10000); }); } else { // Fall back to HTTP API return apiRequest('POST', `/api/servers/${serverId}/toggle-worker`); } } // Headless API operations export async function performHeadlessOperation(action: string, id?: number, params?: any) { const queryParams = new URLSearchParams(); queryParams.append('action', action); if (id !== undefined) { queryParams.append('id', id.toString()); } if (params) { queryParams.append('params', JSON.stringify(params)); } const url = `/api/headless/operation?${queryParams.toString()}`; return apiRequest('GET', url); } // Format functions export function formatAddress(server: { address: string, port: number }): string { return `${server.address}:${server.port}`; } // Helper for relative time (e.g., "2 hours ago") export function getRelativeTime(date: Date | string): string { const now = new Date(); const past = new Date(date); const diffMs = now.getTime() - past.getTime(); const diffSec = Math.floor(diffMs / 1000); const diffMin = Math.floor(diffSec / 60); const diffHour = Math.floor(diffMin / 60); const diffDay = Math.floor(diffHour / 24); if (diffSec < 60) { return 'Just now'; } else if (diffMin < 60) { return `${diffMin} minute${diffMin !== 1 ? 's' : ''} ago`; } else if (diffHour < 24) { return `${diffHour} hour${diffHour !== 1 ? 's' : ''} ago`; } else { return `${diffDay} day${diffDay !== 1 ? 's' : ''} ago`; } } // Activity icon mapping export function getActivityIcon(type: string) { switch (type) { case 'success': return 'check-circle'; case 'warning': return 'alert-triangle'; case 'error': return 'x-circle'; case 'info': default: return 'info'; } } // Status color mapping export function getStatusColor(status: string) { switch (status) { case 'active': return 'bg-green-100 text-green-800'; case 'warning': return 'bg-amber-100 text-amber-800'; case 'error': return 'bg-red-100 text-red-800'; case 'inactive': default: return 'bg-neutral-100 text-neutral-800'; } }

Latest Blog Posts

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/samihalawa/2025-FINAL-mcpMaster'

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