import { useState, useEffect, useCallback } from 'react'; import api from '../services/api-wrapper.ts'; import type { MCPTool } from '../types/index.ts'; import { API_ENDPOINTS } from '../constants/index.ts'; import { cacheMcpTools, getCachedMcpTools } from '../utils/cache.utils.ts'; type MCPToolsState = { tools: MCPTool[]; loading: boolean; error: Error | null; }; const INITIAL_STATE = { tools: [] as MCPTool[], loading: false, error: null, } as MCPToolsState; const isMCPTool = (value: unknown): value is MCPTool => { if (!value || typeof value !== 'object') { return false; } const candidate = value as { name?: unknown; description?: unknown }; return typeof candidate.name === 'string' && (candidate.description === undefined || typeof candidate.description === 'string'); }; const normalizeToolsResponse = (payload: unknown): MCPTool[] | null => { if (Array.isArray(payload)) { return payload.filter(isMCPTool); } if (payload && typeof payload === 'object') { const candidate = payload as { tools?: unknown; data?: unknown }; if (Array.isArray(candidate.tools)) { return candidate.tools.filter(isMCPTool); } if (Array.isArray(candidate.data)) { return candidate.data.filter(isMCPTool); } } return null; }; export const useMCPTools = () => { const [state, setState] = useState(INITIAL_STATE); const fetchTools = useCallback(async () => { try { const cachedTools = getCachedMcpTools(); if (cachedTools && cachedTools.length > 0) { setState({ tools: cachedTools, loading: false, error: null }); } else { setState((prev) => ({ ...prev, loading: true, error: null })); } const payload = await api.get(API_ENDPOINTS.MCP_TOOLS); const parsedTools = normalizeToolsResponse(payload); if (!parsedTools) { throw new Error('Invalid MCP tools response shape'); } setState({ tools: parsedTools, loading: false, error: null }); cacheMcpTools(parsedTools); } catch (err) { setState({ tools: getCachedMcpTools() ?? [], loading: false, error: err instanceof Error ? err : new Error('Failed to fetch MCP tools'), }); } }, []); useEffect(() => { fetchTools(); }, [fetchTools]); return { ...state, refetch: fetchTools }; };