Skip to main content
Glama
useMcpxConnection.ts3.97 kB
import { useCallback, useEffect, useReducer } from "react"; import { getMcpxServerURL } from "@/config/api-config"; import { useAuth } from "@/contexts/useAuth"; type ConnectionState = { isConnecting: boolean; isConnected: boolean; error: string | null; disconnectError: string | null; }; type ConnectionAction = | { type: "CONNECT_START" } | { type: "CONNECT_SUCCESS" } | { type: "CONNECT_ERROR"; error: string } | { type: "DISCONNECT" } | { type: "DISCONNECT_ERROR"; error: string }; const connectionReducer = ( state: ConnectionState, action: ConnectionAction, ): ConnectionState => { switch (action.type) { case "CONNECT_START": return { isConnecting: true, isConnected: false, error: null, disconnectError: null, }; case "CONNECT_SUCCESS": return { isConnecting: false, isConnected: true, error: null, disconnectError: null, }; case "CONNECT_ERROR": return { isConnecting: false, isConnected: false, error: action.error, disconnectError: null, }; case "DISCONNECT": return { isConnecting: false, isConnected: false, error: null, disconnectError: null, }; case "DISCONNECT_ERROR": return { isConnecting: false, isConnected: true, error: null, disconnectError: action.error, }; default: return state; } }; export function useMcpxConnection(enabled: boolean = true) { const { loginRequired, isAuthenticated: isUserAuthenticated, loading: authLoading, } = useAuth(); const shouldDelayConnection = !enabled || (loginRequired && (authLoading || !isUserAuthenticated)); const [state, dispatch] = useReducer(connectionReducer, { isConnecting: false, isConnected: false, error: null, disconnectError: null, }); const connect = useCallback(async () => { if (!enabled) return false; if (shouldDelayConnection || state.isConnecting || state.isConnected) { return false; } dispatch({ type: "CONNECT_START" }); try { const response = await fetch(`${getMcpxServerURL("http")}/auth/mcpx`, { method: "POST", headers: { "Content-Type": "application/json", }, credentials: loginRequired ? "include" : "same-origin", body: JSON.stringify({}), }); if (response.ok) { dispatch({ type: "CONNECT_SUCCESS" }); return true; } else { dispatch({ type: "CONNECT_ERROR", error: `Connection failed: ${response.status}`, }); return false; } } catch (error) { dispatch({ type: "CONNECT_ERROR", error: `Connection error: ${error}` }); return false; } }, [ enabled, shouldDelayConnection, state.isConnecting, state.isConnected, loginRequired, ]); const disconnect = useCallback(async () => { if (!enabled) return; if (!state.isConnected) return; try { await fetch(`${getMcpxServerURL("http")}/auth/mcpx`, { method: "DELETE", credentials: loginRequired ? "include" : "same-origin", }); dispatch({ type: "DISCONNECT" }); } catch (error) { dispatch({ type: "DISCONNECT_ERROR", error: `Disconnect failed: ${error}`, }); } }, [enabled, state.isConnected, loginRequired]); useEffect(() => { if ( enabled && !shouldDelayConnection && !state.isConnected && !state.isConnecting ) { void connect(); } else if (state.isConnected && (shouldDelayConnection || !enabled)) { void disconnect(); } }, [ enabled, shouldDelayConnection, state.isConnected, state.isConnecting, connect, disconnect, ]); return { ...state, connectionError: state.error, disconnectError: state.disconnectError, }; }

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/TheLunarCompany/lunar'

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