@samanhappy/mcphub 0.12.16 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.fr.md +1 -1
  2. package/dist/config/index.js +9 -9
  3. package/dist/config/index.js.map +1 -1
  4. package/dist/middlewares/userContext.js +17 -2
  5. package/dist/middlewares/userContext.js.map +1 -1
  6. package/dist/services/mcpService.js +49 -12
  7. package/dist/services/mcpService.js.map +1 -1
  8. package/dist/services/sseService.js +5 -3
  9. package/dist/services/sseService.js.map +1 -1
  10. package/dist/services/vectorSearchService.js +5 -1
  11. package/dist/services/vectorSearchService.js.map +1 -1
  12. package/frontend/dist/assets/ActivityPage-VwilVMvp.js +2 -0
  13. package/frontend/dist/assets/ActivityPage-VwilVMvp.js.map +1 -0
  14. package/frontend/dist/assets/ConfirmDialog-CxlizGia.js +2 -0
  15. package/frontend/dist/assets/ConfirmDialog-CxlizGia.js.map +1 -0
  16. package/frontend/dist/assets/Dashboard-DuBJTbbA.js +2 -0
  17. package/frontend/dist/assets/Dashboard-DuBJTbbA.js.map +1 -0
  18. package/frontend/dist/assets/DeleteDialog-DRbWonMu.js +2 -0
  19. package/frontend/dist/assets/DeleteDialog-DRbWonMu.js.map +1 -0
  20. package/frontend/dist/assets/EndpointCopy-C59moJ3Y.js +2 -0
  21. package/frontend/dist/assets/EndpointCopy-C59moJ3Y.js.map +1 -0
  22. package/frontend/dist/assets/GroupsPage-Bhg51kbu.js +33 -0
  23. package/frontend/dist/assets/GroupsPage-Bhg51kbu.js.map +1 -0
  24. package/frontend/dist/assets/LoginPage-C8RkMoJN.js +2 -0
  25. package/frontend/dist/assets/LoginPage-C8RkMoJN.js.map +1 -0
  26. package/frontend/dist/assets/LogsPage-HBGNLtyN.js +2 -0
  27. package/frontend/dist/assets/LogsPage-HBGNLtyN.js.map +1 -0
  28. package/frontend/dist/assets/MarketPage-C5ATZ4WS.js +3 -0
  29. package/frontend/dist/assets/MarketPage-C5ATZ4WS.js.map +1 -0
  30. package/frontend/dist/assets/Pagination-BFi-X7qY.js +2 -0
  31. package/frontend/dist/assets/Pagination-BFi-X7qY.js.map +1 -0
  32. package/frontend/dist/assets/PromptsPage-DUge8OO4.js +2 -0
  33. package/frontend/dist/assets/PromptsPage-DUge8OO4.js.map +1 -0
  34. package/frontend/dist/assets/ResourcesPage-5J3JYGVC.js +2 -0
  35. package/frontend/dist/assets/ResourcesPage-5J3JYGVC.js.map +1 -0
  36. package/frontend/dist/assets/ServersPage-DtnlfwJF.js +37 -0
  37. package/frontend/dist/assets/ServersPage-DtnlfwJF.js.map +1 -0
  38. package/frontend/dist/assets/SettingsPage-BeLZKC1d.js +12 -0
  39. package/frontend/dist/assets/SettingsPage-BeLZKC1d.js.map +1 -0
  40. package/frontend/dist/assets/StatusDot-DR803YdX.js +2 -0
  41. package/frontend/dist/assets/StatusDot-DR803YdX.js.map +1 -0
  42. package/frontend/dist/assets/ToggleGroup-DE8t8Ni4.js +2 -0
  43. package/frontend/dist/assets/ToggleGroup-DE8t8Ni4.js.map +1 -0
  44. package/frontend/dist/assets/UsersPage-CMscqAmn.js +2 -0
  45. package/frontend/dist/assets/UsersPage-CMscqAmn.js.map +1 -0
  46. package/frontend/dist/assets/framework-vendor-BUhDPOUZ.js +61 -0
  47. package/frontend/dist/assets/framework-vendor-BUhDPOUZ.js.map +1 -0
  48. package/frontend/dist/assets/i18n-vendor-Kbr87Ofu.js +2 -0
  49. package/frontend/dist/assets/i18n-vendor-Kbr87Ofu.js.map +1 -0
  50. package/frontend/dist/assets/icons-vendor-CKgJB3SC.js +292 -0
  51. package/frontend/dist/assets/icons-vendor-CKgJB3SC.js.map +1 -0
  52. package/frontend/dist/assets/index-B9cW2F0H.js +3 -0
  53. package/frontend/dist/assets/index-B9cW2F0H.js.map +1 -0
  54. package/frontend/dist/assets/index-Crcbkt8x.css +1 -0
  55. package/frontend/dist/assets/resourceService-BFMkDDIh.js +2 -0
  56. package/frontend/dist/assets/{resourceService-CUz722Nb.js.map → resourceService-BFMkDDIh.js.map} +1 -1
  57. package/frontend/dist/assets/useServerData-BnLmpLAC.js +2 -0
  58. package/frontend/dist/assets/useServerData-BnLmpLAC.js.map +1 -0
  59. package/frontend/dist/assets/useSettingsData-Cqi9d7Ug.js +2 -0
  60. package/frontend/dist/assets/useSettingsData-Cqi9d7Ug.js.map +1 -0
  61. package/frontend/dist/assets/variableDetection-BigiltQM.js +16 -0
  62. package/frontend/dist/assets/variableDetection-BigiltQM.js.map +1 -0
  63. package/frontend/dist/index.html +5 -2
  64. package/package.json +2 -2
  65. package/frontend/dist/assets/index-CVDuCISB.js +0 -323
  66. package/frontend/dist/assets/index-CVDuCISB.js.map +0 -1
  67. package/frontend/dist/assets/index-PEyR1nSL.css +0 -1
  68. package/frontend/dist/assets/resourceService-CUz722Nb.js +0 -2
@@ -0,0 +1 @@
1
+ {"version":3,"mappings":"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","names":["callTool","request","server","url","response","apiPost","error","toggleTool","serverName","toolName","enabled","updateToolDescription","description","apiPut","resetToolDescription","apiDelete","_a","DynamicForm","schema","onSubmit","onCancel","loading","storageKey","title","t","useTranslation","formValues","setFormValues","useState","errors","setErrors","isJsonMode","setIsJsonMode","jsonText","setJsonText","jsonError","setJsonError","jsonSchema","useMemo","convertProperty","prop","obj","key","value","useEffect","initializeValues","path","values","propSchema","fullPath","initialValues","savedData","parsedData","handleJsonTextChange","text","parsedJson","switchToJsonMode","switchToFormMode","handleInputChange","prev","newValues","keys","current","i","newErrors","validateForm","validateObject","item","index","handleSubmit","e","getNestedValue","renderObjectField","currentValue","onChange","jsxs","jsx","option","idx","val","renderField","arrayValue","_b","_c","newArray","objKey","objSchema","newValue","newItem","_e","_d","_f","_h","_g","_i","parsedValue","_j","_k","_l","_m","_n","ToolResult","result","onClose","content","normalizeMimeType","collectImagesFromValue","images","base64","extractImagesFromText","parsed","dataUriRegex","match","mimeType","sanitizeTextForDisplay","scrub","next","renderContent","renderContentItem","extractedImages","sanitizedText","image","CheckCircle","XCircle","AlertCircle","ResetDescriptionButton","onClick","disabled","RotateCcw","isEmptyValue","ToolCard","tool","onToggle","onDescriptionUpdate","showToast","useToast","nameSeparator","useSettingsData","isExpanded","setIsExpanded","showRunForm","setShowRunForm","isRunning","setIsRunning","setResult","isEditingDescription","setIsEditingDescription","isResettingDescription","setIsResettingDescription","customDescription","setCustomDescription","descriptionInputRef","useRef","descriptionTextRef","textWidth","setTextWidth","copiedToolName","setCopiedToolName","getStorageKey","useCallback","clearStoredFormData","handleToggle","handleDescriptionEdit","handleDescriptionSave","handleDescriptionChange","handleDescriptionReset","restoredDescription","handleDescriptionKeyDown","handleCopyToolName","textArea","err","handleRunTool","arguments_","_","v","handleCancelRun","handleCloseResult","Check","Copy","Fragment","Edit","Switch","Loader","Play","ChevronDown","ChevronRight","callPrompt","getPrompt","togglePrompt","promptName","updatePromptDescription","resetPromptDescription","PromptResult","message","PromptCard","prompt","handleGetPrompt","convertToSchema","properties","required","arg","ResourceCard","resource","transportLabel","type","ServerCard","onRemove","onEdit","onRefresh","onReload","exportMCPSettings","installConfig","baseUrl","expanded","setExpanded","expandedTab","setExpandedTab","showDeleteDialog","setShowDeleteDialog","isToggling","setIsToggling","isReloading","setIsReloading","showMenu","setShowMenu","showErrorPopover","setShowErrorPopover","copiedError","setCopiedError","menuRef","errorPopoverRef","handleClickOutside","event","totalTools","enabledTools","totalPrompts","enabledPrompts","p","totalResources","enabledResources","r","handleReload","copyText","el","ok","handleCopyError","handleCopyConfig","json","handleOAuth","left","top","handleToolToggle","__vitePreload","toolService","handlePromptToggle","promptService","handleResourceToggle","resourceUri","toggleResource","handleToolDescriptionUpdate","_name","_desc","options","handlePromptDescriptionUpdate","handleResourceDescriptionUpdate","updateResourceDescription","resetResourceDescription","c","parts","serverEndpoint","X","ServerStatusDot","Wrench","MessageSquare","FileText","MoreHorizontal","Edit3","RefreshCw","Trash2","tab","active","DeleteDialog","AddServerForm","onAdd","modalVisible","setModalVisible","setError","confirmationVisible","setConfirmationVisible","pendingPayload","setPendingPayload","detectedVariables","setDetectedVariables","toggleModal","handleConfirmSubmit","submitServer","payload","variables","detectVariables","ServerForm","variable","EditServerForm","encodedServerName","isRenaming","requestBody","McpbUploadForm","onSuccess","isDragging","setIsDragging","isUploading","setIsUploading","selectedFile","setSelectedFile","showServerForm","setShowServerForm","manifestData","setManifestData","extractDir","setExtractDir","showConfirmDialog","setShowConfirmDialog","pendingServerName","setPendingServerName","handleDragOver","handleDragLeave","handleDrop","files","file","handleFileSelect","handleUpload","formData","fetchWithInterceptors","getApiUrl","handleInstallServer","forceOverride","serverConfig","convertMcpbToMcpConfig","checkResult","apiGet","handleConfirmOverride","handleCancelOverride","manifest","extractPath","_serverName","mcpConfig","config","ConfirmDialog","nameInput","JSONImportForm","jsonInput","setJsonInput","isImporting","setIsImporting","previewServers","setPreviewServers","examplePlaceholder","parseAndValidateJson","input","handlePreview","servers","name","normalizedConfig","handleImport","successCount","failureCount","results","ServersPage","navigate","useNavigate","allServers","isLoading","pagination","currentPage","serversPerPage","setCurrentPage","setServersPerPage","handleServerAdd","handleServerEdit","handleServerRemove","handleServerToggle","handleServerReload","triggerRefresh","useServerData","editingServer","setEditingServer","isRefreshing","setIsRefreshing","showMcpbUpload","setShowMcpbUpload","showJsonImport","setShowJsonImport","filter","setFilter","search","setSearch","counts","s","filteredServers","q","handleEditClick","fullServerData","handleRefresh","resolve","Plus","FileCode","Upload","k","l","n","Search","Pagination"],"ignoreList":[],"sources":["../../src/services/toolService.ts","../../src/components/ui/DynamicForm.tsx","../../src/components/ui/ToolResult.tsx","../../src/components/ui/ResetDescriptionButton.tsx","../../src/components/ui/ToolCard.tsx","../../src/services/promptService.ts","../../src/components/ui/PromptResult.tsx","../../src/components/ui/PromptCard.tsx","../../src/components/ui/ResourceCard.tsx","../../src/components/ServerCard.tsx","../../src/components/AddServerForm.tsx","../../src/components/EditServerForm.tsx","../../src/components/McpbUploadForm.tsx","../../src/components/JSONImportForm.tsx","../../src/pages/ServersPage.tsx"],"sourcesContent":["import { apiDelete, apiPost, apiPut } from '../utils/fetchInterceptor';\n\nexport interface ToolCallRequest {\n toolName: string;\n arguments?: Record<string, any>;\n}\n\nexport interface ToolCallResult {\n success: boolean;\n content?: Array<{\n type: string;\n text?: string;\n [key: string]: any;\n }>;\n error?: string;\n message?: string;\n}\n\n/**\n * Call a MCP tool via the call_tool API\n */\nexport const callTool = async (\n request: ToolCallRequest,\n server?: string,\n): Promise<ToolCallResult> => {\n try {\n // Construct the URL with optional server parameter\n // URL-encode server and tool names to handle slashes in names (e.g., \"com.atlassian/atlassian-mcp-server\")\n const url = server\n ? `/tools/${encodeURIComponent(server)}/${encodeURIComponent(request.toolName)}`\n : '/tools/call';\n\n const response = await apiPost<any>(url, request.arguments, {\n headers: {\n Authorization: `Bearer ${localStorage.getItem('mcphub_token')}`, // Add bearer auth for MCP routing\n },\n });\n\n if (response.success === false) {\n return {\n success: false,\n error: response.message || 'Tool call failed',\n };\n }\n\n return {\n success: true,\n content: response?.content || [],\n };\n } catch (error) {\n console.error('Error calling tool', { toolName: request.toolName, server, error });\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n };\n }\n};\n\n/**\n * Toggle a tool's enabled state for a specific server\n */\nexport const toggleTool = async (\n serverName: string,\n toolName: string,\n enabled: boolean,\n): Promise<{ success: boolean; error?: string }> => {\n try {\n // URL-encode server and tool names to handle slashes (e.g., \"com.atlassian/atlassian-mcp-server\")\n const response = await apiPost<any>(\n `/servers/${encodeURIComponent(serverName)}/tools/${encodeURIComponent(toolName)}/toggle`,\n { enabled },\n {\n headers: {\n Authorization: `Bearer ${localStorage.getItem('mcphub_token')}`,\n },\n },\n );\n\n return {\n success: response.success,\n error: response.success ? undefined : response.message,\n };\n } catch (error) {\n console.error('Error toggling tool', { serverName, toolName, enabled, error });\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n };\n }\n};\n\n/**\n * Update a tool's description for a specific server\n */\nexport const updateToolDescription = async (\n serverName: string,\n toolName: string,\n description: string,\n): Promise<{ success: boolean; error?: string }> => {\n try {\n // URL-encode server and tool names to handle slashes (e.g., \"com.atlassian/atlassian-mcp-server\")\n const response = await apiPut<any>(\n `/servers/${encodeURIComponent(serverName)}/tools/${encodeURIComponent(toolName)}/description`,\n { description },\n {\n headers: {\n Authorization: `Bearer ${localStorage.getItem('mcphub_token')}`,\n },\n },\n );\n\n return {\n success: response.success,\n error: response.success ? undefined : response.message,\n };\n } catch (error) {\n console.error('Error updating tool description', { serverName, toolName, error });\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n };\n }\n};\n\n/**\n * Reset a tool's description override for a specific server\n */\nexport const resetToolDescription = async (\n serverName: string,\n toolName: string,\n): Promise<{ success: boolean; error?: string; description?: string }> => {\n try {\n const response = await apiDelete<any>(\n `/servers/${encodeURIComponent(serverName)}/tools/${encodeURIComponent(toolName)}/description`,\n {\n headers: {\n Authorization: `Bearer ${localStorage.getItem('mcphub_token')}`,\n },\n },\n );\n\n return {\n success: response.success,\n error: response.success ? undefined : response.message,\n description: response.data?.description,\n };\n } catch (error) {\n console.error('Error resetting tool description', { serverName, toolName, error });\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n };\n }\n};\n","import React, { useState, useEffect, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { ToolInputSchema } from '@/types';\n\ninterface JsonSchema {\n type: string;\n properties?: Record<string, JsonSchema>;\n required?: string[];\n items?: JsonSchema;\n enum?: any[];\n description?: string;\n default?: any;\n}\n\ninterface DynamicFormProps {\n schema: ToolInputSchema;\n onSubmit: (values: Record<string, any>) => void;\n onCancel: () => void;\n loading?: boolean;\n storageKey?: string; // Optional key for localStorage persistence\n title?: string; // Optional title to display instead of default parameters title\n}\n\nconst DynamicForm: React.FC<DynamicFormProps> = ({\n schema,\n onSubmit,\n onCancel,\n loading = false,\n storageKey,\n title,\n}) => {\n const { t } = useTranslation();\n const [formValues, setFormValues] = useState<Record<string, any>>({});\n const [errors, setErrors] = useState<Record<string, string>>({});\n const [isJsonMode, setIsJsonMode] = useState<boolean>(false);\n const [jsonText, setJsonText] = useState<string>('');\n const [jsonError, setJsonError] = useState<string>('');\n\n // Convert ToolInputSchema to JsonSchema - memoized to prevent infinite re-renders\n const jsonSchema = useMemo(() => {\n const convertToJsonSchema = (schema: ToolInputSchema): JsonSchema => {\n const convertProperty = (prop: unknown): JsonSchema => {\n if (typeof prop === 'object' && prop !== null) {\n const obj = prop as any;\n return {\n type: obj.type || 'string',\n description: obj.description,\n enum: obj.enum,\n default: obj.default,\n properties: obj.properties\n ? Object.fromEntries(\n Object.entries(obj.properties).map(([key, value]) => [\n key,\n convertProperty(value),\n ]),\n )\n : undefined,\n required: obj.required,\n items: obj.items ? convertProperty(obj.items) : undefined,\n };\n }\n return { type: 'string' };\n };\n\n return {\n type: schema.type,\n properties: schema.properties\n ? Object.fromEntries(\n Object.entries(schema.properties).map(([key, value]) => [\n key,\n convertProperty(value),\n ]),\n )\n : undefined,\n required: schema.required,\n };\n };\n\n return convertToJsonSchema(schema);\n }, [schema]);\n\n // Initialize form values with defaults or from localStorage\n useEffect(() => {\n const initializeValues = (schema: JsonSchema, path: string = ''): Record<string, any> => {\n const values: Record<string, any> = {};\n\n if (schema.type === 'object' && schema.properties) {\n Object.entries(schema.properties).forEach(([key, propSchema]) => {\n const fullPath = path ? `${path}.${key}` : key;\n if (propSchema.default !== undefined) {\n values[key] = propSchema.default;\n } else if (propSchema.type === 'string') {\n values[key] = '';\n } else if (propSchema.type === 'number' || propSchema.type === 'integer') {\n values[key] = 0;\n } else if (propSchema.type === 'boolean') {\n values[key] = false;\n } else if (propSchema.type === 'array') {\n values[key] = [];\n } else if (propSchema.type === 'object') {\n // For objects with properties, recursively initialize\n if (propSchema.properties) {\n values[key] = initializeValues(propSchema, fullPath);\n } else {\n // For objects without properties, initialize as empty object\n values[key] = {};\n }\n }\n });\n }\n\n return values;\n };\n\n let initialValues = initializeValues(jsonSchema);\n\n // Try to load saved form data from localStorage\n if (storageKey) {\n try {\n const savedData = localStorage.getItem(storageKey);\n if (savedData) {\n const parsedData = JSON.parse(savedData);\n // Merge saved data with initial values, preserving structure\n initialValues = { ...initialValues, ...parsedData };\n }\n } catch (error) {\n console.warn('Failed to load saved form data:', error);\n }\n }\n\n setFormValues(initialValues);\n }, [jsonSchema, storageKey]);\n\n // Sync JSON text with form values when switching modes\n useEffect(() => {\n if (isJsonMode && Object.keys(formValues).length > 0) {\n setJsonText(JSON.stringify(formValues, null, 2));\n setJsonError('');\n }\n }, [isJsonMode, formValues]);\n\n const handleJsonTextChange = (text: string) => {\n setJsonText(text);\n setJsonError('');\n\n try {\n const parsedJson = JSON.parse(text);\n setFormValues(parsedJson);\n\n // Save to localStorage if storageKey is provided\n if (storageKey) {\n try {\n localStorage.setItem(storageKey, JSON.stringify(parsedJson));\n } catch (error) {\n console.warn('Failed to save form data to localStorage:', error);\n }\n }\n } catch (error) {\n setJsonError(t('tool.invalidJsonFormat'));\n }\n };\n\n const switchToJsonMode = () => {\n setJsonText(JSON.stringify(formValues, null, 2));\n setJsonError('');\n setIsJsonMode(true);\n };\n\n const switchToFormMode = () => {\n // Validate JSON before switching\n if (jsonText.trim()) {\n try {\n const parsedJson = JSON.parse(jsonText);\n setFormValues(parsedJson);\n setJsonError('');\n setIsJsonMode(false);\n } catch (error) {\n setJsonError(t('tool.fixJsonBeforeSwitching'));\n return;\n }\n } else {\n setIsJsonMode(false);\n }\n };\n\n const handleInputChange = (path: string, value: any) => {\n setFormValues((prev) => {\n const newValues = { ...prev };\n const keys = path.split('.');\n let current = newValues;\n\n for (let i = 0; i < keys.length - 1; i++) {\n if (!current[keys[i]]) {\n current[keys[i]] = {};\n }\n current = current[keys[i]];\n }\n\n current[keys[keys.length - 1]] = value;\n\n // Save to localStorage if storageKey is provided\n if (storageKey) {\n try {\n localStorage.setItem(storageKey, JSON.stringify(newValues));\n } catch (error) {\n console.warn('Failed to save form data to localStorage:', error);\n }\n }\n\n return newValues;\n });\n\n // Clear error for this field\n if (errors[path]) {\n setErrors((prev) => {\n const newErrors = { ...prev };\n delete newErrors[path];\n return newErrors;\n });\n }\n };\n const validateForm = (): boolean => {\n const newErrors: Record<string, string> = {};\n\n const validateObject = (schema: JsonSchema, values: any, path: string = '') => {\n if (schema.type === 'object' && schema.properties) {\n Object.entries(schema.properties).forEach(([key, propSchema]) => {\n const fullPath = path ? `${path}.${key}` : key;\n const value = values?.[key];\n\n // Check required fields\n if (\n schema.required?.includes(key) &&\n (value === undefined ||\n value === null ||\n value === '' ||\n (Array.isArray(value) && value.length === 0))\n ) {\n newErrors[fullPath] = `${key} is required`;\n return;\n }\n\n // Validate type\n if (value !== undefined && value !== null && value !== '') {\n if (propSchema.type === 'string' && typeof value !== 'string') {\n newErrors[fullPath] = `${key} must be a string`;\n } else if (propSchema.type === 'number' && typeof value !== 'number') {\n newErrors[fullPath] = `${key} must be a number`;\n } else if (\n propSchema.type === 'integer' &&\n (!Number.isInteger(value) || typeof value !== 'number')\n ) {\n newErrors[fullPath] = `${key} must be an integer`;\n } else if (propSchema.type === 'boolean' && typeof value !== 'boolean') {\n newErrors[fullPath] = `${key} must be a boolean`;\n } else if (propSchema.type === 'array' && Array.isArray(value)) {\n // Validate array items\n if (propSchema.items) {\n value.forEach((item: any, index: number) => {\n if (propSchema.items?.type === 'object' && propSchema.items.properties) {\n validateObject(propSchema.items, item, `${fullPath}.${index}`);\n }\n });\n }\n } else if (propSchema.type === 'object' && typeof value === 'object') {\n validateObject(propSchema, value, fullPath);\n }\n }\n });\n }\n };\n\n validateObject(jsonSchema, formValues);\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n };\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (validateForm()) {\n onSubmit(formValues);\n }\n };\n\n const getNestedValue = (obj: any, path: string): any => {\n return path.split('.').reduce((current, key) => current?.[key], obj);\n };\n\n const renderObjectField = (\n key: string,\n schema: JsonSchema,\n currentValue: any,\n onChange: (value: any) => void,\n ): React.ReactNode => {\n const value = currentValue?.[key];\n\n if (schema.type === 'string') {\n if (schema.enum) {\n return (\n <select\n value={value || ''}\n onChange={(e) => onChange(e.target.value)}\n className=\"w-full border rounded-md px-2 py-1 text-sm border-gray-300 focus:outline-none focus:ring-1 focus:ring-blue-500\"\n >\n <option value=\"\">{t('tool.selectOption')}</option>\n {schema.enum.map((option: any, idx: number) => (\n <option key={idx} value={option}>\n {option}\n </option>\n ))}\n </select>\n );\n } else {\n return (\n <input\n type=\"text\"\n value={value || ''}\n onChange={(e) => onChange(e.target.value)}\n className=\"w-full border rounded-md px-2 py-1 text-sm border-gray-300 focus:outline-none focus:ring-1 focus:ring-blue-500 form-input\"\n placeholder={schema.description || t('tool.enterKey', { key })}\n />\n );\n }\n }\n\n if (schema.type === 'number' || schema.type === 'integer') {\n return (\n <input\n type=\"number\"\n step={schema.type === 'integer' ? '1' : 'any'}\n value={value ?? ''}\n onChange={(e) => {\n const val =\n e.target.value === ''\n ? ''\n : schema.type === 'integer'\n ? parseInt(e.target.value)\n : parseFloat(e.target.value);\n onChange(val);\n }}\n className=\"w-full border rounded-md px-2 py-1 text-sm border-gray-300 focus:outline-none focus:ring-1 focus:ring-blue-500 form-input\"\n />\n );\n }\n\n if (schema.type === 'boolean') {\n return (\n <input\n type=\"checkbox\"\n checked={value || false}\n onChange={(e) => onChange(e.target.checked)}\n className=\"h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded\"\n />\n );\n }\n\n // Default to text input\n return (\n <input\n type=\"text\"\n value={value || ''}\n onChange={(e) => onChange(e.target.value)}\n className=\"w-full border rounded-md px-2 py-1 text-sm border-gray-300 focus:outline-none focus:ring-1 focus:ring-blue-500 form-input\"\n placeholder={schema.description || t('tool.enterKey', { key })}\n />\n );\n };\n\n const renderField = (key: string, propSchema: JsonSchema, path: string = ''): React.ReactNode => {\n const fullPath = path ? `${path}.${key}` : key;\n const value = getNestedValue(formValues, fullPath);\n const error = errors[fullPath]; // Handle array type\n if (propSchema.type === 'array') {\n const arrayValue = getNestedValue(formValues, fullPath) || [];\n\n return (\n <div key={fullPath} className=\"mb-6\">\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {key}\n {(path\n ? getNestedValue(jsonSchema, path)?.required?.includes(key)\n : jsonSchema.required?.includes(key)) && (\n <span className=\"text-status-red ml-1\">*</span>\n )}\n </label>\n {propSchema.description && (\n <p className=\"text-xs text-gray-500 mb-2\">{propSchema.description}</p>\n )}\n\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-md p-3 bg-gray-50 dark:bg-gray-800\">\n {arrayValue.map((item: any, index: number) => (\n <div key={index} className=\"mb-3 p-3 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-md\">\n <div className=\"flex justify-between items-center mb-2\">\n <span className=\"text-sm font-medium text-gray-600\">\n {t('tool.item', { index: index + 1 })}\n </span>\n <button\n type=\"button\"\n onClick={() => {\n const newArray = [...arrayValue];\n newArray.splice(index, 1);\n handleInputChange(fullPath, newArray);\n }}\n className=\"text-status-red hover:text-red-700 text-sm\"\n >\n {t('common.remove')}\n </button>\n </div>\n\n {propSchema.items?.type === 'string' && propSchema.items.enum ? (\n <select\n value={item || ''}\n onChange={(e) => {\n const newArray = [...arrayValue];\n newArray[index] = e.target.value;\n handleInputChange(fullPath, newArray);\n }}\n className=\"w-full border rounded-md px-3 py-2 border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n <option value=\"\">{t('tool.selectOption')}</option>\n {propSchema.items.enum.map((option: any, idx: number) => (\n <option key={idx} value={option}>\n {option}\n </option>\n ))}\n </select>\n ) : propSchema.items?.type === 'object' && propSchema.items.properties ? (\n <div className=\"space-y-3\">\n {Object.entries(propSchema.items.properties).map(([objKey, objSchema]) => (\n <div key={objKey}>\n <label className=\"block text-xs font-medium text-gray-600 mb-1\">\n {objKey}\n {propSchema.items?.required?.includes(objKey) && (\n <span className=\"text-status-red ml-1\">*</span>\n )}\n </label>\n {renderObjectField(objKey, objSchema as JsonSchema, item, (newValue) => {\n const newArray = [...arrayValue];\n newArray[index] = { ...newArray[index], [objKey]: newValue };\n handleInputChange(fullPath, newArray);\n })}\n </div>\n ))}\n </div>\n ) : (\n <input\n type=\"text\"\n value={item || ''}\n onChange={(e) => {\n const newArray = [...arrayValue];\n newArray[index] = e.target.value;\n handleInputChange(fullPath, newArray);\n }}\n className=\"w-full border rounded-md px-3 py-2 border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500 form-input\"\n placeholder={t('tool.enterValue', { type: propSchema.items?.type || 'value' })}\n />\n )}\n </div>\n ))}\n\n <button\n type=\"button\"\n onClick={() => {\n const newItem = propSchema.items?.type === 'object' ? {} : '';\n handleInputChange(fullPath, [...arrayValue, newItem]);\n }}\n className=\"w-full mt-2 px-3 py-2 text-sm text-blue-600 border border-blue-300 rounded-md hover:bg-blue-50\"\n >\n {t('tool.addItem', { key })}\n </button>\n </div>\n\n {error && <p className=\"text-status-red text-xs mt-1\">{error}</p>}\n </div>\n );\n } // Handle object type\n if (propSchema.type === 'object') {\n if (propSchema.properties) {\n // Object with defined properties - render as nested form\n return (\n <div key={fullPath} className=\"mb-6\">\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {key}\n {(path\n ? getNestedValue(jsonSchema, path)?.required?.includes(key)\n : jsonSchema.required?.includes(key)) && (\n <span className=\"text-status-red ml-1\">*</span>\n )}\n </label>\n {propSchema.description && (\n <p className=\"text-xs text-gray-500 mb-2\">{propSchema.description}</p>\n )}\n\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-md p-4 bg-gray-50 dark:bg-gray-800\">\n {Object.entries(propSchema.properties).map(([objKey, objSchema]) =>\n renderField(objKey, objSchema as JsonSchema, fullPath),\n )}\n </div>\n\n {error && <p className=\"text-status-red text-xs mt-1\">{error}</p>}\n </div>\n );\n } else {\n // Object without defined properties - render as JSON textarea\n return (\n <div key={fullPath} className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {key}\n {(path\n ? getNestedValue(jsonSchema, path)?.required?.includes(key)\n : jsonSchema.required?.includes(key)) && (\n <span className=\"text-status-red ml-1\">*</span>\n )}\n <span className=\"text-xs text-gray-500 ml-1\">(JSON object)</span>\n </label>\n {propSchema.description && (\n <p className=\"text-xs text-gray-500 mb-2\">{propSchema.description}</p>\n )}\n <textarea\n value={typeof value === 'object' ? JSON.stringify(value, null, 2) : value || '{}'}\n onChange={(e) => {\n try {\n const parsedValue = JSON.parse(e.target.value);\n handleInputChange(fullPath, parsedValue);\n } catch (err) {\n // Keep the string value if it's not valid JSON yet\n handleInputChange(fullPath, e.target.value);\n }\n }}\n placeholder={`{\\n \"key\": \"value\"\\n}`}\n className={`w-full border rounded-md px-3 py-2 font-mono text-sm ${error ? 'border-red-500' : 'border-gray-300'} focus:outline-none focus:ring-2 focus:ring-blue-500`}\n rows={4}\n />\n {error && <p className=\"text-status-red text-xs mt-1\">{error}</p>}\n </div>\n );\n }\n }\n if (propSchema.type === 'string') {\n if (propSchema.enum) {\n return (\n <div key={fullPath} className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {key}\n {(path ? false : jsonSchema.required?.includes(key)) && (\n <span className=\"text-status-red ml-1\">*</span>\n )}\n </label>\n {propSchema.description && (\n <p className=\"text-xs text-gray-500 mb-2\">{propSchema.description}</p>\n )}\n <select\n value={value || ''}\n onChange={(e) => handleInputChange(fullPath, e.target.value)}\n className={`w-full border rounded-md px-3 py-2 ${error ? 'border-red-500' : 'border-gray-300'} focus:outline-none focus:ring-2 focus:ring-blue-500`}\n >\n <option value=\"\">{t('tool.selectOption')}</option>\n {propSchema.enum.map((option, idx) => (\n <option key={idx} value={option}>\n {option}\n </option>\n ))}\n </select>\n {error && <p className=\"text-status-red text-xs mt-1\">{error}</p>}\n </div>\n );\n } else {\n return (\n <div key={fullPath} className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {key}\n {(path ? false : jsonSchema.required?.includes(key)) && (\n <span className=\"text-status-red ml-1\">*</span>\n )}\n </label>\n {propSchema.description && (\n <p className=\"text-xs text-gray-500 mb-2\">{propSchema.description}</p>\n )}\n <input\n type=\"text\"\n value={value || ''}\n onChange={(e) => handleInputChange(fullPath, e.target.value)}\n className={`w-full border rounded-md px-3 py-2 ${error ? 'border-red' : 'border-gray-200'} focus:outline-none form-input`}\n />\n {error && <p className=\"text-status-red text-xs mt-1\">{error}</p>}\n </div>\n );\n }\n }\n if (propSchema.type === 'number' || propSchema.type === 'integer') {\n return (\n <div key={fullPath} className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {key}\n {(path ? false : jsonSchema.required?.includes(key)) && (\n <span className=\"text-status-red ml-1\">*</span>\n )}\n </label>\n {propSchema.description && (\n <p className=\"text-xs text-gray-500 mb-2\">{propSchema.description}</p>\n )}\n <input\n type=\"number\"\n step={propSchema.type === 'integer' ? '1' : 'any'}\n value={value !== undefined && value !== null ? value : ''}\n onChange={(e) => {\n const val =\n e.target.value === ''\n ? ''\n : propSchema.type === 'integer'\n ? parseInt(e.target.value)\n : parseFloat(e.target.value);\n handleInputChange(fullPath, val);\n }}\n className={`w-full border rounded-md px-3 py-2 form-input ${error ? 'border-red-500' : 'border-gray-300'} focus:outline-none focus:ring-2 focus:ring-blue-500`}\n />\n {error && <p className=\"text-status-red text-xs mt-1\">{error}</p>}\n </div>\n );\n }\n\n if (propSchema.type === 'boolean') {\n return (\n <div key={fullPath} className=\"mb-4\">\n <div className=\"flex items-center\">\n <input\n type=\"checkbox\"\n checked={value || false}\n onChange={(e) => handleInputChange(fullPath, e.target.checked)}\n className=\"h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded\"\n />\n <label className=\"ml-2 block text-sm text-gray-700\">\n {key}\n {(path ? false : jsonSchema.required?.includes(key)) && (\n <span className=\"text-status-red ml-1\">*</span>\n )}\n </label>\n </div>\n {propSchema.description && (\n <p className=\"text-xs text-gray-500 mt-1\">{propSchema.description}</p>\n )}\n {error && <p className=\"text-status-red text-xs mt-1\">{error}</p>}\n </div>\n );\n } // For other types, show as text input with description\n return (\n <div key={fullPath} className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {key}\n {(path ? false : jsonSchema.required?.includes(key)) && (\n <span className=\"text-status-red ml-1\">*</span>\n )}\n <span className=\"text-xs text-gray-500 ml-1\">({propSchema.type})</span>\n </label>\n {propSchema.description && (\n <p className=\"text-xs text-gray-500 mb-2\">{propSchema.description}</p>\n )}\n <input\n type=\"text\"\n value={value || ''}\n onChange={(e) => handleInputChange(fullPath, e.target.value)}\n placeholder={t('tool.enterValue', { type: propSchema.type })}\n className={`w-full border rounded-md px-3 py-2 ${error ? 'border-red-500' : 'border-gray-300'} focus:outline-none focus:ring-2 focus:ring-blue-500 form-input`}\n />\n {error && <p className=\"text-status-red text-xs mt-1\">{error}</p>}\n </div>\n );\n };\n\n if (!jsonSchema.properties) {\n return (\n <div className=\"p-4 bg-gray-50 dark:bg-gray-800 rounded-md\">\n <p className=\"text-sm text-gray-600\">{t('tool.noParameters')}</p>\n <div className=\"flex justify-end space-x-2 mt-4\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"hub-btn\"\n >\n {t('tool.cancel')}\n </button>\n <button\n onClick={() => onSubmit({})}\n disabled={loading}\n className=\"hub-btn primary\"\n >\n {loading ? t('tool.running') : t('tool.runTool')}\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4\">\n {/* Mode Toggle */}\n <div className=\"flex justify-between items-center pb-3\">\n <h6 className=\"text-md font-medium text-gray-900\">{title}</h6>\n <div className=\"flex space-x-2\">\n <button\n type=\"button\"\n onClick={switchToFormMode}\n className={`hub-btn sm ${\n !isJsonMode ? 'primary' : ''\n }`}\n >\n {t('tool.formMode')}\n </button>\n <button\n type=\"button\"\n onClick={switchToJsonMode}\n className={`hub-btn sm ${\n isJsonMode ? 'primary' : ''\n }`}\n >\n {t('tool.jsonMode')}\n </button>\n </div>\n </div>\n\n {/* JSON Mode */}\n {isJsonMode ? (\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\n {t('tool.jsonConfiguration')}\n </label>\n <textarea\n value={jsonText}\n onChange={(e) => handleJsonTextChange(e.target.value)}\n placeholder={`{\\n \"key\": \"value\"\\n}`}\n className={`w-full h-64 border rounded-md px-3 py-2 font-mono text-sm resize-y form-input ${\n jsonError ? 'border-red-500' : 'border-gray-300'\n } focus:outline-none focus:ring-2 focus:ring-blue-500`}\n />\n {jsonError && <p className=\"text-status-red text-xs mt-1\">{jsonError}</p>}\n </div>\n\n <div className=\"flex justify-end space-x-2 pt-4\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"hub-btn sm\"\n >\n {t('tool.cancel')}\n </button>\n <button\n onClick={() => {\n try {\n const parsedJson = JSON.parse(jsonText);\n onSubmit(parsedJson);\n } catch (error) {\n setJsonError(t('tool.invalidJsonFormat'));\n }\n }}\n disabled={loading || !!jsonError}\n className=\"hub-btn sm primary\"\n >\n {loading ? t('tool.running') : t('tool.runTool')}\n </button>\n </div>\n </div>\n ) : (\n /* Form Mode */\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {Object.entries(jsonSchema.properties || {}).map(([key, propSchema]) =>\n renderField(key, propSchema),\n )}\n\n <div className=\"flex justify-end space-x-2 pt-4\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"hub-btn sm\"\n >\n {t('tool.cancel')}\n </button>\n <button\n type=\"submit\"\n disabled={loading}\n className=\"hub-btn sm primary\"\n >\n {loading ? t('tool.running') : t('tool.runTool')}\n </button>\n </div>\n </form>\n )}\n </div>\n );\n};\n\nexport default DynamicForm;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { CheckCircle, XCircle, AlertCircle } from '@/components/icons/LucideIcons';\n\ninterface ToolResultProps {\n result: {\n success: boolean;\n content?: Array<{\n type: string;\n text?: string;\n [key: string]: any;\n }>;\n error?: string;\n message?: string;\n };\n onClose: () => void;\n}\n\ntype ImagePayload = {\n data: string;\n mimeType?: string;\n};\n\nconst ToolResult: React.FC<ToolResultProps> = ({ result, onClose }) => {\n const { t } = useTranslation();\n // Extract content from data.content\n const content = result.content;\n\n const normalizeMimeType = (value?: string) => {\n if (!value) return 'image/png';\n return value.startsWith('image/') ? value : `image/${value}`;\n };\n\n const collectImagesFromValue = (value: any): ImagePayload[] => {\n if (!value) return [];\n\n if (Array.isArray(value)) {\n return value.flatMap((item) => collectImagesFromValue(item));\n }\n\n if (typeof value !== 'object') return [];\n\n const images: ImagePayload[] = [];\n\n if (value.type === 'image' && value.data) {\n images.push({\n data: String(value.data),\n mimeType: normalizeMimeType(value.mimeType || value.mime_type),\n });\n }\n\n const base64 =\n value.image_base64 ||\n value.imageBase64 ||\n value.image_data ||\n value.imageData ||\n value.base64;\n if (base64) {\n images.push({\n data: String(base64),\n mimeType: normalizeMimeType(\n value.image_mimeType || value.image_mime_type || value.mimeType || value.mime_type,\n ),\n });\n }\n\n if (value.image && typeof value.image === 'object') {\n images.push(...collectImagesFromValue(value.image));\n }\n\n if (Array.isArray(value.images)) {\n images.push(...collectImagesFromValue(value.images));\n }\n\n if (Array.isArray(value.content)) {\n images.push(...collectImagesFromValue(value.content));\n }\n\n return images;\n };\n\n const extractImagesFromText = (text: string): ImagePayload[] => {\n const images: ImagePayload[] = [];\n\n try {\n const parsed = JSON.parse(text);\n images.push(...collectImagesFromValue(parsed));\n if (images.length > 0) {\n return images;\n }\n } catch {\n // Not JSON, continue to data URI scan\n }\n\n const dataUriRegex = /data:image\\/(png|jpe?g|gif|webp);base64,([A-Za-z0-9+/=]+)/g;\n let match: RegExpExecArray | null;\n while ((match = dataUriRegex.exec(text)) !== null) {\n const mimeType = `image/${match[1] === 'jpg' ? 'jpeg' : match[1]}`;\n images.push({ data: match[2], mimeType });\n }\n\n return images;\n };\n\n const sanitizeTextForDisplay = (text: string): string => {\n try {\n const parsed = JSON.parse(text);\n const scrub = (value: any): any => {\n if (Array.isArray(value)) return value.map(scrub);\n if (value && typeof value === 'object') {\n const next: Record<string, any> = {};\n for (const [key, val] of Object.entries(value)) {\n if (typeof val === 'string' && key.toLowerCase().includes('base64')) {\n next[key] = '[base64 omitted]';\n } else {\n next[key] = scrub(val);\n }\n }\n return next;\n }\n return value;\n };\n return JSON.stringify(scrub(parsed), null, 2);\n } catch {\n return text.replace(\n /data:image\\/(png|jpe?g|gif|webp);base64,[A-Za-z0-9+/=]+/g,\n '[image data omitted]',\n );\n }\n };\n\n const renderContent = (content: any): React.ReactNode => {\n if (Array.isArray(content)) {\n return content.map((item, index) => (\n <div key={index} className=\"mb-3 last:mb-0\">\n {renderContentItem(item)}\n </div>\n ));\n }\n\n return renderContentItem(content);\n };\n\n const renderContentItem = (item: any): React.ReactNode => {\n if (typeof item === 'string') {\n const extractedImages = extractImagesFromText(item);\n const sanitizedText = sanitizeTextForDisplay(item);\n return (\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n {extractedImages.length > 0 && (\n <div className=\"mb-3 space-y-3\">\n {extractedImages.map((image, idx) => (\n <img\n key={idx}\n src={`data:${image.mimeType || 'image/png'};base64,${image.data}`}\n alt={t('tool.toolResult')}\n className=\"max-w-full h-auto rounded-md\"\n />\n ))}\n </div>\n )}\n <pre className=\"whitespace-pre-wrap text-sm text-gray-800 font-mono\">\n {sanitizedText}\n </pre>\n </div>\n );\n }\n\n if (typeof item === 'object' && item !== null) {\n if (item.type === 'text' && item.text) {\n const extractedImages = extractImagesFromText(item.text);\n const sanitizedText = sanitizeTextForDisplay(item.text);\n return (\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n {extractedImages.length > 0 && (\n <div className=\"mb-3 space-y-3\">\n {extractedImages.map((image, idx) => (\n <img\n key={idx}\n src={`data:${image.mimeType || 'image/png'};base64,${image.data}`}\n alt={t('tool.toolResult')}\n className=\"max-w-full h-auto rounded-md\"\n />\n ))}\n </div>\n )}\n <pre className=\"whitespace-pre-wrap text-sm text-gray-800 font-mono\">\n {sanitizedText}\n </pre>\n </div>\n );\n }\n\n if (item.type === 'image' && item.data) {\n return (\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n <img\n src={`data:${item.mimeType || 'image/png'};base64,${item.data}`}\n alt={t('tool.toolResult')}\n className=\"max-w-full h-auto rounded-md\"\n />\n </div>\n );\n }\n\n // For other structured content, try to parse as JSON\n try {\n const parsed = typeof item === 'string' ? JSON.parse(item) : item;\n\n return (\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n <div className=\"text-xs text-gray-500 mb-2\">{t('tool.jsonResponse')}</div>\n <pre className=\"text-sm text-gray-800 overflow-auto\">{JSON.stringify(parsed, null, 2)}</pre>\n </div>\n );\n } catch {\n // If not valid JSON, show as string\n return (\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n <pre className=\"whitespace-pre-wrap text-sm text-gray-800 font-mono\">{String(item)}</pre>\n </div>\n );\n }\n }\n\n return (\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n <pre className=\"whitespace-pre-wrap text-sm text-gray-800 font-mono\">{String(item)}</pre>\n </div>\n );\n };\n\n return (\n <div className=\"border border-gray-300 rounded-lg bg-white dark:bg-gray-800 shadow-sm\">\n <div className=\"border-b border-gray-300 px-4 py-3 bg-gray-50 dark:bg-gray-800 rounded-t-lg\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center space-x-2\">\n {result.success ? (\n <CheckCircle size={20} className=\"text-status-green\" />\n ) : (\n <XCircle size={20} className=\"text-status-red\" />\n )}\n <div>\n <h4 className=\"text-sm font-medium text-gray-900\">\n {t('tool.execution')} {result.success ? t('tool.successful') : t('tool.failed')}\n </h4>\n\n </div>\n </div>\n <button\n onClick={onClose}\n className=\"text-gray-400 hover:text-gray-600 text-sm\"\n >\n ✕\n </button>\n </div>\n </div>\n\n <div className=\"p-4\">\n {result.success ? (\n <div>\n {result.content && result.content.length > 0 ? (\n <div>\n <div className=\"text-sm text-gray-600 mb-3\">{t('tool.result')}</div>\n {renderContent(result.content)}\n </div>\n ) : (\n <div className=\"text-sm text-gray-500 italic\">\n {t('tool.noContent')}\n </div>\n )}\n </div>\n ) : (\n <div>\n <div className=\"flex items-center space-x-2 mb-3\">\n <AlertCircle size={16} className=\"text-red-500\" />\n <span className=\"text-sm font-medium text-red-700\">{t('tool.error')}</span>\n </div>\n {content && content.length > 0 ? (\n <div>\n <div className=\"text-sm text-gray-600 mb-3\">{t('tool.errorDetails')}</div>\n {renderContent(content)}\n </div>\n ) : (\n <div className=\"bg-red-50 border border-red-300 rounded-md p-3\">\n <pre className=\"text-sm text-red-800 whitespace-pre-wrap\">\n {result.error || result.message || t('tool.unknownError')}\n </pre>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default ToolResult;\n","import type { MouseEvent } from 'react';\nimport { RotateCcw } from '@/components/icons/LucideIcons';\n\ninterface ResetDescriptionButtonProps {\n title: string;\n onClick: (event: MouseEvent<HTMLButtonElement>) => void;\n disabled?: boolean;\n loading?: boolean;\n}\n\nconst ResetDescriptionButton = ({\n title,\n onClick,\n disabled = false,\n loading = false,\n}: ResetDescriptionButtonProps) => {\n return (\n <button\n type=\"button\"\n className=\"ml-2 p-1 text-amber-600 hover:text-amber-700 cursor-pointer transition-colors disabled:opacity-60 disabled:cursor-not-allowed\"\n onClick={onClick}\n disabled={disabled}\n title={title}\n aria-label={title}\n >\n <RotateCcw size={14} className={loading ? 'animate-spin' : ''} />\n </button>\n );\n};\n\nexport default ResetDescriptionButton;","import { useState, useCallback, useRef, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Tool } from '@/types';\nimport {\n ChevronDown,\n ChevronRight,\n Play,\n Loader,\n Edit,\n Check,\n Copy,\n} from '@/components/icons/LucideIcons';\nimport {\n callTool,\n ToolCallResult,\n updateToolDescription,\n resetToolDescription,\n} from '@/services/toolService';\nimport { useSettingsData } from '@/hooks/useSettingsData';\nimport { useToast } from '@/contexts/ToastContext';\nimport { Switch } from './ToggleGroup';\nimport DynamicForm from './DynamicForm';\nimport ToolResult from './ToolResult';\nimport ResetDescriptionButton from './ResetDescriptionButton';\n\ninterface ToolCardProps {\n server: string;\n tool: Tool;\n onToggle?: (toolName: string, enabled: boolean) => void;\n onDescriptionUpdate?: (\n toolName: string,\n description: string,\n options?: { restored?: boolean },\n ) => void;\n}\n\n// Helper to check for \"empty\" values\nfunction isEmptyValue(value: any): boolean {\n if (value == null) return true; // null or undefined\n if (typeof value === 'string') return value.trim() === '';\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === 'object') return Object.keys(value).length === 0;\n return false;\n}\n\nconst ToolCard = ({ tool, server, onToggle, onDescriptionUpdate }: ToolCardProps) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const { nameSeparator } = useSettingsData();\n const [isExpanded, setIsExpanded] = useState(false);\n const [showRunForm, setShowRunForm] = useState(false);\n const [isRunning, setIsRunning] = useState(false);\n const [result, setResult] = useState<ToolCallResult | null>(null);\n const [isEditingDescription, setIsEditingDescription] = useState(false);\n const [isResettingDescription, setIsResettingDescription] = useState(false);\n const [customDescription, setCustomDescription] = useState(tool.description || '');\n const descriptionInputRef = useRef<HTMLInputElement>(null);\n const descriptionTextRef = useRef<HTMLSpanElement>(null);\n const [textWidth, setTextWidth] = useState<number>(0);\n const [copiedToolName, setCopiedToolName] = useState(false);\n\n // Focus the input when editing mode is activated\n useEffect(() => {\n if (isEditingDescription && descriptionInputRef.current) {\n descriptionInputRef.current.focus();\n // Set input width to match text width\n if (textWidth > 0) {\n descriptionInputRef.current.style.width = `${textWidth + 20}px`; // Add some padding\n }\n }\n }, [isEditingDescription, textWidth]);\n\n // Measure text width when not editing\n useEffect(() => {\n if (!isEditingDescription && descriptionTextRef.current) {\n setTextWidth(descriptionTextRef.current.offsetWidth);\n }\n }, [isEditingDescription, customDescription]);\n\n useEffect(() => {\n setCustomDescription(tool.description || '');\n }, [tool.description]);\n\n // Generate a unique key for localStorage based on tool name and server\n const getStorageKey = useCallback(() => {\n return `mcphub_tool_form_${server ? `${server}_` : ''}${tool.name}`;\n }, [tool.name, server]);\n\n // Clear form data from localStorage\n const clearStoredFormData = useCallback(() => {\n localStorage.removeItem(getStorageKey());\n }, [getStorageKey]);\n\n const handleToggle = (enabled: boolean) => {\n if (onToggle) {\n onToggle(tool.name, enabled);\n }\n };\n\n const handleDescriptionEdit = () => {\n setIsEditingDescription(true);\n };\n\n const handleDescriptionSave = async () => {\n try {\n const result = await updateToolDescription(server, tool.name, customDescription);\n if (result.success) {\n setIsEditingDescription(false);\n if (onDescriptionUpdate) {\n onDescriptionUpdate(tool.name, customDescription);\n }\n } else {\n // Revert on error\n setCustomDescription(tool.description || '');\n console.error('Failed to update tool description:', result.error);\n }\n } catch (error) {\n console.error('Error updating tool description:', error);\n setCustomDescription(tool.description || '');\n setIsEditingDescription(false);\n }\n };\n\n const handleDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setCustomDescription(e.target.value);\n };\n\n const handleDescriptionReset = async () => {\n setIsResettingDescription(true);\n\n try {\n const result = await resetToolDescription(server, tool.name);\n if (result.success) {\n const restoredDescription = result.description || '';\n setCustomDescription(restoredDescription);\n setIsEditingDescription(false);\n onDescriptionUpdate?.(tool.name, restoredDescription, { restored: true });\n } else {\n showToast(result.error || t('tool.restoreDefaultFailed'), 'error');\n }\n } catch (error) {\n console.error('Error resetting tool description:', error);\n showToast(t('tool.restoreDefaultFailed'), 'error');\n } finally {\n setIsResettingDescription(false);\n }\n };\n\n const handleDescriptionKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n handleDescriptionSave();\n } else if (e.key === 'Escape') {\n setCustomDescription(tool.description || '');\n setIsEditingDescription(false);\n }\n };\n\n const handleCopyToolName = async (e: React.MouseEvent) => {\n e.stopPropagation();\n\n try {\n if (navigator.clipboard && window.isSecureContext) {\n await navigator.clipboard.writeText(tool.name);\n setCopiedToolName(true);\n showToast(t('common.copySuccess'), 'success');\n setTimeout(() => setCopiedToolName(false), 2000);\n } else {\n // Fallback for HTTP or unsupported clipboard API\n const textArea = document.createElement('textarea');\n textArea.value = tool.name;\n textArea.style.position = 'fixed';\n textArea.style.left = '-9999px';\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n try {\n document.execCommand('copy');\n setCopiedToolName(true);\n showToast(t('common.copySuccess'), 'success');\n setTimeout(() => setCopiedToolName(false), 2000);\n } catch (err) {\n showToast(t('common.copyFailed'), 'error');\n console.error('Copy to clipboard failed:', err);\n }\n document.body.removeChild(textArea);\n }\n } catch (error) {\n showToast(t('common.copyFailed'), 'error');\n console.error('Copy to clipboard failed:', error);\n }\n };\n\n const handleRunTool = async (arguments_: Record<string, any>) => {\n setIsRunning(true);\n try {\n // filter empty values\n arguments_ = Object.fromEntries(\n Object.entries(arguments_).filter(([_, v]) => !isEmptyValue(v)),\n );\n const result = await callTool(\n {\n toolName: tool.name,\n arguments: arguments_,\n },\n server,\n );\n\n setResult(result);\n // Clear form data on successful submission\n // clearStoredFormData()\n } catch (error) {\n setResult({\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n });\n } finally {\n setIsRunning(false);\n }\n };\n\n const handleCancelRun = () => {\n setShowRunForm(false);\n // Clear form data when cancelled\n clearStoredFormData();\n setResult(null);\n };\n\n const handleCloseResult = () => {\n setResult(null);\n };\n\n return (\n <div\n className=\"hub-card overflow-hidden\"\n style={{ marginBottom: 8 }}\n >\n <div\n className=\"flex justify-between items-center gap-2 px-3 py-2.5 cursor-pointer hover:bg-[var(--hub-surface-hover)] transition-colors\"\n onClick={(e) => {\n e.stopPropagation();\n setIsExpanded(!isExpanded);\n }}\n >\n <div className=\"flex-1 min-w-0 flex items-center gap-1.5 flex-wrap\">\n <span className=\"hub-mono font-medium\" style={{ fontSize: 13, color: 'var(--hub-ink)' }}>\n {tool.name.replace(server + nameSeparator, '')}\n </span>\n <button\n className=\"hub-icon-btn sm\"\n onClick={handleCopyToolName}\n title={t('common.copy')}\n >\n {copiedToolName\n ? <Check size={12} style={{ color: 'var(--hub-ok)' }} />\n : <Copy size={12} />}\n </button>\n <span className=\"flex items-center gap-1\" style={{ fontSize: 12, color: 'var(--hub-ink-3)' }}>\n {isEditingDescription ? (\n <>\n <input\n ref={descriptionInputRef}\n type=\"text\"\n className=\"hub-input\"\n style={{ height: 26, fontSize: 12, width: textWidth > 0 ? `${textWidth + 20}px` : 160, minWidth: 80 }}\n value={customDescription}\n onChange={handleDescriptionChange}\n onKeyDown={handleDescriptionKeyDown}\n onClick={(e) => e.stopPropagation()}\n />\n <button\n className=\"hub-icon-btn sm\"\n onClick={(e) => { e.stopPropagation(); handleDescriptionSave(); }}\n disabled={isResettingDescription}\n >\n <Check size={12} style={{ color: 'var(--hub-ok)' }} />\n </button>\n <ResetDescriptionButton\n title={t('tool.restoreDefault')}\n onClick={(e) => { e.stopPropagation(); handleDescriptionReset(); }}\n disabled={isResettingDescription}\n loading={isResettingDescription}\n />\n </>\n ) : (\n <>\n <span ref={descriptionTextRef}>\n {customDescription || t('tool.noDescription')}\n </span>\n <button\n className=\"hub-icon-btn sm\"\n onClick={(e) => { e.stopPropagation(); handleDescriptionEdit(); }}\n >\n <Edit size={12} />\n </button>\n <ResetDescriptionButton\n title={t('tool.restoreDefault')}\n onClick={(e) => { e.stopPropagation(); handleDescriptionReset(); }}\n disabled={isResettingDescription}\n loading={isResettingDescription}\n />\n </>\n )}\n </span>\n </div>\n <div className=\"flex items-center gap-1.5 flex-shrink-0\">\n <div onClick={(e) => e.stopPropagation()}>\n <Switch\n checked={tool.enabled ?? true}\n onCheckedChange={handleToggle}\n disabled={isRunning}\n />\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setIsExpanded(true);\n setShowRunForm(true);\n }}\n className=\"hub-btn sm\"\n style={{ color: 'var(--hub-accent)' }}\n disabled={isRunning || !tool.enabled}\n >\n {isRunning ? <Loader size={12} className=\"animate-spin\" /> : <Play size={12} />}\n <span>{isRunning ? t('tool.running') : t('tool.run')}</span>\n </button>\n <button className=\"hub-icon-btn sm\">\n {isExpanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n </button>\n </div>\n </div>\n\n {isExpanded && (\n <div style={{ borderTop: '1px solid var(--hub-line-2)', padding: '10px 12px', display: 'flex', flexDirection: 'column', gap: 10 }}>\n {/* Schema Display */}\n {!showRunForm && (\n <div style={{ background: 'var(--hub-bg-2)', borderRadius: 7, padding: '8px 12px', border: '1px solid var(--hub-line)' }}>\n <div className=\"hub-sect\" style={{ marginBottom: 6 }}>{t('tool.inputSchema')}</div>\n <pre className=\"hub-mono overflow-auto\" style={{ fontSize: 11.5, color: 'var(--hub-ink-2)', margin: 0 }}>\n {JSON.stringify(tool.inputSchema, null, 2)}\n </pre>\n </div>\n )}\n\n {/* Run Form */}\n {showRunForm && (\n <div style={{ border: '1px solid var(--hub-line)', borderRadius: 8, padding: 14 }}>\n <DynamicForm\n schema={tool.inputSchema || { type: 'object' }}\n onSubmit={handleRunTool}\n onCancel={handleCancelRun}\n loading={isRunning}\n storageKey={getStorageKey()}\n title={t('tool.runToolWithName', {\n name: tool.name.replace(server + nameSeparator, ''),\n })}\n />\n {result && (\n <div style={{ marginTop: 12 }}>\n <ToolResult result={result} onClose={handleCloseResult} />\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default ToolCard;\n","import { apiDelete, apiPost, apiPut } from '../utils/fetchInterceptor';\n\nexport interface PromptCallRequest {\n promptName: string;\n arguments?: Record<string, any>;\n}\n\nexport interface PromptCallResult {\n success: boolean;\n data?: any;\n error?: string;\n message?: string;\n}\n\n// GetPrompt result types\nexport interface GetPromptResult {\n success: boolean;\n data?: any;\n error?: string;\n}\n\n/**\n * Call a MCP prompt via the call_prompt API\n */\nexport const callPrompt = async (\n request: PromptCallRequest,\n server?: string,\n): Promise<PromptCallResult> => {\n try {\n // Construct the URL with optional server parameter\n const url = server ? `/prompts/call/${server}` : '/prompts/call';\n const response = await apiPost<any>(url, {\n promptName: request.promptName,\n arguments: request.arguments,\n });\n\n if (!response.success) {\n return {\n success: false,\n error: response.message || 'Prompt call failed',\n };\n }\n\n return {\n success: true,\n data: response.data,\n };\n } catch (error) {\n console.error('Error calling prompt', { promptName: request.promptName, server, error });\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n };\n }\n};\n\nexport const getPrompt = async (\n request: PromptCallRequest,\n server?: string,\n): Promise<GetPromptResult> => {\n try {\n // URL-encode server and prompt names to handle slashes (e.g., \"com.atlassian/atlassian-mcp-server\")\n const response = await apiPost(\n `/mcp/${encodeURIComponent(server || '')}/prompts/${encodeURIComponent(request.promptName)}`,\n {\n name: request.promptName,\n arguments: request.arguments,\n },\n );\n\n // apiPost already returns parsed data, not a Response object\n if (!response.success) {\n throw new Error(`Failed to get prompt: ${response.message || 'Unknown error'}`);\n }\n\n return {\n success: true,\n data: response.data,\n };\n } catch (error) {\n console.error('Error getting prompt', { promptName: request.promptName, server, error });\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n };\n }\n};\n\n/**\n * Toggle a prompt's enabled state for a specific server\n */\nexport const togglePrompt = async (\n serverName: string,\n promptName: string,\n enabled: boolean,\n): Promise<{ success: boolean; error?: string }> => {\n try {\n // URL-encode server and prompt names to handle slashes (e.g., \"com.atlassian/atlassian-mcp-server\")\n const response = await apiPost<any>(\n `/servers/${encodeURIComponent(serverName)}/prompts/${encodeURIComponent(promptName)}/toggle`,\n {\n enabled,\n },\n );\n\n return {\n success: response.success,\n error: response.success ? undefined : response.message,\n };\n } catch (error) {\n console.error('Error toggling prompt', { serverName, promptName, enabled, error });\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n };\n }\n};\n\n/**\n * Update a prompt's description for a specific server\n */\nexport const updatePromptDescription = async (\n serverName: string,\n promptName: string,\n description: string,\n): Promise<{ success: boolean; error?: string }> => {\n try {\n // URL-encode server and prompt names to handle slashes (e.g., \"com.atlassian/atlassian-mcp-server\")\n const response = await apiPut<any>(\n `/servers/${encodeURIComponent(serverName)}/prompts/${encodeURIComponent(promptName)}/description`,\n { description },\n {\n headers: {\n Authorization: `Bearer ${localStorage.getItem('mcphub_token')}`,\n },\n },\n );\n\n return {\n success: response.success,\n error: response.success ? undefined : response.message,\n };\n } catch (error) {\n console.error('Error updating prompt description', { serverName, promptName, error });\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n };\n }\n};\n\nexport const resetPromptDescription = async (\n serverName: string,\n promptName: string,\n): Promise<{ success: boolean; error?: string; description?: string }> => {\n try {\n const response = await apiDelete<any>(\n `/servers/${encodeURIComponent(serverName)}/prompts/${encodeURIComponent(promptName)}/description`,\n {\n headers: {\n Authorization: `Bearer ${localStorage.getItem('mcphub_token')}`,\n },\n },\n );\n\n return {\n success: response.success,\n error: response.success ? undefined : response.message,\n description: response.data?.description,\n };\n } catch (error) {\n console.error('Error resetting prompt description', { serverName, promptName, error });\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n };\n }\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { CheckCircle, XCircle, AlertCircle } from '@/components/icons/LucideIcons';\n\ninterface PromptResultProps {\n result: {\n success: boolean;\n data?: any;\n error?: string;\n message?: string;\n };\n onClose: () => void;\n}\n\nconst PromptResult: React.FC<PromptResultProps> = ({ result, onClose }) => {\n const { t } = useTranslation();\n\n const renderContent = (content: any): React.ReactNode => {\n if (typeof content === 'string') {\n return (\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n <pre className=\"whitespace-pre-wrap text-sm text-gray-800 font-mono\">{content}</pre>\n </div>\n );\n }\n\n if (typeof content === 'object' && content !== null) {\n // Handle the specific prompt data structure\n if (content.description || content.messages) {\n return (\n <div className=\"space-y-4\">\n {content.description && (\n <div>\n <h4 className=\"text-sm font-medium text-gray-900 mb-2\">{t('prompt.description')}</h4>\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n <p className=\"text-sm text-gray-800\">{content.description}</p>\n </div>\n </div>\n )}\n \n {content.messages && (\n <div>\n <h4 className=\"text-sm font-medium text-gray-900 mb-2\">{t('prompt.messages')}</h4>\n <div className=\"space-y-3\">\n {content.messages.map((message: any, index: number) => (\n <div key={index} className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n <div className=\"flex items-center mb-2\">\n <span className=\"inline-block w-16 text-xs font-medium text-gray-500\">\n {message.role}:\n </span>\n </div>\n {typeof message.content === 'string' ? (\n <pre className=\"whitespace-pre-wrap text-sm text-gray-800 font-mono\">\n {message.content}\n </pre>\n ) : typeof message.content === 'object' && message.content.type === 'text' ? (\n <pre className=\"whitespace-pre-wrap text-sm text-gray-800 font-mono\">\n {message.content.text}\n </pre>\n ) : (\n <pre className=\"text-sm text-gray-800 overflow-auto\">\n {JSON.stringify(message.content, null, 2)}\n </pre>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n }\n\n // For other structured content, try to parse as JSON\n try {\n const parsed = typeof content === 'string' ? JSON.parse(content) : content;\n\n return (\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n <div className=\"text-xs text-gray-500 mb-2\">{t('prompt.jsonResponse')}</div>\n <pre className=\"text-sm text-gray-800 overflow-auto\">{JSON.stringify(parsed, null, 2)}</pre>\n </div>\n );\n } catch {\n // If not valid JSON, show as string\n return (\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n <pre className=\"whitespace-pre-wrap text-sm text-gray-800 font-mono\">{String(content)}</pre>\n </div>\n );\n }\n }\n\n return (\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded-md p-3\">\n <pre className=\"whitespace-pre-wrap text-sm text-gray-800 font-mono\">{String(content)}</pre>\n </div>\n );\n };\n\n return (\n <div className=\"border border-gray-300 rounded-lg bg-white dark:bg-gray-800 shadow-sm\">\n <div className=\"border-b border-gray-300 px-4 py-3 bg-gray-50 dark:bg-gray-800 rounded-t-lg\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center space-x-2\">\n {result.success ? (\n <CheckCircle size={20} className=\"text-status-green\" />\n ) : (\n <XCircle size={20} className=\"text-status-red\" />\n )}\n <div>\n <h4 className=\"text-sm font-medium text-gray-900\">\n {t('prompt.execution')} {result.success ? t('prompt.successful') : t('prompt.failed')}\n </h4>\n </div>\n </div>\n <button\n onClick={onClose}\n className=\"text-gray-400 hover:text-gray-600 text-sm\"\n >\n ✕\n </button>\n </div>\n </div>\n\n <div className=\"p-4\">\n {result.success ? (\n <div>\n {result.data ? (\n <div>\n <div className=\"text-sm text-gray-600 mb-3\">{t('prompt.result')}</div>\n {renderContent(result.data)}\n </div>\n ) : (\n <div className=\"text-sm text-gray-500 italic\">\n {t('prompt.noContent')}\n </div>\n )}\n </div>\n ) : (\n <div>\n <div className=\"flex items-center space-x-2 mb-3\">\n <AlertCircle size={16} className=\"text-red-500\" />\n <span className=\"text-sm font-medium text-red-700\">{t('prompt.error')}</span>\n </div>\n <div className=\"bg-red-50 border border-red-300 rounded-md p-3\">\n <pre className=\"text-sm text-red-800 whitespace-pre-wrap\">\n {result.error || result.message || t('prompt.unknownError')}\n </pre>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default PromptResult;","import { useState, useCallback, useRef, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Prompt } from '@/types';\nimport {\n ChevronDown,\n ChevronRight,\n Play,\n Loader,\n Edit,\n Check,\n} from '@/components/icons/LucideIcons';\nimport { Switch } from './ToggleGroup';\nimport {\n getPrompt,\n updatePromptDescription,\n resetPromptDescription,\n PromptCallResult,\n} from '@/services/promptService';\nimport { useSettingsData } from '@/hooks/useSettingsData';\nimport DynamicForm from './DynamicForm';\nimport PromptResult from './PromptResult';\nimport { useToast } from '@/contexts/ToastContext';\nimport ResetDescriptionButton from './ResetDescriptionButton';\n\ninterface PromptCardProps {\n server: string;\n prompt: Prompt;\n onToggle?: (promptName: string, enabled: boolean) => void;\n onDescriptionUpdate?: (\n promptName: string,\n description: string,\n options?: { restored?: boolean },\n ) => void;\n}\n\nconst PromptCard = ({ prompt, server, onToggle, onDescriptionUpdate }: PromptCardProps) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const { nameSeparator } = useSettingsData();\n const [isExpanded, setIsExpanded] = useState(false);\n const [showRunForm, setShowRunForm] = useState(false);\n const [isRunning, setIsRunning] = useState(false);\n const [result, setResult] = useState<PromptCallResult | null>(null);\n const [isEditingDescription, setIsEditingDescription] = useState(false);\n const [isResettingDescription, setIsResettingDescription] = useState(false);\n const [customDescription, setCustomDescription] = useState(prompt.description || '');\n const descriptionInputRef = useRef<HTMLInputElement>(null);\n const descriptionTextRef = useRef<HTMLSpanElement>(null);\n const [textWidth, setTextWidth] = useState<number>(0);\n\n // Focus the input when editing mode is activated\n useEffect(() => {\n if (isEditingDescription && descriptionInputRef.current) {\n descriptionInputRef.current.focus();\n // Set input width to match text width\n if (textWidth > 0) {\n descriptionInputRef.current.style.width = `${textWidth + 20}px`; // Add some padding\n }\n }\n }, [isEditingDescription, textWidth]);\n\n // Measure text width when not editing\n useEffect(() => {\n if (!isEditingDescription && descriptionTextRef.current) {\n setTextWidth(descriptionTextRef.current.offsetWidth);\n }\n }, [isEditingDescription, customDescription]);\n\n useEffect(() => {\n setCustomDescription(prompt.description || '');\n }, [prompt.description]);\n\n // Generate a unique key for localStorage based on prompt name and server\n const getStorageKey = useCallback(() => {\n return `mcphub_prompt_form_${server ? `${server}_` : ''}${prompt.name}`;\n }, [prompt.name, server]);\n\n // Clear form data from localStorage\n const clearStoredFormData = useCallback(() => {\n localStorage.removeItem(getStorageKey());\n }, [getStorageKey]);\n\n const handleToggle = (enabled: boolean) => {\n if (onToggle) {\n onToggle(prompt.name, enabled);\n }\n };\n\n const handleDescriptionEdit = () => {\n setIsEditingDescription(true);\n };\n\n const handleDescriptionSave = async () => {\n setIsEditingDescription(false);\n try {\n const result = await updatePromptDescription(server, prompt.name, customDescription);\n if (result.success) {\n if (onDescriptionUpdate) {\n onDescriptionUpdate(prompt.name, customDescription);\n }\n } else {\n showToast(result.error || t('prompt.descriptionUpdateFailed'), 'error');\n // Revert to original description on failure\n setCustomDescription(prompt.description || '');\n }\n } catch (error) {\n console.error('Error updating prompt description:', error);\n showToast(t('prompt.descriptionUpdateFailed'), 'error');\n // Revert to original description on failure\n setCustomDescription(prompt.description || '');\n }\n };\n\n const handleDescriptionReset = async () => {\n setIsResettingDescription(true);\n\n try {\n const result = await resetPromptDescription(server, prompt.name);\n if (result.success) {\n const restoredDescription = result.description || '';\n setCustomDescription(restoredDescription);\n setIsEditingDescription(false);\n onDescriptionUpdate?.(prompt.name, restoredDescription, { restored: true });\n } else {\n showToast(result.error || t('prompt.restoreDefaultFailed'), 'error');\n }\n } catch (error) {\n console.error('Error resetting prompt description:', error);\n showToast(t('prompt.restoreDefaultFailed'), 'error');\n } finally {\n setIsResettingDescription(false);\n }\n };\n\n const handleDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setCustomDescription(e.target.value);\n };\n\n const handleDescriptionKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n handleDescriptionSave();\n } else if (e.key === 'Escape') {\n setCustomDescription(prompt.description || '');\n setIsEditingDescription(false);\n }\n };\n\n const handleGetPrompt = async (arguments_: Record<string, any>) => {\n setIsRunning(true);\n try {\n const result = await getPrompt({ promptName: prompt.name, arguments: arguments_ }, server);\n console.log('GetPrompt result:', result);\n setResult({\n success: result.success,\n data: result.data,\n error: result.error,\n });\n // Clear form data on successful submission\n // clearStoredFormData()\n } catch (error) {\n setResult({\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n });\n } finally {\n setIsRunning(false);\n }\n };\n\n const handleCancelRun = () => {\n setShowRunForm(false);\n // Clear form data when cancelled\n clearStoredFormData();\n setResult(null);\n };\n\n const handleCloseResult = () => {\n setResult(null);\n };\n\n // Convert prompt arguments to ToolInputSchema format for DynamicForm\n const convertToSchema = () => {\n if (!prompt.arguments || prompt.arguments.length === 0) {\n return { type: 'object', properties: {}, required: [] };\n }\n\n const properties: Record<string, any> = {};\n const required: string[] = [];\n\n prompt.arguments.forEach((arg) => {\n properties[arg.name] = {\n type: 'string', // Default to string for prompts\n description: arg.description || '',\n };\n\n if (arg.required) {\n required.push(arg.name);\n }\n });\n\n return {\n type: 'object',\n properties,\n required,\n };\n };\n\n return (\n <div\n className=\"hub-card overflow-hidden\"\n style={{ marginBottom: 8 }}\n >\n <div\n className=\"flex justify-between items-center gap-2 px-3 py-2.5 cursor-pointer hover:bg-[var(--hub-surface-hover)] transition-colors\"\n onClick={() => setIsExpanded(!isExpanded)}\n >\n <div className=\"flex-1 min-w-0 flex items-center gap-1.5 flex-wrap\">\n <span className=\"hub-mono font-medium\" style={{ fontSize: 13, color: 'var(--hub-ink)' }}>\n {prompt.name.replace(server + nameSeparator, '')}\n </span>\n {prompt.title && (\n <span style={{ fontSize: 12, color: 'var(--hub-ink-2)' }}>{prompt.title}</span>\n )}\n <span className=\"flex items-center gap-1\" style={{ fontSize: 12, color: 'var(--hub-ink-3)' }}>\n {isEditingDescription ? (\n <>\n <input\n ref={descriptionInputRef}\n type=\"text\"\n className=\"hub-input\"\n style={{ height: 26, fontSize: 12, width: textWidth > 0 ? `${textWidth + 20}px` : 160, minWidth: 80 }}\n value={customDescription}\n onChange={handleDescriptionChange}\n onKeyDown={handleDescriptionKeyDown}\n onClick={(e) => e.stopPropagation()}\n />\n <button\n className=\"hub-icon-btn sm\"\n onClick={(e) => { e.stopPropagation(); handleDescriptionSave(); }}\n disabled={isResettingDescription}\n >\n <Check size={12} style={{ color: 'var(--hub-ok)' }} />\n </button>\n <ResetDescriptionButton\n title={t('prompt.restoreDefault')}\n onClick={(e) => { e.stopPropagation(); handleDescriptionReset(); }}\n disabled={isResettingDescription}\n loading={isResettingDescription}\n />\n </>\n ) : (\n <>\n <span ref={descriptionTextRef}>\n {customDescription || t('tool.noDescription')}\n </span>\n <button\n className=\"hub-icon-btn sm\"\n onClick={(e) => { e.stopPropagation(); handleDescriptionEdit(); }}\n >\n <Edit size={12} />\n </button>\n <ResetDescriptionButton\n title={t('prompt.restoreDefault')}\n onClick={(e) => { e.stopPropagation(); handleDescriptionReset(); }}\n disabled={isResettingDescription}\n loading={isResettingDescription}\n />\n </>\n )}\n </span>\n </div>\n <div className=\"flex items-center gap-1.5 flex-shrink-0\">\n <div onClick={(e) => e.stopPropagation()}>\n {prompt.enabled !== undefined && (\n <Switch\n checked={prompt.enabled}\n onCheckedChange={handleToggle}\n disabled={isRunning}\n />\n )}\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setIsExpanded(true);\n setShowRunForm(true);\n }}\n className=\"hub-btn sm\"\n style={{ color: 'var(--hub-accent)' }}\n disabled={isRunning || !prompt.enabled}\n >\n {isRunning ? <Loader size={12} className=\"animate-spin\" /> : <Play size={12} />}\n <span>{isRunning ? t('tool.running') : t('tool.run')}</span>\n </button>\n <button className=\"hub-icon-btn sm\">\n {isExpanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n </button>\n </div>\n </div>\n\n {isExpanded && (\n <div style={{ borderTop: '1px solid var(--hub-line-2)', padding: '10px 12px', display: 'flex', flexDirection: 'column', gap: 10 }}>\n {/* Run Form */}\n {showRunForm && (\n <div style={{ border: '1px solid var(--hub-line)', borderRadius: 8, padding: 14 }}>\n <DynamicForm\n schema={convertToSchema()}\n onSubmit={handleGetPrompt}\n onCancel={handleCancelRun}\n loading={isRunning}\n storageKey={getStorageKey()}\n title={t('prompt.runPromptWithName', {\n name: prompt.name.replace(server + nameSeparator, ''),\n })}\n />\n {result && (\n <div style={{ marginTop: 12 }}>\n <PromptResult result={result} onClose={handleCloseResult} />\n </div>\n )}\n </div>\n )}\n\n {/* Arguments Display (when not showing form) */}\n {!showRunForm && prompt.arguments && prompt.arguments.length > 0 && (\n <div style={{ background: 'var(--hub-bg-2)', borderRadius: 7, padding: '8px 12px', border: '1px solid var(--hub-line)' }}>\n <div className=\"hub-sect\" style={{ marginBottom: 6 }}>{t('tool.parameters')}</div>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n {prompt.arguments.map((arg, index) => (\n <div key={index} className=\"flex items-start gap-2\">\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-1\">\n <span className=\"hub-mono\" style={{ fontSize: 12.5, color: 'var(--hub-ink)' }}>{arg.name}</span>\n {arg.required && <span style={{ color: 'var(--hub-err)', fontSize: 12 }}>*</span>}\n </div>\n {arg.description && (\n <p style={{ fontSize: 12, color: 'var(--hub-ink-3)', margin: '2px 0 0' }}>{arg.description}</p>\n )}\n </div>\n {arg.title && (\n <span style={{ fontSize: 11, color: 'var(--hub-ink-3)' }}>{arg.title}</span>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Result Display (when not showing form) */}\n {!showRunForm && result && (\n <div>\n <PromptResult result={result} onClose={handleCloseResult} />\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default PromptCard;\n","import { useEffect, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Check, ChevronDown, ChevronRight, Edit } from '@/components/icons/LucideIcons';\nimport { Resource } from '@/types';\nimport { Switch } from './ToggleGroup';\nimport ResetDescriptionButton from './ResetDescriptionButton';\n\ninterface ResourceCardProps {\n resource: Resource;\n onToggle?: (resourceUri: string, enabled: boolean) => void;\n onDescriptionUpdate?: (\n resourceUri: string,\n description: string,\n options?: { restored?: boolean },\n ) => Promise<void> | void;\n}\n\nconst ResourceCard = ({ resource, onToggle, onDescriptionUpdate }: ResourceCardProps) => {\n const { t } = useTranslation();\n const [isExpanded, setIsExpanded] = useState(false);\n const [isEditingDescription, setIsEditingDescription] = useState(false);\n const [isResettingDescription, setIsResettingDescription] = useState(false);\n const [customDescription, setCustomDescription] = useState(resource.description || '');\n const descriptionInputRef = useRef<HTMLInputElement>(null);\n const descriptionTextRef = useRef<HTMLSpanElement>(null);\n const [textWidth, setTextWidth] = useState<number>(0);\n\n useEffect(() => {\n if (isEditingDescription && descriptionInputRef.current) {\n descriptionInputRef.current.focus();\n if (textWidth > 0) {\n descriptionInputRef.current.style.width = `${textWidth + 20}px`;\n }\n }\n }, [isEditingDescription, textWidth]);\n\n useEffect(() => {\n if (!isEditingDescription && descriptionTextRef.current) {\n setTextWidth(descriptionTextRef.current.offsetWidth);\n }\n }, [isEditingDescription, customDescription]);\n\n useEffect(() => {\n setCustomDescription(resource.description || '');\n }, [resource.description]);\n\n const handleToggle = (enabled: boolean) => {\n if (onToggle) {\n onToggle(resource.uri, enabled);\n }\n };\n\n const handleDescriptionSave = async () => {\n setIsEditingDescription(false);\n if (onDescriptionUpdate) {\n await onDescriptionUpdate(resource.uri, customDescription);\n }\n };\n\n const handleDescriptionReset = async () => {\n setIsResettingDescription(true);\n try {\n await onDescriptionUpdate?.(resource.uri, '', { restored: true });\n setIsEditingDescription(false);\n } finally {\n setIsResettingDescription(false);\n }\n };\n\n const handleDescriptionKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n handleDescriptionSave();\n } else if (e.key === 'Escape') {\n setCustomDescription(resource.description || '');\n setIsEditingDescription(false);\n }\n };\n\n return (\n <div\n className=\"hub-card overflow-hidden\"\n style={{ marginBottom: 8 }}\n >\n <div\n className=\"flex justify-between items-center gap-2 px-3 py-2.5 cursor-pointer hover:bg-[var(--hub-surface-hover)] transition-colors\"\n onClick={() => setIsExpanded(!isExpanded)}\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n <span className=\"hub-mono font-medium truncate\" style={{ fontSize: 13, color: 'var(--hub-ink)' }}>\n {resource.name || resource.uri}\n </span>\n <span className=\"hub-mono truncate\" style={{ fontSize: 11.5, color: 'var(--hub-ink-3)' }}>\n {resource.uri}\n </span>\n </div>\n <span className=\"flex items-center gap-1 mt-0.5\" style={{ fontSize: 12, color: 'var(--hub-ink-3)' }}>\n {isEditingDescription ? (\n <>\n <input\n ref={descriptionInputRef}\n type=\"text\"\n className=\"hub-input\"\n style={{ height: 26, fontSize: 12, width: textWidth > 0 ? `${textWidth + 20}px` : 160, minWidth: 80 }}\n value={customDescription}\n onChange={(e) => setCustomDescription(e.target.value)}\n onKeyDown={handleDescriptionKeyDown}\n onClick={(e) => e.stopPropagation()}\n />\n <button\n className=\"hub-icon-btn sm\"\n onClick={(e) => { e.stopPropagation(); handleDescriptionSave(); }}\n disabled={isResettingDescription}\n >\n <Check size={12} style={{ color: 'var(--hub-ok)' }} />\n </button>\n <ResetDescriptionButton\n title={t('builtinResources.restoreDefault')}\n onClick={(e) => { e.stopPropagation(); handleDescriptionReset(); }}\n disabled={isResettingDescription}\n loading={isResettingDescription}\n />\n </>\n ) : (\n <>\n <span ref={descriptionTextRef}>{customDescription || t('tool.noDescription')}</span>\n <button\n className=\"hub-icon-btn sm\"\n onClick={(e) => { e.stopPropagation(); setIsEditingDescription(true); }}\n >\n <Edit size={12} />\n </button>\n <ResetDescriptionButton\n title={t('builtinResources.restoreDefault')}\n onClick={(e) => { e.stopPropagation(); handleDescriptionReset(); }}\n disabled={isResettingDescription}\n loading={isResettingDescription}\n />\n </>\n )}\n </span>\n </div>\n\n <div className=\"flex items-center gap-1.5 flex-shrink-0\">\n <div onClick={(e) => e.stopPropagation()}>\n <Switch checked={resource.enabled !== false} onCheckedChange={handleToggle} />\n </div>\n <button className=\"hub-icon-btn sm\">\n {isExpanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n </button>\n </div>\n </div>\n\n {isExpanded && (\n <div style={{ borderTop: '1px solid var(--hub-line-2)', padding: '8px 12px' }}>\n <span className=\"hub-sect\">{t('builtinResources.mimeType')}:</span>{' '}\n <span style={{ fontSize: 12, color: 'var(--hub-ink-2)' }}>{resource.mimeType || 'text/plain'}</span>\n </div>\n )}\n </div>\n );\n};\n\nexport default ResourceCard;\n","import { useState, useRef, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n ChevronRight,\n AlertCircle,\n Copy,\n Check,\n RefreshCw,\n Wrench,\n MessageSquare,\n FileText,\n MoreHorizontal,\n X,\n Edit3,\n Trash2,\n} from 'lucide-react';\nimport { Server } from '@/types';\nimport { ServerStatusDot } from '@/components/ui/StatusDot';\nimport ToolCard from '@/components/ui/ToolCard';\nimport PromptCard from '@/components/ui/PromptCard';\nimport ResourceCard from '@/components/ui/ResourceCard';\nimport DeleteDialog from '@/components/ui/DeleteDialog';\nimport { useToast } from '@/contexts/ToastContext';\nimport { useSettingsData } from '@/hooks/useSettingsData';\n\ninterface ServerCardProps {\n server: Server;\n onRemove: (serverName: string) => void;\n onEdit: (server: Server) => void;\n onToggle?: (server: Server, enabled: boolean) => Promise<boolean>;\n onRefresh?: () => void;\n onReload?: (server: Server) => Promise<boolean>;\n}\n\nconst transportLabel = (t: any, type?: string) => {\n if (!type) return null;\n if (type === 'stdio') return t('server.typeStdio') || 'stdio';\n if (type === 'sse') return t('server.typeSse') || 'sse';\n if (type === 'streamable-http') return t('server.typeStreamableHttp') || 'http';\n if (type === 'openapi') return t('server.typeOpenapi') || 'openapi';\n return type;\n};\n\nconst ServerCard = ({ server, onRemove, onEdit, onToggle, onRefresh, onReload }: ServerCardProps) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const { exportMCPSettings, installConfig } = useSettingsData();\n const baseUrl = installConfig?.baseUrl?.replace(/\\/+$/, '') || '';\n\n const [expanded, setExpanded] = useState(false);\n const [expandedTab, setExpandedTab] = useState<'tools' | 'prompts' | 'resources' | null>(null);\n const [showDeleteDialog, setShowDeleteDialog] = useState(false);\n const [isToggling, setIsToggling] = useState(false);\n const [isReloading, setIsReloading] = useState(false);\n const [showMenu, setShowMenu] = useState(false);\n const [showErrorPopover, setShowErrorPopover] = useState(false);\n const [copiedError, setCopiedError] = useState(false);\n const menuRef = useRef<HTMLDivElement>(null);\n const errorPopoverRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) setShowMenu(false);\n if (errorPopoverRef.current && !errorPopoverRef.current.contains(event.target as Node))\n setShowErrorPopover(false);\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n const totalTools = server.tools?.length || 0;\n const enabledTools = server.tools?.filter((tool) => tool.enabled !== false).length || 0;\n const totalPrompts = server.prompts?.length || 0;\n const enabledPrompts = server.prompts?.filter((p) => p.enabled !== false).length || 0;\n const totalResources = server.resources?.length || 0;\n const enabledResources = server.resources?.filter((r) => r.enabled !== false).length || 0;\n\n const handleToggle = async (e: React.MouseEvent) => {\n e.stopPropagation();\n if (isToggling || !onToggle) return;\n setIsToggling(true);\n try {\n await onToggle(server, !(server.enabled !== false));\n } finally {\n setIsToggling(false);\n }\n };\n\n const handleReload = async (e: React.MouseEvent) => {\n e.stopPropagation();\n setShowMenu(false);\n if (isReloading || !onReload) return;\n setIsReloading(true);\n try {\n const success = await onReload(server);\n if (success) {\n showToast(t('server.reloadSuccess') || 'Server reloaded successfully', 'success');\n } else {\n showToast(t('server.reloadError', { serverName: server.name }) || 'Failed to reload', 'error');\n }\n } finally {\n setIsReloading(false);\n }\n };\n\n const copyText = async (value: string) => {\n try {\n if (navigator.clipboard && window.isSecureContext) {\n await navigator.clipboard.writeText(value);\n return true;\n }\n } catch {\n /* noop */\n }\n try {\n const el = document.createElement('textarea');\n el.value = value;\n el.style.position = 'fixed';\n el.style.left = '-9999px';\n document.body.appendChild(el);\n el.focus();\n el.select();\n const ok = document.execCommand('copy');\n document.body.removeChild(el);\n return ok;\n } catch {\n return false;\n }\n };\n\n const handleCopyError = async (e: React.MouseEvent) => {\n e.stopPropagation();\n if (!server.error) return;\n const ok = await copyText(server.error);\n if (ok) {\n setCopiedError(true);\n showToast(t('common.copySuccess') || 'Copied', 'success');\n setTimeout(() => setCopiedError(false), 1500);\n } else {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n }\n };\n\n const handleCopyConfig = async (e: React.MouseEvent) => {\n e.stopPropagation();\n setShowMenu(false);\n try {\n const result = await exportMCPSettings(server.name);\n if (!result || !result.success || !result.data) {\n showToast(result?.message || t('common.copyFailed') || 'Copy failed', 'error');\n return;\n }\n const json = JSON.stringify(result.data, null, 2);\n const ok = await copyText(json);\n showToast(\n ok ? t('common.copySuccess') || 'Copied' : t('common.copyFailed') || 'Copy failed',\n ok ? 'success' : 'error',\n );\n } catch (error) {\n console.error('Error copying server configuration:', error);\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n }\n };\n\n const handleOAuth = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (server.oauth?.authorizationUrl) {\n const w = 600;\n const h = 700;\n const left = window.screen.width / 2 - w / 2;\n const top = window.screen.height / 2 - h / 2;\n window.open(server.oauth.authorizationUrl, 'OAuth Authorization', `width=${w},height=${h},left=${left},top=${top}`);\n showToast(t('status.oauthWindowOpened'), 'info');\n }\n };\n\n const handleToolToggle = async (toolName: string, enabled: boolean) => {\n try {\n const { toggleTool } = await import('@/services/toolService');\n const result = await toggleTool(server.name, toolName, enabled);\n if (result.success) {\n showToast(t(enabled ? 'tool.enableSuccess' : 'tool.disableSuccess', { name: toolName }), 'success');\n onRefresh?.();\n } else {\n showToast(result.error || t('tool.toggleFailed'), 'error');\n }\n } catch (err) {\n console.error(err);\n showToast(t('tool.toggleFailed'), 'error');\n }\n };\n\n const handlePromptToggle = async (promptName: string, enabled: boolean) => {\n try {\n const { togglePrompt } = await import('@/services/promptService');\n const result = await togglePrompt(server.name, promptName, enabled);\n if (result.success) {\n showToast(t(enabled ? 'tool.enableSuccess' : 'tool.disableSuccess', { name: promptName }), 'success');\n onRefresh?.();\n } else {\n showToast(result.error || t('tool.toggleFailed'), 'error');\n }\n } catch (err) {\n console.error(err);\n showToast(t('tool.toggleFailed'), 'error');\n }\n };\n\n const handleResourceToggle = async (resourceUri: string, enabled: boolean) => {\n try {\n const { toggleResource } = await import('@/services/resourceService');\n const result = await toggleResource(server.name, resourceUri, enabled);\n if (result.success) {\n showToast(t(enabled ? 'tool.enableSuccess' : 'tool.disableSuccess', { name: resourceUri }), 'success');\n onRefresh?.();\n } else {\n showToast(result.error || t('tool.toggleFailed'), 'error');\n }\n } catch (err) {\n console.error(err);\n showToast(t('tool.toggleFailed'), 'error');\n }\n };\n\n const handleToolDescriptionUpdate = (_name: string, _desc: string, options?: { restored?: boolean }) => {\n showToast(\n options?.restored ? t('tool.restoreDefaultSuccess') : t('tool.descriptionUpdateSuccess'),\n 'success',\n );\n onRefresh?.();\n };\n\n const handlePromptDescriptionUpdate = (_name: string, _desc: string, options?: { restored?: boolean }) => {\n showToast(\n options?.restored ? t('prompt.restoreDefaultSuccess') : t('prompt.descriptionUpdateSuccess'),\n 'success',\n );\n onRefresh?.();\n };\n\n const handleResourceDescriptionUpdate = async (\n resourceUri: string,\n description: string,\n options?: { restored?: boolean },\n ) => {\n try {\n const { updateResourceDescription, resetResourceDescription } = await import(\n '@/services/resourceService'\n );\n const result = options?.restored\n ? await resetResourceDescription(server.name, resourceUri)\n : await updateResourceDescription(server.name, resourceUri, description);\n if (result.success) {\n showToast(\n options?.restored\n ? t('builtinResources.restoreDefaultSuccess')\n : t('builtinResources.descriptionUpdateSuccess'),\n 'success',\n );\n onRefresh?.();\n } else {\n showToast(\n result.error ||\n (options?.restored\n ? t('builtinResources.restoreDefaultFailed')\n : t('builtinResources.descriptionUpdateFailed')),\n 'error',\n );\n }\n } catch (err) {\n console.error(err);\n showToast(\n options?.restored\n ? t('builtinResources.restoreDefaultFailed')\n : t('builtinResources.descriptionUpdateFailed'),\n 'error',\n );\n }\n };\n\n // Derive the launch command/URL for the technical display.\n const launchCmd = (() => {\n const c = server.config;\n if (!c) return '';\n if (c.url) return c.url;\n const parts: string[] = [];\n if (c.command) parts.push(c.command);\n if (c.args?.length) parts.push(...c.args);\n return parts.join(' ');\n })();\n\n const enabled = server.enabled !== false;\n const serverEndpoint = `${baseUrl}/mcp/${server.name}`;\n\n return (\n <>\n <div\n className=\"hub-card overflow-visible\"\n style={{ marginBottom: 10, opacity: enabled ? 1 : 0.7 }}\n >\n {/* Main row */}\n <div\n className=\"grid items-center gap-3 px-4 py-3 cursor-pointer hover:bg-[var(--hub-surface-hover)] transition-colors\"\n style={{ gridTemplateColumns: 'minmax(220px,1.6fr) 130px 90px 140px 80px 36px' }}\n onClick={() => setExpanded(!expanded)}\n >\n {/* Name + description */}\n <div className=\"flex items-center gap-2.5 min-w-0\">\n <ChevronRight\n size={12}\n style={{\n color: 'var(--hub-ink-3)',\n transform: expanded ? 'rotate(90deg)' : 'none',\n transition: 'transform 0.15s',\n flexShrink: 0,\n }}\n />\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span\n className=\"hub-mono truncate\"\n style={{\n fontSize: 13.5,\n color: enabled ? 'var(--hub-ink)' : 'var(--hub-ink-3)',\n }}\n >\n {server.name}\n </span>\n {server.error && (\n <div className=\"relative\" ref={errorPopoverRef}>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setShowErrorPopover((v) => !v);\n }}\n className=\"text-[var(--hub-err)] hover:opacity-80\"\n aria-label={t('server.viewErrorDetails')}\n >\n <AlertCircle size={14} />\n </button>\n {showErrorPopover && (\n <div\n className=\"absolute z-20 mt-1.5 hub-card\"\n style={{\n left: 0,\n top: '100%',\n width: 460,\n maxHeight: 320,\n overflow: 'hidden',\n boxShadow: '0 8px 24px rgba(0,0,0,0.08)',\n }}\n onClick={(e) => e.stopPropagation()}\n >\n <div\n className=\"flex items-center justify-between px-3 py-2\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <div className=\"flex items-center gap-2\">\n <span\n className=\"text-[12px] font-medium\"\n style={{ color: 'var(--hub-err)' }}\n >\n {t('server.errorDetails')}\n </span>\n <button\n onClick={handleCopyError}\n className=\"hub-icon-btn sm\"\n title={t('common.copy')}\n >\n {copiedError ? (\n <Check size={12} className=\"text-[var(--hub-ok)]\" />\n ) : (\n <Copy size={12} />\n )}\n </button>\n </div>\n <button\n onClick={() => setShowErrorPopover(false)}\n className=\"hub-icon-btn sm\"\n aria-label={t('app.closeButton')}\n >\n <X size={12} />\n </button>\n </div>\n <div\n className=\"p-3 overflow-auto hub-mono\"\n style={{ maxHeight: 260, fontSize: 12 }}\n >\n <pre className=\"whitespace-pre-wrap break-words m-0\" style={{ color: 'var(--hub-ink-2)' }}>\n {server.error}\n </pre>\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n {server.config?.description && (\n <div\n className=\"text-[11.5px] truncate\"\n style={{ color: 'var(--hub-ink-3)', marginTop: 1 }}\n title={server.config.description}\n >\n {server.config.description}\n </div>\n )}\n </div>\n </div>\n\n {/* Status */}\n <div>\n <ServerStatusDot status={server.status} enabled={server.enabled} onAuthClick={handleOAuth} />\n </div>\n\n {/* Transport */}\n <div>\n {server.config?.type ? (\n <span className=\"hub-tag\">{transportLabel(t, server.config.type)}</span>\n ) : (\n <span style={{ color: 'var(--hub-ink-3)', fontSize: 12 }}>—</span>\n )}\n </div>\n\n {/* Tools / Prompts / Resources counts */}\n <div\n className=\"flex items-center gap-2.5 hub-num hub-mono\"\n style={{ color: 'var(--hub-ink-2)', fontSize: 12 }}\n title={`T:${enabledTools}/${totalTools} · P:${enabledPrompts}/${totalPrompts} · R:${enabledResources}/${totalResources}`}\n >\n <span className=\"flex items-center gap-0.5\">\n <Wrench size={11} style={{ color: 'var(--hub-ink-3)', flexShrink: 0 }} />\n <span>{totalTools === 0 ? '0' : `${enabledTools}/${totalTools}`}</span>\n </span>\n <span className=\"flex items-center gap-0.5\">\n <MessageSquare size={11} style={{ color: 'var(--hub-ink-3)', flexShrink: 0 }} />\n <span>{totalPrompts === 0 ? '0' : `${enabledPrompts}/${totalPrompts}`}</span>\n </span>\n <span className=\"flex items-center gap-0.5\">\n <FileText size={11} style={{ color: 'var(--hub-ink-3)', flexShrink: 0 }} />\n <span>{totalResources === 0 ? '0' : `${enabledResources}/${totalResources}`}</span>\n </span>\n </div>\n\n {/* Toggle switch */}\n <div className=\"flex items-center justify-center\">\n <button\n type=\"button\"\n className={'hub-switch' + (enabled ? ' on' : '')}\n onClick={handleToggle}\n disabled={isToggling}\n aria-label={enabled ? t('server.disable') : t('server.enable')}\n />\n </div>\n\n {/* Menu */}\n <div className=\"relative\" ref={menuRef}>\n <button\n className=\"hub-icon-btn\"\n onClick={(e) => {\n e.stopPropagation();\n setShowMenu((v) => !v);\n }}\n aria-label=\"More\"\n >\n <MoreHorizontal size={14} />\n </button>\n {showMenu && (\n <div\n className=\"absolute right-0 top-full mt-1 z-20 hub-card\"\n style={{ minWidth: 160, padding: 4 }}\n onClick={(e) => e.stopPropagation()}\n >\n <button\n onClick={(e) => {\n e.stopPropagation();\n setShowMenu(false);\n onEdit(server);\n }}\n className=\"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left\"\n style={{ color: 'var(--hub-ink)' }}\n >\n <Edit3 size={13} /> {t('server.edit')}\n </button>\n <button\n onClick={handleCopyConfig}\n className=\"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left\"\n style={{ color: 'var(--hub-ink)' }}\n >\n <Copy size={13} /> {t('server.copy')}\n </button>\n {onReload && (\n <button\n onClick={handleReload}\n disabled={isReloading || isToggling || !enabled}\n className=\"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left disabled:opacity-50 disabled:cursor-not-allowed\"\n style={{ color: 'var(--hub-ink)' }}\n >\n <RefreshCw size={13} /> {t('server.reload')}\n </button>\n )}\n <div style={{ height: 1, background: 'var(--hub-line-2)', margin: '4px 0' }} />\n <button\n onClick={(e) => {\n e.stopPropagation();\n setShowMenu(false);\n setShowDeleteDialog(true);\n }}\n className=\"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left\"\n style={{ color: 'var(--hub-err)' }}\n >\n <Trash2 size={13} /> {t('server.delete')}\n </button>\n </div>\n )}\n </div>\n </div>\n\n {/* Expanded detail */}\n {expanded && (\n <div\n style={{\n borderTop: '1px solid var(--hub-line-2)',\n background: 'var(--hub-bg-2)',\n padding: '14px 16px 16px 38px',\n }}\n >\n {/* Capability tabs + endpoint on same row */}\n <div className=\"flex items-center gap-1 mb-2\">\n {[\n {\n key: 'tools' as const,\n icon: <Wrench size={12} />,\n label: t('server.tools'),\n count: totalTools,\n enabled: enabledTools,\n },\n {\n key: 'prompts' as const,\n icon: <MessageSquare size={12} />,\n label: t('server.prompts'),\n count: totalPrompts,\n enabled: enabledPrompts,\n },\n {\n key: 'resources' as const,\n icon: <FileText size={12} />,\n label: t('nav.resources'),\n count: totalResources,\n enabled: enabledResources,\n },\n ].map((tab) => {\n const active = expandedTab === tab.key;\n return (\n <button\n key={tab.key}\n onClick={() => setExpandedTab(active ? null : tab.key)}\n className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md text-[12px] transition-colors hover:bg-[var(--hub-surface-hover)]\"\n style={{\n background: active ? 'var(--hub-surface)' : 'transparent',\n border: '1px solid ' + (active ? 'var(--hub-line)' : 'transparent'),\n color: active ? 'var(--hub-ink)' : 'var(--hub-ink-2)',\n }}\n >\n {tab.icon}\n <span>{tab.label}</span>\n <span className=\"hub-mono hub-num\" style={{ color: 'var(--hub-ink-3)', fontSize: 11 }}>\n {tab.count === 0 ? '0' : `${tab.enabled}/${tab.count}`}\n </span>\n </button>\n );\n })}\n\n {/* Endpoint inline, pushed to the right */}\n <div className=\"ml-auto flex-shrink-0\">\n <div className=\"hub-endpoint\" style={{ height: 26 }}>\n <div className=\"hub-endpoint-label\">/mcp/</div>\n <div className=\"hub-endpoint-url\" title={serverEndpoint} style={{ maxWidth: 200 }}>\n {server.name}\n </div>\n <button\n type=\"button\"\n className=\"hub-endpoint-copy\"\n onClick={async (e) => {\n e.stopPropagation();\n const ok = await copyText(serverEndpoint);\n showToast(\n ok ? t('common.copySuccess') || 'Copied' : t('common.copyFailed') || 'Failed',\n ok ? 'success' : 'error',\n );\n }}\n title={t('common.copy')}\n >\n <Copy size={12} />\n </button>\n </div>\n </div>\n </div>\n\n {expandedTab === 'tools' && server.tools && (\n <div className=\"space-y-3 mt-2\">\n {server.tools.map((tool, index) => (\n <ToolCard\n key={index}\n server={server.name}\n tool={tool}\n onToggle={handleToolToggle}\n onDescriptionUpdate={handleToolDescriptionUpdate}\n />\n ))}\n </div>\n )}\n {expandedTab === 'prompts' && server.prompts && (\n <div className=\"space-y-3 mt-2\">\n {server.prompts.map((prompt, index) => (\n <PromptCard\n key={index}\n server={server.name}\n prompt={prompt}\n onToggle={handlePromptToggle}\n onDescriptionUpdate={handlePromptDescriptionUpdate}\n />\n ))}\n </div>\n )}\n {expandedTab === 'resources' && server.resources && (\n <div className=\"mt-2\">\n {server.resources.length === 0 ? (\n <div className=\"text-sm\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('builtinResources.noResources')}\n </div>\n ) : (\n <div className=\"space-y-3\">\n {server.resources.map((resource, index) => (\n <ResourceCard\n key={`${resource.uri}-${index}`}\n resource={resource}\n onToggle={handleResourceToggle}\n onDescriptionUpdate={handleResourceDescriptionUpdate}\n />\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n\n <DeleteDialog\n isOpen={showDeleteDialog}\n onClose={() => setShowDeleteDialog(false)}\n onConfirm={() => {\n onRemove(server.name);\n setShowDeleteDialog(false);\n }}\n serverName={server.name}\n />\n </>\n );\n};\n\nexport default ServerCard;\n","import { useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport ServerForm from './ServerForm'\nimport { apiPost } from '../utils/fetchInterceptor'\nimport { detectVariables } from '../utils/variableDetection'\n\ninterface AddServerFormProps {\n onAdd: () => void\n}\n\nconst AddServerForm = ({ onAdd }: AddServerFormProps) => {\n const { t } = useTranslation()\n const [modalVisible, setModalVisible] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [confirmationVisible, setConfirmationVisible] = useState(false)\n const [pendingPayload, setPendingPayload] = useState<any>(null)\n const [detectedVariables, setDetectedVariables] = useState<string[]>([])\n\n const toggleModal = () => {\n setModalVisible(!modalVisible)\n setError(null) // Clear any previous errors when toggling modal\n setConfirmationVisible(false) // Close confirmation dialog\n setPendingPayload(null) // Clear pending payload\n }\n\n const handleConfirmSubmit = async () => {\n if (pendingPayload) {\n await submitServer(pendingPayload)\n setConfirmationVisible(false)\n setPendingPayload(null)\n }\n }\n\n const submitServer = async (payload: any) => {\n try {\n setError(null)\n const result = await apiPost('/servers', payload)\n\n if (!result.success) {\n // Use specific error message from the response if available\n if (result && result.message) {\n setError(result.message)\n } else {\n setError(t('server.addError'))\n }\n return\n }\n\n setModalVisible(false)\n onAdd()\n } catch (err) {\n console.error('Error adding server:', err)\n\n // Use friendly error messages based on error type\n if (!navigator.onLine) {\n setError(t('errors.network'))\n } else if (err instanceof TypeError && (\n err.message.includes('NetworkError') ||\n err.message.includes('Failed to fetch')\n )) {\n setError(t('errors.serverConnection'))\n } else {\n setError(t('errors.serverAdd'))\n }\n }\n }\n\n const handleSubmit = async (payload: any) => {\n try {\n // Check for variables in the payload\n const variables = detectVariables(payload)\n\n if (variables.length > 0) {\n // Show confirmation dialog\n setDetectedVariables(variables)\n setPendingPayload(payload)\n setConfirmationVisible(true)\n } else {\n // Submit directly if no variables found\n await submitServer(payload)\n }\n } catch (err) {\n console.error('Error processing server submission:', err)\n setError(t('errors.serverAdd'))\n }\n }\n\n return (\n <div>\n <button\n onClick={toggleModal}\n className=\"hub-btn primary\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-3.5 w-3.5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z\" clipRule=\"evenodd\" />\n </svg>\n {t('server.add')}\n </button>\n\n {modalVisible && (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <ServerForm\n onSubmit={handleSubmit}\n onCancel={toggleModal}\n modalTitle={t('server.addServer')}\n formError={error}\n />\n </div>\n )}\n\n {confirmationVisible && (\n <div className=\"fixed inset-0 bg-black/50 z-[60] flex items-center justify-center p-4\">\n <div className=\"hub-card p-6 w-full max-w-md\">\n <h3 className=\"text-lg font-semibold text-gray-900 mb-4\">\n {t('server.confirmVariables')}\n </h3>\n <p className=\"text-gray-600 mb-4\">\n {t('server.variablesDetected')}\n </p>\n <div className=\"bg-yellow-50 border border-yellow-200 rounded p-3 mb-4\">\n <div className=\"flex items-start\">\n <div className=\"flex-shrink-0\">\n <svg className=\"h-5 w-5 text-yellow-400\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z\" clipRule=\"evenodd\" />\n </svg>\n </div>\n <div className=\"ml-3\">\n <h4 className=\"text-sm font-medium text-yellow-800\">\n {t('server.detectedVariables')}:\n </h4>\n <ul className=\"mt-1 text-sm text-yellow-700\">\n {detectedVariables.map((variable, index) => (\n <li key={index} className=\"font-mono\">\n ${`{${variable}}`}\n </li>\n ))}\n </ul>\n </div>\n </div>\n </div>\n <p className=\"text-gray-600 text-sm mb-6\">\n {t('server.confirmVariablesMessage')}\n </p>\n <div className=\"flex justify-end space-x-3\">\n <button\n onClick={() => {\n setConfirmationVisible(false)\n setPendingPayload(null)\n }}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={handleConfirmSubmit}\n className=\"hub-btn primary\"\n >\n {t('server.confirmAndAdd')}\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default AddServerForm","import { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Server } from '@/types';\nimport { apiPut } from '../utils/fetchInterceptor';\nimport ServerForm from './ServerForm';\n\ninterface EditServerFormProps {\n server: Server;\n onEdit: () => void;\n onCancel: () => void;\n}\n\nconst EditServerForm = ({ server, onEdit, onCancel }: EditServerFormProps) => {\n const { t } = useTranslation();\n const [error, setError] = useState<string | null>(null);\n\n const handleSubmit = async (payload: any) => {\n try {\n setError(null);\n const encodedServerName = encodeURIComponent(server.name);\n\n // Check if name is being changed\n const isRenaming = payload.name && payload.name !== server.name;\n\n // Build the request body\n const requestBody = {\n config: payload.config,\n ...(isRenaming ? { newName: payload.name } : {}),\n };\n\n const result = await apiPut(`/servers/${encodedServerName}`, requestBody);\n\n if (!result.success) {\n // Use specific error message from the response if available\n if (result && result.message) {\n setError(result.message);\n } else {\n setError(t('server.updateError', { serverName: server.name }));\n }\n return;\n }\n\n onEdit();\n } catch (err) {\n console.error('Error updating server:', err);\n\n // Use friendly error messages based on error type\n if (!navigator.onLine) {\n setError(t('errors.network'));\n } else if (\n err instanceof TypeError &&\n (err.message.includes('NetworkError') || err.message.includes('Failed to fetch'))\n ) {\n setError(t('errors.serverConnection'));\n } else {\n setError(t('errors.serverUpdate', { serverName: server.name }));\n }\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <ServerForm\n onSubmit={handleSubmit}\n onCancel={onCancel}\n initialData={server}\n modalTitle={t('server.editTitle', { serverName: server.name })}\n formError={error}\n />\n </div>\n );\n};\n\nexport default EditServerForm;\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { apiPost, apiGet, apiPut, fetchWithInterceptors } from '@/utils/fetchInterceptor';\nimport { getApiUrl } from '@/utils/runtime';\nimport ConfirmDialog from '@/components/ui/ConfirmDialog';\n\ninterface McpbUploadFormProps {\n onSuccess: (serverConfig: any) => void;\n onCancel: () => void;\n}\n\ninterface McpbUploadResponse {\n success: boolean;\n data?: {\n manifest: any;\n extractDir: string;\n };\n message?: string;\n}\n\nconst McpbUploadForm: React.FC<McpbUploadFormProps> = ({ onSuccess, onCancel }) => {\n const { t } = useTranslation();\n const [isDragging, setIsDragging] = useState(false);\n const [isUploading, setIsUploading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [selectedFile, setSelectedFile] = useState<File | null>(null);\n const [showServerForm, setShowServerForm] = useState(false);\n const [manifestData, setManifestData] = useState<any>(null);\n const [extractDir, setExtractDir] = useState<string>('');\n const [showConfirmDialog, setShowConfirmDialog] = useState(false);\n const [pendingServerName, setPendingServerName] = useState<string>('');\n\n const handleDragOver = (e: React.DragEvent) => {\n e.preventDefault();\n setIsDragging(true);\n };\n\n const handleDragLeave = (e: React.DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n };\n\n const handleDrop = (e: React.DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n\n const files = e.dataTransfer.files;\n if (files.length > 0) {\n const file = files[0];\n if (file.name.endsWith('.mcpb')) {\n setSelectedFile(file);\n setError(null);\n } else {\n setError(t('mcpb.invalidFileType'));\n }\n }\n };\n\n const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (files && files.length > 0) {\n const file = files[0];\n if (file.name.endsWith('.mcpb')) {\n setSelectedFile(file);\n setError(null);\n } else {\n setError(t('mcpb.invalidFileType'));\n }\n }\n };\n\n const handleUpload = async () => {\n if (!selectedFile) {\n setError(t('mcpb.noFileSelected'));\n return;\n }\n\n setIsUploading(true);\n setError(null);\n\n try {\n const formData = new FormData();\n formData.append('mcpbFile', selectedFile);\n\n const response = await fetchWithInterceptors(getApiUrl('/mcpb/upload'), {\n method: 'POST',\n body: formData,\n });\n\n const result: McpbUploadResponse = await response.json();\n\n if (!response.ok) {\n throw new Error(result.message || `HTTP error! Status: ${response.status}`);\n }\n\n if (result.success && result.data) {\n setManifestData(result.data.manifest);\n setExtractDir(result.data.extractDir);\n setShowServerForm(true);\n } else {\n throw new Error(result.message || t('mcpb.uploadFailed'));\n }\n } catch (err) {\n console.error('MCPB upload error:', err);\n setError(err instanceof Error ? err.message : t('mcpb.uploadFailed'));\n } finally {\n setIsUploading(false);\n }\n };\n\n const handleInstallServer = async (serverName: string, forceOverride: boolean = false) => {\n setIsUploading(true);\n setError(null);\n\n try {\n // Convert MCPB manifest to MCPHub stdio server configuration\n const serverConfig = convertMcpbToMcpConfig(manifestData, extractDir, serverName);\n\n // First, check if server exists\n if (!forceOverride) {\n const checkResult = await apiGet('/servers');\n\n if (checkResult.success) {\n const existingServer = checkResult.data?.find(\n (server: any) => server.name === serverName,\n );\n\n if (existingServer) {\n // Server exists, show confirmation dialog\n setPendingServerName(serverName);\n setShowConfirmDialog(true);\n setIsUploading(false);\n return;\n }\n }\n }\n\n // Install or override the server\n let result;\n if (forceOverride) {\n result = await apiPut(`/servers/${encodeURIComponent(serverName)}`, {\n name: serverName,\n config: serverConfig,\n });\n } else {\n result = await apiPost('/servers', {\n name: serverName,\n config: serverConfig,\n });\n }\n\n if (result.success) {\n onSuccess(serverConfig);\n } else {\n throw new Error(result.message || t('mcpb.installFailed'));\n }\n } catch (err) {\n console.error('MCPB install error:', err);\n setError(err instanceof Error ? err.message : t('mcpb.installFailed'));\n setIsUploading(false);\n }\n };\n\n const handleConfirmOverride = () => {\n setShowConfirmDialog(false);\n if (pendingServerName) {\n handleInstallServer(pendingServerName, true);\n }\n };\n\n const handleCancelOverride = () => {\n setShowConfirmDialog(false);\n setPendingServerName('');\n setIsUploading(false);\n };\n\n const convertMcpbToMcpConfig = (manifest: any, extractPath: string, _serverName: string) => {\n const mcpConfig = manifest.server?.mcp_config || {};\n\n // Convert MCPB manifest to MCPHub stdio configuration\n const config: any = {\n type: 'stdio',\n command: mcpConfig.command || 'node',\n args: (mcpConfig.args || []).map((arg: string) => arg.replace('${__dirname}', extractPath)),\n };\n\n // Add environment variables if they exist\n if (mcpConfig.env && Object.keys(mcpConfig.env).length > 0) {\n config.env = { ...mcpConfig.env };\n\n // Replace ${__dirname} in environment variables\n Object.keys(config.env).forEach((key) => {\n if (typeof config.env[key] === 'string') {\n config.env[key] = config.env[key].replace('${__dirname}', extractPath);\n }\n });\n }\n\n return config;\n };\n\n if (showServerForm && manifestData) {\n return (\n <>\n <ConfirmDialog\n isOpen={showConfirmDialog}\n onClose={handleCancelOverride}\n onConfirm={handleConfirmOverride}\n title={t('mcpb.serverExistsTitle')}\n message={t('mcpb.serverExistsConfirm', { serverName: pendingServerName })}\n confirmText={t('mcpb.override')}\n cancelText={t('common.cancel')}\n variant=\"warning\"\n />\n\n <div\n className={`fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4 ${showConfirmDialog ? 'opacity-50 pointer-events-none' : ''}`}\n >\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-3xl max-h-screen overflow-y-auto\">\n <div className=\"flex justify-between items-center mb-6\">\n <h2 className=\"text-xl font-semibold text-gray-900\">{t('mcpb.installServer')}</h2>\n <button onClick={onCancel} className=\"text-gray-500 hover:text-gray-700\">\n ✕\n </button>\n </div>\n\n {error && (\n <div className=\"mb-4 bg-red-50 border-l-4 border-red-500 p-4 rounded\">\n <p className=\"text-red-700\">{error}</p>\n </div>\n )}\n\n <div className=\"space-y-6\">\n {/* Extension Info */}\n <div className=\"bg-gray-50 dark:bg-gray-800 p-4 rounded-lg\">\n <h3 className=\"font-medium text-gray-900 mb-2\">{t('mcpb.extensionInfo')}</h3>\n <div className=\"space-y-2 text-sm\">\n <div>\n <strong>{t('mcpb.name')}:</strong>{' '}\n {manifestData.display_name || manifestData.name}\n </div>\n <div>\n <strong>{t('mcpb.version')}:</strong> {manifestData.version}\n </div>\n <div>\n <strong>{t('mcpb.description')}:</strong> {manifestData.description}\n </div>\n {manifestData.author && (\n <div>\n <strong>{t('mcpb.author')}:</strong> {manifestData.author.name}\n </div>\n )}\n {manifestData.tools && manifestData.tools.length > 0 && (\n <div>\n <strong>{t('mcpb.tools')}:</strong>\n <ul className=\"list-disc list-inside ml-4\">\n {manifestData.tools.map((tool: any, index: number) => (\n <li key={index}>\n {tool.name} - {tool.description}\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n </div>\n\n {/* Server Configuration */}\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\n {t('mcpb.serverName')}\n </label>\n <input\n type=\"text\"\n id=\"serverName\"\n defaultValue={manifestData.name}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 form-input\"\n placeholder={t('mcpb.serverNamePlaceholder')}\n />\n </div>\n\n {/* Action Buttons */}\n <div className=\"flex justify-end space-x-4\">\n <button\n onClick={onCancel}\n disabled={isUploading}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={() => {\n const nameInput = document.getElementById('serverName') as HTMLInputElement;\n const serverName = nameInput?.value.trim() || manifestData.name;\n handleInstallServer(serverName);\n }}\n disabled={isUploading}\n className=\"hub-btn primary\"\n >\n {isUploading ? (\n <>\n <svg\n className=\"animate-spin h-4 w-4 mr-2\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n {t('mcpb.installing')}\n </>\n ) : (\n t('mcpb.install')\n )}\n </button>\n </div>\n </div>\n </div>\n </div>\n </>\n );\n }\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-lg\">\n <div className=\"flex justify-between items-center mb-6\">\n <h2 className=\"text-xl font-semibold text-gray-900\">{t('mcpb.uploadTitle')}</h2>\n <button onClick={onCancel} className=\"text-gray-500 hover:text-gray-700\">\n ✕\n </button>\n </div>\n\n {error && (\n <div className=\"mb-4 bg-red-50 border-l-4 border-red-500 p-4 rounded\">\n <p className=\"text-red-700\">{error}</p>\n </div>\n )}\n\n {/* File Drop Zone */}\n <div\n className={`relative border-2 border-dashed rounded-lg p-8 text-center transition-colors ${\n isDragging\n ? 'border-blue-500 bg-blue-50'\n : selectedFile\n ? 'border-gray-500 '\n : 'border-gray-300 hover:border-gray-400'\n }`}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {selectedFile ? (\n <div className=\"space-y-2\">\n <svg\n className=\"mx-auto h-12 w-12 text-green-200\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <p className=\"text-sm text-gray-900 font-medium\">{selectedFile.name}</p>\n <p className=\"text-xs text-gray-500\">\n {(selectedFile.size / 1024 / 1024).toFixed(2)} MB\n </p>\n </div>\n ) : (\n <div className=\"space-y-2\">\n <svg\n className=\"mx-auto h-12 w-12 text-gray-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"\n />\n </svg>\n <div>\n <p className=\"text-sm text-gray-900\">{t('mcpb.dropFileHere')}</p>\n <p className=\"text-xs text-gray-500\">{t('mcpb.orClickToSelect')}</p>\n </div>\n </div>\n )}\n\n <input\n type=\"file\"\n accept=\".mcpb\"\n onChange={handleFileSelect}\n className=\"absolute inset-0 w-full h-full opacity-0 cursor-pointer\"\n />\n </div>\n\n <div className=\"mt-6 flex justify-end space-x-4\">\n <button\n onClick={onCancel}\n disabled={isUploading}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={handleUpload}\n disabled={!selectedFile || isUploading}\n className=\"hub-btn primary flex items-center\"\n >\n {isUploading ? (\n <>\n <svg\n className=\"animate-spin h-4 w-4 mr-2\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n {t('mcpb.uploading')}\n </>\n ) : (\n t('mcpb.upload')\n )}\n </button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default McpbUploadForm;\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { apiPost } from '@/utils/fetchInterceptor';\n\ninterface JSONImportFormProps {\n onSuccess: () => void;\n onCancel: () => void;\n}\n\ninterface McpServerConfig {\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n type?: string;\n url?: string;\n headers?: Record<string, string>;\n openapi?: {\n version: string;\n url: string;\n };\n}\n\ninterface ImportJsonFormat {\n mcpServers: Record<string, McpServerConfig>;\n}\n\nconst JSONImportForm: React.FC<JSONImportFormProps> = ({ onSuccess, onCancel }) => {\n const { t } = useTranslation();\n const [jsonInput, setJsonInput] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [isImporting, setIsImporting] = useState(false);\n const [previewServers, setPreviewServers] = useState<Array<{ name: string; config: any }> | null>(\n null,\n );\n\n const examplePlaceholder = `{\n \"mcpServers\": {\n \"stdio-server-example\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"mcp-server-example\"]\n },\n \"sse-server-example\": {\n \"type\": \"sse\",\n \"url\": \"http://localhost:3000\"\n },\n \"http-server-example\": {\n \"type\": \"streamable-http\",\n \"url\": \"http://localhost:3001\",\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"Bearer your-token\"\n }\n },\n \"openapi-server-example\": {\n \"type\": \"openapi\",\n \"openapi\": {\n \"url\": \"https://petstore.swagger.io/v2/swagger.json\"\n }\n }\n }\n}\n\nSupports: STDIO, SSE, HTTP (streamable-http), OpenAPI\nAll servers will be imported in a single efficient batch operation.`;\n\n const parseAndValidateJson = (input: string): ImportJsonFormat | null => {\n try {\n const parsed = JSON.parse(input.trim());\n\n // Validate structure\n if (!parsed.mcpServers || typeof parsed.mcpServers !== 'object') {\n setError(t('jsonImport.invalidFormat'));\n return null;\n }\n\n return parsed as ImportJsonFormat;\n } catch (e) {\n setError(t('jsonImport.parseError'));\n return null;\n }\n };\n\n const handlePreview = () => {\n setError(null);\n const parsed = parseAndValidateJson(jsonInput);\n if (!parsed) return;\n\n const servers = Object.entries(parsed.mcpServers).map(([name, config]) => {\n // Normalize config to MCPHub format\n const normalizedConfig: any = {};\n\n if (config.type === 'sse' || config.type === 'streamable-http') {\n normalizedConfig.type = config.type;\n normalizedConfig.url = config.url;\n if (config.headers) {\n normalizedConfig.headers = config.headers;\n }\n } else if (config.type === 'openapi') {\n normalizedConfig.type = 'openapi';\n normalizedConfig.openapi = config.openapi;\n } else {\n // Default to stdio\n normalizedConfig.type = 'stdio';\n normalizedConfig.command = config.command;\n normalizedConfig.args = config.args || [];\n if (config.env) {\n normalizedConfig.env = config.env;\n }\n }\n\n return { name, config: normalizedConfig };\n });\n\n setPreviewServers(servers);\n };\n\n const handleImport = async () => {\n if (!previewServers) return;\n\n setIsImporting(true);\n setError(null);\n\n try {\n // Use batch import API for better performance\n const result = await apiPost('/servers/batch', {\n servers: previewServers,\n });\n\n if (result.success && result.data) {\n const { successCount, failureCount, results } = result.data;\n\n if (failureCount > 0) {\n const errors = results\n .filter((r: any) => !r.success)\n .map((r: any) => `${r.name}: ${r.message || t('jsonImport.addFailed')}`);\n\n setError(\n t('jsonImport.partialSuccess', { count: successCount, total: previewServers.length }) +\n '\\n' +\n errors.join('\\n'),\n );\n }\n\n if (successCount > 0) {\n onSuccess();\n }\n } else {\n setError(result.message || t('jsonImport.importFailed'));\n }\n } catch (err) {\n console.error('Import error:', err);\n setError(t('jsonImport.importFailed'));\n } finally {\n setIsImporting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto\">\n <div className=\"flex justify-between items-center mb-6\">\n <h2 className=\"text-xl font-semibold text-gray-900\">{t('jsonImport.title')}</h2>\n <button onClick={onCancel} className=\"text-gray-500 hover:text-gray-700\">\n ✕\n </button>\n </div>\n\n {error && (\n <div className=\"mb-4 bg-red-50 border-l-4 border-red-500 p-4 rounded\">\n <p className=\"text-red-700 whitespace-pre-wrap\">{error}</p>\n </div>\n )}\n\n {!previewServers ? (\n <div>\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\n {t('jsonImport.inputLabel')}\n </label>\n <textarea\n value={jsonInput}\n onChange={(e) => setJsonInput(e.target.value)}\n className=\"w-full h-96 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm\"\n placeholder={examplePlaceholder}\n />\n <p className=\"text-xs text-gray-500 mt-2\">{t('jsonImport.inputHelp')}</p>\n </div>\n\n <div className=\"flex justify-end space-x-4\">\n <button\n onClick={onCancel}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={handlePreview}\n disabled={!jsonInput.trim()}\n className=\"hub-btn primary\"\n >\n {t('jsonImport.preview')}\n </button>\n </div>\n </div>\n ) : (\n <div>\n <div className=\"mb-4\">\n <h3 className=\"text-lg font-medium text-gray-900 mb-3\">\n {t('jsonImport.previewTitle')}\n </h3>\n <div className=\"space-y-3\">\n {previewServers.map((server, index) => (\n <div key={index} className=\"bg-gray-50 dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex-1\">\n <h4 className=\"font-medium text-gray-900\">{server.name}</h4>\n <div className=\"mt-2 space-y-1 text-sm text-gray-600\">\n <div>\n <strong>{t('server.type')}:</strong> {server.config.type || 'stdio'}\n </div>\n {server.config.command && (\n <div>\n <strong>{t('server.command')}:</strong> {server.config.command}\n </div>\n )}\n {server.config.args && server.config.args.length > 0 && (\n <div>\n <strong>{t('server.arguments')}:</strong>{' '}\n {server.config.args.join(' ')}\n </div>\n )}\n {server.config.url && (\n <div>\n <strong>{t('server.url')}:</strong> {server.config.url}\n </div>\n )}\n {server.config.env && Object.keys(server.config.env).length > 0 && (\n <div>\n <strong>{t('server.envVars')}:</strong>{' '}\n {Object.keys(server.config.env).join(', ')}\n </div>\n )}\n {server.config.headers &&\n Object.keys(server.config.headers).length > 0 && (\n <div>\n <strong>{t('server.headers')}:</strong>{' '}\n {Object.keys(server.config.headers).join(', ')}\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n ))}\n </div>\n </div>\n\n <div className=\"flex justify-end space-x-4\">\n <button\n onClick={() => setPreviewServers(null)}\n disabled={isImporting}\n className=\"hub-btn\"\n >\n {t('common.back')}\n </button>\n <button\n onClick={handleImport}\n disabled={isImporting}\n className=\"hub-btn primary\"\n >\n {isImporting ? (\n <>\n <svg\n className=\"animate-spin h-4 w-4 mr-2\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n {t('jsonImport.importing')}\n </>\n ) : (\n t('jsonImport.import')\n )}\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default JSONImportForm;\n","import React, { useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router-dom';\nimport { Plus, RefreshCw, Search, Upload, FileCode, AlertCircle, X } from 'lucide-react';\nimport { Server } from '@/types';\nimport ServerCard from '@/components/ServerCard';\nimport AddServerForm from '@/components/AddServerForm';\nimport EditServerForm from '@/components/EditServerForm';\nimport McpbUploadForm from '@/components/McpbUploadForm';\nimport JSONImportForm from '@/components/JSONImportForm';\nimport Pagination from '@/components/ui/Pagination';\nimport { useServerData } from '@/hooks/useServerData';\n\ntype Filter = 'all' | 'online' | 'issues';\n\nconst ServersPage: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const {\n servers,\n allServers,\n error,\n setError,\n isLoading,\n pagination,\n currentPage,\n serversPerPage,\n setCurrentPage,\n setServersPerPage,\n handleServerAdd,\n handleServerEdit,\n handleServerRemove,\n handleServerToggle,\n handleServerReload,\n triggerRefresh,\n } = useServerData({ refreshOnMount: true });\n\n const [editingServer, setEditingServer] = useState<Server | null>(null);\n const [isRefreshing, setIsRefreshing] = useState(false);\n const [showMcpbUpload, setShowMcpbUpload] = useState(false);\n const [showJsonImport, setShowJsonImport] = useState(false);\n const [filter, setFilter] = useState<Filter>('all');\n const [search, setSearch] = useState('');\n\n const counts = useMemo(\n () => ({\n all: allServers.length,\n online: allServers.filter((s: Server) => s.status === 'connected').length,\n issues: allServers.filter(\n (s: Server) => s.status !== 'connected' && s.enabled !== false,\n ).length,\n }),\n [allServers],\n );\n\n const filteredServers = useMemo(() => {\n const q = search.trim().toLowerCase();\n return servers.filter((s) => {\n if (filter === 'online' && s.status !== 'connected') return false;\n if (filter === 'issues' && (s.status === 'connected' || s.enabled === false)) return false;\n if (!q) return true;\n const hay = (\n s.name +\n ' ' +\n (s.config?.description || '') +\n ' ' +\n (s.tools?.map((t) => t.name).join(' ') || '')\n ).toLowerCase();\n return hay.includes(q);\n });\n }, [servers, filter, search]);\n\n const handleEditClick = async (server: Server) => {\n const fullServerData = await handleServerEdit(server);\n if (fullServerData) setEditingServer(fullServerData);\n };\n\n const handleRefresh = async () => {\n setIsRefreshing(true);\n try {\n triggerRefresh();\n await new Promise((resolve) => setTimeout(resolve, 400));\n } finally {\n setIsRefreshing(false);\n }\n };\n\n return (\n <div>\n {/* Header */}\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('pages.servers.title')}</h1>\n <p className=\"hub-sub\">\n <span className=\"hub-num\">{counts.all}</span> {t('nav.servers').toLowerCase()} ·{' '}\n <span className=\"hub-num\">{counts.online}</span> {t('status.online')} ·{' '}\n <span className=\"hub-num\">{counts.issues}</span>{' '}\n {t('common.inactive') || 'issues'}\n </p>\n </div>\n <div className=\"flex gap-2\">\n <button className=\"hub-btn\" onClick={() => navigate('/market')}>\n <Plus size={13} /> {t('nav.market')}\n </button>\n <button className=\"hub-btn\" onClick={() => setShowJsonImport(true)}>\n <FileCode size={13} /> {t('jsonImport.button')}\n </button>\n <button className=\"hub-btn\" onClick={() => setShowMcpbUpload(true)}>\n <Upload size={13} /> {t('mcpb.upload')}\n </button>\n <button\n className=\"hub-btn\"\n onClick={handleRefresh}\n disabled={isRefreshing}\n aria-label={t('common.refresh')}\n >\n <RefreshCw size={13} className={isRefreshing ? 'animate-spin' : ''} />\n {t('common.refresh')}\n </button>\n <AddServerForm onAdd={handleServerAdd} />\n </div>\n </div>\n\n {error && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-4\"\n style={{\n padding: '10px 14px',\n borderColor: 'oklch(0.85 0.1 25)',\n background: 'oklch(0.97 0.03 25)',\n color: 'oklch(0.4 0.18 25)',\n }}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <AlertCircle size={14} className=\"flex-shrink-0\" />\n <span className=\"truncate text-[13px]\">{error}</span>\n </div>\n <button\n className=\"hub-icon-btn sm\"\n onClick={() => setError(null)}\n aria-label={t('app.closeButton')}\n >\n <X size={13} />\n </button>\n </div>\n )}\n\n {/* Toolbar */}\n <div className=\"flex items-center gap-2 mb-4 flex-wrap\">\n <div\n className=\"hub-card flex items-center\"\n style={{ padding: 2, borderRadius: 7, background: 'var(--hub-surface)' }}\n >\n {(\n [\n ['all', t('common.all') || 'All', counts.all],\n ['online', t('status.online'), counts.online],\n ['issues', t('common.inactive') || 'Issues', counts.issues],\n ] as [Filter, string, number][]\n ).map(([k, l, n]) => (\n <button\n key={k}\n onClick={() => setFilter(k)}\n className=\"inline-flex items-center gap-1.5 px-3 text-[12px]\"\n style={{\n height: 24,\n borderRadius: 5,\n background: filter === k ? 'var(--hub-bg-2)' : 'transparent',\n color: filter === k ? 'var(--hub-ink)' : 'var(--hub-ink-3)',\n border: '1px solid ' + (filter === k ? 'var(--hub-line)' : 'transparent'),\n }}\n >\n {l}\n <span className=\"hub-mono\" style={{ fontSize: 11, color: 'var(--hub-ink-3)' }}>\n {n}\n </span>\n </button>\n ))}\n </div>\n\n <div\n className=\"hub-card flex items-center gap-2 px-2.5 flex-1\"\n style={{ height: 30, background: 'var(--hub-surface)', maxWidth: 360 }}\n >\n <Search size={13} style={{ color: 'var(--hub-ink-3)' }} />\n <input\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"flex-1 bg-transparent outline-none text-[13px]\"\n style={{ color: 'var(--hub-ink)' }}\n placeholder={t('market.searchPlaceholder') || 'Search…'}\n />\n {search && (\n <button onClick={() => setSearch('')} className=\"hub-icon-btn sm\">\n <X size={11} />\n </button>\n )}\n </div>\n\n <div className=\"ml-auto hub-mono text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {filteredServers.length}/{servers.length}\n </div>\n </div>\n\n {/* List */}\n {isLoading && servers.length === 0 ? (\n <div className=\"hub-card p-6 flex items-center justify-center\">\n <div className=\"flex flex-col items-center gap-2\">\n <RefreshCw size={20} className=\"animate-spin\" style={{ color: 'var(--hub-ink-3)' }} />\n <p style={{ color: 'var(--hub-ink-3)' }}>{t('app.loading')}</p>\n </div>\n </div>\n ) : filteredServers.length === 0 ? (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n <p>{servers.length === 0 ? t('app.noServers') : t('market.noServers')}</p>\n </div>\n ) : (\n <>\n <div className=\"flex flex-col\">\n {filteredServers.map((server) => (\n <ServerCard\n key={server.name}\n server={server}\n onRemove={handleServerRemove}\n onEdit={handleEditClick}\n onToggle={handleServerToggle}\n onRefresh={triggerRefresh}\n onReload={handleServerReload}\n />\n ))}\n </div>\n\n <div className=\"flex items-center mt-4 text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n <div className=\"flex-[2]\">\n {pagination\n ? t('common.showing', {\n start: (pagination.page - 1) * pagination.limit + 1,\n end: Math.min(pagination.page * pagination.limit, pagination.total),\n total: pagination.total,\n })\n : t('common.showing', { start: 1, end: servers.length, total: servers.length })}\n </div>\n <div className=\"flex-[4] flex justify-center\">\n {pagination && pagination.totalPages > 1 && (\n <Pagination\n currentPage={currentPage}\n totalPages={pagination.totalPages}\n onPageChange={setCurrentPage}\n disabled={isLoading}\n />\n )}\n </div>\n <div className=\"flex-[2] flex items-center justify-end gap-2\">\n <label htmlFor=\"perPage\">{t('common.itemsPerPage')}:</label>\n <select\n id=\"perPage\"\n value={serversPerPage}\n onChange={(e) => setServersPerPage(Number(e.target.value))}\n disabled={isLoading}\n className=\"hub-input\"\n style={{ height: 26, width: 70, padding: '0 6px', fontSize: 12 }}\n >\n <option value={5}>5</option>\n <option value={10}>10</option>\n <option value={20}>20</option>\n <option value={50}>50</option>\n </select>\n </div>\n </div>\n </>\n )}\n\n {editingServer && (\n <EditServerForm\n server={editingServer}\n onEdit={() => {\n setEditingServer(null);\n triggerRefresh();\n }}\n onCancel={() => setEditingServer(null)}\n />\n )}\n {showMcpbUpload && (\n <McpbUploadForm\n onSuccess={() => {\n setShowMcpbUpload(false);\n triggerRefresh();\n }}\n onCancel={() => setShowMcpbUpload(false)}\n />\n )}\n {showJsonImport && (\n <JSONImportForm\n onSuccess={() => {\n setShowJsonImport(false);\n triggerRefresh();\n }}\n onCancel={() => setShowJsonImport(false)}\n />\n )}\n </div>\n );\n};\n\nexport default ServersPage;\n"],"file":"assets/ServersPage-DtnlfwJF.js"}