@samanhappy/mcphub 0.12.15 → 0.12.17
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.
- package/dist/config/index.js +9 -9
- package/dist/config/index.js.map +1 -1
- package/dist/controllers/oauthCallbackController.js +10 -5
- package/dist/controllers/oauthCallbackController.js.map +1 -1
- package/dist/middlewares/userContext.js +17 -2
- package/dist/middlewares/userContext.js.map +1 -1
- package/dist/server.js +2 -4
- package/dist/server.js.map +1 -1
- package/dist/services/mcpService.js +7 -2
- package/dist/services/mcpService.js.map +1 -1
- package/dist/services/sseService.js +14 -1
- package/dist/services/sseService.js.map +1 -1
- package/dist/services/vectorSearchService.js +5 -1
- package/dist/services/vectorSearchService.js.map +1 -1
- package/dist/utils/proxyTrust.js +20 -0
- package/dist/utils/proxyTrust.js.map +1 -0
- package/frontend/dist/assets/ActivityPage-ClgKeihP.js +2 -0
- package/frontend/dist/assets/ActivityPage-ClgKeihP.js.map +1 -0
- package/frontend/dist/assets/Badge-Ck2fhRdl.js +2 -0
- package/frontend/dist/assets/Badge-Ck2fhRdl.js.map +1 -0
- package/frontend/dist/assets/ConfirmDialog-uYjffH4V.js +2 -0
- package/frontend/dist/assets/ConfirmDialog-uYjffH4V.js.map +1 -0
- package/frontend/dist/assets/Dashboard-BIXrLobn.js +2 -0
- package/frontend/dist/assets/Dashboard-BIXrLobn.js.map +1 -0
- package/frontend/dist/assets/DeleteDialog-BAfrV8EB.js +2 -0
- package/frontend/dist/assets/DeleteDialog-BAfrV8EB.js.map +1 -0
- package/frontend/dist/assets/GroupsPage-BjrvyHwu.js +33 -0
- package/frontend/dist/assets/GroupsPage-BjrvyHwu.js.map +1 -0
- package/frontend/dist/assets/LoginPage-BBHt_TfF.js +2 -0
- package/frontend/dist/assets/LoginPage-BBHt_TfF.js.map +1 -0
- package/frontend/dist/assets/LogsPage-D8Znq5NB.js +2 -0
- package/frontend/dist/assets/LogsPage-D8Znq5NB.js.map +1 -0
- package/frontend/dist/assets/MarketPage-haRuzjCw.js +3 -0
- package/frontend/dist/assets/MarketPage-haRuzjCw.js.map +1 -0
- package/frontend/dist/assets/Pagination-y-gVO8ms.js +2 -0
- package/frontend/dist/assets/Pagination-y-gVO8ms.js.map +1 -0
- package/frontend/dist/assets/PromptsPage-ByHWPyGe.js +2 -0
- package/frontend/dist/assets/PromptsPage-ByHWPyGe.js.map +1 -0
- package/frontend/dist/assets/ResourcesPage-Bodw5OY9.js +2 -0
- package/frontend/dist/assets/ResourcesPage-Bodw5OY9.js.map +1 -0
- package/frontend/dist/assets/ServersPage-CtS1I4yS.js +37 -0
- package/frontend/dist/assets/ServersPage-CtS1I4yS.js.map +1 -0
- package/frontend/dist/assets/SettingsPage-DxVigf7p.js +12 -0
- package/frontend/dist/assets/SettingsPage-DxVigf7p.js.map +1 -0
- package/frontend/dist/assets/ToggleGroup-HfxdlkGi.js +2 -0
- package/frontend/dist/assets/ToggleGroup-HfxdlkGi.js.map +1 -0
- package/frontend/dist/assets/UsersPage-Bipw33cS.js +2 -0
- package/frontend/dist/assets/UsersPage-Bipw33cS.js.map +1 -0
- package/frontend/dist/assets/framework-vendor-_OBebcuv.js +61 -0
- package/frontend/dist/assets/framework-vendor-_OBebcuv.js.map +1 -0
- package/frontend/dist/assets/i18n-vendor-MQ921plD.js +2 -0
- package/frontend/dist/assets/i18n-vendor-MQ921plD.js.map +1 -0
- package/frontend/dist/assets/icons-vendor-B67NtVuR.js +172 -0
- package/frontend/dist/assets/icons-vendor-B67NtVuR.js.map +1 -0
- package/frontend/dist/assets/index-CmnA4an8.js +5 -0
- package/frontend/dist/assets/index-CmnA4an8.js.map +1 -0
- package/frontend/dist/assets/index-DfFHVARX.css +1 -0
- package/frontend/dist/assets/resourceService-BfCTSBsr.js +2 -0
- package/frontend/dist/assets/{resourceService-C3LGHhTi.js.map → resourceService-BfCTSBsr.js.map} +1 -1
- package/frontend/dist/assets/useGroupData-DLhbP6zd.js +2 -0
- package/frontend/dist/assets/useGroupData-DLhbP6zd.js.map +1 -0
- package/frontend/dist/assets/useServerData-QZqQTYcv.js +2 -0
- package/frontend/dist/assets/useServerData-QZqQTYcv.js.map +1 -0
- package/frontend/dist/assets/useSettingsData-D3VROqS7.js +2 -0
- package/frontend/dist/assets/useSettingsData-D3VROqS7.js.map +1 -0
- package/frontend/dist/assets/variableDetection-C3Xi21av.js +16 -0
- package/frontend/dist/assets/variableDetection-C3Xi21av.js.map +1 -0
- package/frontend/dist/index.html +5 -2
- package/package.json +2 -2
- package/frontend/dist/assets/index-CebeneXS.js +0 -323
- package/frontend/dist/assets/index-CebeneXS.js.map +0 -1
- package/frontend/dist/assets/index-PEyR1nSL.css +0 -1
- package/frontend/dist/assets/resourceService-C3LGHhTi.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","ServerCard","onRemove","onEdit","onRefresh","onReload","expandedTab","setExpandedTab","showDeleteDialog","setShowDeleteDialog","isToggling","setIsToggling","isReloading","setIsReloading","showErrorPopover","setShowErrorPopover","copied","setCopied","errorPopoverRef","handleClickOutside","event","exportMCPSettings","totalTools","enabledTools","totalPrompts","enabledPrompts","totalResources","enabledResources","handleRemove","handleEdit","handleReload","handleErrorIconClick","copyToClipboard","handleCopyServerConfig","configJson","handleConfirmDelete","handleToolToggle","__vitePreload","toolService","handlePromptToggle","promptService","handleToolDescriptionUpdate","_toolName","_description","options","handlePromptDescriptionUpdate","_promptName","handleOAuthAuthorization","left","top","handleResourceToggle","resourceUri","toggleResource","handleResourceDescriptionUpdate","updateResourceDescription","resetResourceDescription","StatusBadge","Wrench","MessageSquare","FileText","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","r","ServersPage","navigate","useNavigate","isLoading","pagination","currentPage","serversPerPage","setCurrentPage","setServersPerPage","handleServerAdd","handleServerEdit","handleServerRemove","handleServerToggle","handleServerReload","triggerRefresh","useServerData","editingServer","setEditingServer","isRefreshing","setIsRefreshing","showMcpbUpload","setShowMcpbUpload","showJsonImport","setShowJsonImport","handleEditClick","fullServerData","handleEditComplete","handleRefresh","resolve","handleMcpbUploadSuccess","_serverConfig","handleJsonImportSuccess","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=\"px-4 py-2 text-sm text-gray-600 bg-gray-100 dark:bg-gray-800 rounded-md hover:bg-gray-200\"\n >\n {t('tool.cancel')}\n </button>\n <button\n onClick={() => onSubmit({})}\n disabled={loading}\n className=\"px-4 py-2 text-sm text-white bg-blue-600 rounded-md hover:bg-blue-700 disabled:opacity-50\"\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={`px-3 py-1 text-sm rounded-md transition-colors ${\n !isJsonMode\n ? 'bg-blue-100 text-blue-800 rounded hover:bg-blue-200 text-sm btn-primary'\n : 'text-sm text-gray-600 bg-gray-200 rounded hover:bg-gray-300 btn-secondary'\n }`}\n >\n {t('tool.formMode')}\n </button>\n <button\n type=\"button\"\n onClick={switchToJsonMode}\n className={`px-3 py-1 text-sm rounded-md transition-colors ${\n isJsonMode\n ? 'px-4 py-1 bg-blue-100 text-blue-800 rounded hover:bg-blue-200 text-sm btn-primary'\n : 'text-sm text-gray-600 bg-gray-200 rounded hover:bg-gray-300 btn-secondary'\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=\"px-4 py-1 text-sm text-gray-600 bg-gray-200 rounded hover:bg-gray-300 btn-secondary\"\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=\"px-4 py-1 bg-blue-100 text-blue-800 rounded hover:bg-blue-200 text-sm btn-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=\"px-4 py-1 text-sm text-gray-600 bg-gray-200 rounded hover:bg-gray-300 btn-secondary\"\n >\n {t('tool.cancel')}\n </button>\n <button\n type=\"submit\"\n disabled={loading}\n className=\"px-4 py-1 bg-blue-100 text-blue-800 rounded hover:bg-blue-200 text-sm btn-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 className=\"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 shadow rounded-lg mb-4\">\n <div\n className=\"flex justify-between items-center cursor-pointer p-2\"\n onClick={(e) => {\n e.stopPropagation();\n setIsExpanded(!isExpanded);\n }}\n >\n <div className=\"flex-1\">\n <h3 className=\"text-lg font-medium text-gray-900 inline-flex items-center\">\n {tool.name.replace(server + nameSeparator, '')}\n <button\n className=\"ml-2 p-1 text-gray-500 hover:text-blue-600 cursor-pointer transition-colors\"\n onClick={handleCopyToolName}\n title={t('common.copy')}\n >\n {copiedToolName ? <Check size={16} className=\"text-green-500\" /> : <Copy size={16} />}\n </button>\n <span className=\"ml-2 text-sm font-normal text-gray-600 inline-flex items-center\">\n {isEditingDescription ? (\n <>\n <input\n ref={descriptionInputRef}\n type=\"text\"\n className=\"px-2 py-1 border border-blue-300 rounded bg-white dark:bg-gray-800 text-sm focus:outline-none form-input\"\n value={customDescription}\n onChange={handleDescriptionChange}\n onKeyDown={handleDescriptionKeyDown}\n onClick={(e) => e.stopPropagation()}\n style={{\n minWidth: '100px',\n width: textWidth > 0 ? `${textWidth + 20}px` : 'auto',\n }}\n />\n <button\n className=\"ml-2 p-1 text-green-600 hover:text-green-800 cursor-pointer transition-colors\"\n onClick={(e) => {\n e.stopPropagation();\n handleDescriptionSave();\n }}\n disabled={isResettingDescription}\n >\n <Check size={16} />\n </button>\n <ResetDescriptionButton\n title={t('tool.restoreDefault')}\n onClick={(e) => {\n e.stopPropagation();\n handleDescriptionReset();\n }}\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=\"ml-2 p-1 text-gray-500 hover:text-blue-600 cursor-pointer transition-colors\"\n onClick={(e) => {\n e.stopPropagation();\n handleDescriptionEdit();\n }}\n >\n <Edit size={14} />\n </button>\n <ResetDescriptionButton\n title={t('tool.restoreDefault')}\n onClick={(e) => {\n e.stopPropagation();\n handleDescriptionReset();\n }}\n disabled={isResettingDescription}\n loading={isResettingDescription}\n />\n </>\n )}\n </span>\n </h3>\n </div>\n <div className=\"flex items-center space-x-2\">\n <div className=\"flex items-center space-x-2\" 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); // Ensure card is expanded when showing run form\n setShowRunForm(true);\n }}\n className=\"flex items-center space-x-1 px-3 py-1 text-sm text-blue-600 bg-blue-50 hover:bg-blue-100 rounded-md transition-colors btn-primary\"\n disabled={isRunning || !tool.enabled}\n >\n {isRunning ? <Loader size={14} className=\"animate-spin\" /> : <Play size={14} />}\n <span>{isRunning ? t('tool.running') : t('tool.run')}</span>\n </button>\n <button className=\"text-gray-400 hover:text-gray-600\">\n {isExpanded ? <ChevronDown size={18} /> : <ChevronRight size={18} />}\n </button>\n </div>\n </div>\n\n {isExpanded && (\n <div className=\"mt-4 space-y-4\">\n {/* Schema Display */}\n {!showRunForm && (\n <div className=\"bg-gray-50 dark:bg-gray-800 rounded p-3 border border-gray-300\">\n <h4 className=\"text-sm font-medium text-gray-900 mb-2\">{t('tool.inputSchema')}</h4>\n <pre className=\"text-xs text-gray-600 overflow-auto\">\n {JSON.stringify(tool.inputSchema, null, 2)}\n </pre>\n </div>\n )}\n\n {/* Run Form */}\n {showRunForm && (\n <div className=\"border border-gray-300 rounded-lg p-4\">\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 {/* Tool Result */}\n {result && (\n <div className=\"mt-4\">\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 className=\"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 shadow rounded-lg mb-4\">\n <div\n className=\"flex justify-between items-center p-2 cursor-pointer\"\n onClick={() => setIsExpanded(!isExpanded)}\n >\n <div className=\"flex-1\">\n <h3 className=\"text-lg font-medium text-gray-900\">\n {prompt.name.replace(server + nameSeparator, '')}\n {prompt.title && (\n <span className=\"ml-2 text-sm font-normal text-gray-600\">{prompt.title}</span>\n )}\n <span className=\"ml-2 text-sm font-normal text-gray-500 inline-flex items-center\">\n {isEditingDescription ? (\n <>\n <input\n ref={descriptionInputRef}\n type=\"text\"\n className=\"px-2 py-1 border border-blue-300 rounded bg-white dark:bg-gray-800 text-sm focus:outline-none form-input\"\n value={customDescription}\n onChange={handleDescriptionChange}\n onKeyDown={handleDescriptionKeyDown}\n onClick={(e) => e.stopPropagation()}\n style={{\n minWidth: '100px',\n width: textWidth > 0 ? `${textWidth + 20}px` : 'auto',\n }}\n />\n <button\n className=\"ml-2 p-1 text-green-600 hover:text-green-800 cursor-pointer transition-colors\"\n onClick={(e) => {\n e.stopPropagation();\n handleDescriptionSave();\n }}\n disabled={isResettingDescription}\n >\n <Check size={16} />\n </button>\n <ResetDescriptionButton\n title={t('prompt.restoreDefault')}\n onClick={(e) => {\n e.stopPropagation();\n handleDescriptionReset();\n }}\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=\"ml-2 p-1 text-gray-500 hover:text-blue-600 cursor-pointer transition-colors\"\n onClick={(e) => {\n e.stopPropagation();\n handleDescriptionEdit();\n }}\n >\n <Edit size={14} />\n </button>\n <ResetDescriptionButton\n title={t('prompt.restoreDefault')}\n onClick={(e) => {\n e.stopPropagation();\n handleDescriptionReset();\n }}\n disabled={isResettingDescription}\n loading={isResettingDescription}\n />\n </>\n )}\n </span>\n </h3>\n </div>\n <div className=\"flex items-center space-x-2\">\n <div className=\"flex items-center space-x-2\" 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); // Ensure card is expanded when showing run form\n setShowRunForm(true);\n }}\n className=\"flex items-center space-x-1 px-3 py-1 text-sm text-blue-600 bg-blue-50 hover:bg-blue-100 rounded-md transition-colors btn-primary\"\n disabled={isRunning || !prompt.enabled}\n >\n {isRunning ? <Loader size={14} className=\"animate-spin\" /> : <Play size={14} />}\n <span>{isRunning ? t('tool.running') : t('tool.run')}</span>\n </button>\n <button className=\"text-gray-400 hover:text-gray-600\">\n {isExpanded ? <ChevronDown size={18} /> : <ChevronRight size={18} />}\n </button>\n </div>\n </div>\n\n {isExpanded && (\n <div className=\"mt-4 space-y-4\">\n {/* Run Form */}\n {showRunForm && (\n <div className=\"border border-gray-300 rounded-lg p-4\">\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 {/* Prompt Result */}\n {result && (\n <div className=\"mt-4\">\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 className=\"bg-gray-50 dark:bg-gray-800 rounded p-3 border border-gray-300\">\n <h4 className=\"text-sm font-medium text-gray-900 mb-2\">{t('tool.parameters')}</h4>\n <div className=\"space-y-2\">\n {prompt.arguments.map((arg, index) => (\n <div key={index} className=\"flex items-start\">\n <div className=\"flex-1\">\n <div className=\"flex items-center\">\n <span className=\"font-medium text-gray-700\">{arg.name}</span>\n {arg.required && <span className=\"text-red-500 ml-1\">*</span>}\n </div>\n {arg.description && (\n <p className=\"text-sm text-gray-600 mt-1\">{arg.description}</p>\n )}\n </div>\n <div className=\"text-xs text-gray-500 ml-2\">{arg.title || ''}</div>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Result Display (when not showing form) */}\n {!showRunForm && result && (\n <div className=\"mt-4\">\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 className=\"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 shadow rounded-lg mb-4\">\n <div\n className=\"flex justify-between items-center p-2 cursor-pointer\"\n onClick={() => setIsExpanded(!isExpanded)}\n >\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-lg font-medium text-gray-900 truncate\">\n {resource.name || resource.uri}\n </h3>\n <div className=\"text-sm text-gray-500 truncate\">{resource.uri}</div>\n <span className=\"text-sm font-normal text-gray-500 inline-flex items-center mt-1\">\n {isEditingDescription ? (\n <>\n <input\n ref={descriptionInputRef}\n type=\"text\"\n className=\"px-2 py-1 border border-blue-300 rounded bg-white dark:bg-gray-800 text-sm focus:outline-none form-input\"\n value={customDescription}\n onChange={(e) => setCustomDescription(e.target.value)}\n onKeyDown={handleDescriptionKeyDown}\n onClick={(e) => e.stopPropagation()}\n style={{\n minWidth: '100px',\n width: textWidth > 0 ? `${textWidth + 20}px` : 'auto',\n }}\n />\n <button\n className=\"ml-2 p-1 text-green-600 hover:text-green-800 cursor-pointer transition-colors\"\n onClick={(e) => {\n e.stopPropagation();\n handleDescriptionSave();\n }}\n disabled={isResettingDescription}\n >\n <Check size={16} />\n </button>\n <ResetDescriptionButton\n title={t('builtinResources.restoreDefault')}\n onClick={(e) => {\n e.stopPropagation();\n handleDescriptionReset();\n }}\n disabled={isResettingDescription}\n loading={isResettingDescription}\n />\n </>\n ) : (\n <>\n <span ref={descriptionTextRef}>{customDescription || t('tool.noDescription')}</span>\n <button\n className=\"ml-2 p-1 text-gray-500 hover:text-blue-600 cursor-pointer transition-colors\"\n onClick={(e) => {\n e.stopPropagation();\n setIsEditingDescription(true);\n }}\n >\n <Edit size={14} />\n </button>\n <ResetDescriptionButton\n title={t('builtinResources.restoreDefault')}\n onClick={(e) => {\n e.stopPropagation();\n handleDescriptionReset();\n }}\n disabled={isResettingDescription}\n loading={isResettingDescription}\n />\n </>\n )}\n </span>\n </div>\n\n <div className=\"flex items-center space-x-2\">\n <div className=\"flex items-center space-x-2\" onClick={(e) => e.stopPropagation()}>\n <Switch checked={resource.enabled !== false} onCheckedChange={handleToggle} />\n </div>\n <button className=\"text-gray-400 hover:text-gray-600\">\n {isExpanded ? <ChevronDown size={18} /> : <ChevronRight size={18} />}\n </button>\n </div>\n </div>\n\n {isExpanded && (\n <div className=\"mt-2 px-3 pb-3 text-sm text-gray-600 border-t border-gray-100 dark:border-gray-800\">\n <div className=\"pt-2\">\n <span className=\"font-medium\">{t('builtinResources.mimeType')}:</span>{' '}\n {resource.mimeType || 'text/plain'}\n </div>\n </div>\n )}\n </div>\n );\n};\n\nexport default ResourceCard;\n","import { useState, useRef, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Server } from '@/types';\nimport { ChevronDown, ChevronRight, AlertCircle, Copy, Check, Wrench, MessageSquare, FileText } from 'lucide-react';\nimport { StatusBadge } from '@/components/ui/Badge';\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 ServerCard = ({\n server,\n onRemove,\n onEdit,\n onToggle,\n onRefresh,\n onReload,\n}: ServerCardProps) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\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 [showErrorPopover, setShowErrorPopover] = useState(false);\n const [copied, setCopied] = useState(false);\n const errorPopoverRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (errorPopoverRef.current && !errorPopoverRef.current.contains(event.target as Node)) {\n setShowErrorPopover(false);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, []);\n\n const { exportMCPSettings } = useSettingsData();\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((prompt) => prompt.enabled !== false).length || 0;\n const totalResources = server.resources?.length || 0;\n const enabledResources =\n server.resources?.filter((resource) => resource.enabled !== false).length || 0;\n\n const handleRemove = (e: React.MouseEvent) => {\n e.stopPropagation();\n setShowDeleteDialog(true);\n };\n\n const handleEdit = (e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit(server);\n };\n\n const handleToggle = async (e: React.MouseEvent) => {\n e.stopPropagation();\n if (isToggling || !onToggle) return;\n\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 if (isReloading || !onReload) return;\n\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(\n t('server.reloadError', { serverName: server.name }) || 'Failed to reload server',\n 'error',\n );\n }\n } finally {\n setIsReloading(false);\n }\n };\n\n const handleErrorIconClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n setShowErrorPopover(!showErrorPopover);\n };\n\n const copyToClipboard = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (!server.error) return;\n\n if (navigator.clipboard && window.isSecureContext) {\n navigator.clipboard.writeText(server.error).then(() => {\n setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 2000);\n });\n } else {\n // Fallback for HTTP or unsupported clipboard API\n const textArea = document.createElement('textarea');\n textArea.value = server.error;\n // Avoid scrolling to bottom\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 setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n console.error('Copy to clipboard failed:', err);\n }\n document.body.removeChild(textArea);\n }\n };\n\n const handleCopyServerConfig = async (e: React.MouseEvent) => {\n e.stopPropagation();\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 configJson = JSON.stringify(result.data, null, 2);\n\n if (navigator.clipboard && window.isSecureContext) {\n await navigator.clipboard.writeText(configJson);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n } else {\n // Fallback for HTTP or unsupported clipboard API\n const textArea = document.createElement('textarea');\n textArea.value = configJson;\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 showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n } catch (err) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n console.error('Copy to clipboard failed:', err);\n }\n document.body.removeChild(textArea);\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 handleConfirmDelete = () => {\n onRemove(server.name);\n setShowDeleteDialog(false);\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(\n t(enabled ? 'tool.enableSuccess' : 'tool.disableSuccess', { name: toolName }),\n 'success',\n );\n // Trigger refresh to update the tool's state in the UI\n if (onRefresh) {\n onRefresh();\n }\n } else {\n showToast(result.error || t('tool.toggleFailed'), 'error');\n }\n } catch (error) {\n console.error('Error toggling tool:', error);\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(\n t(enabled ? 'tool.enableSuccess' : 'tool.disableSuccess', { name: promptName }),\n 'success',\n );\n // Trigger refresh to update the prompt's state in the UI\n if (onRefresh) {\n onRefresh();\n }\n } else {\n showToast(result.error || t('tool.toggleFailed'), 'error');\n }\n } catch (error) {\n console.error('Error toggling prompt:', error);\n showToast(t('tool.toggleFailed'), 'error');\n }\n };\n\n const handleToolDescriptionUpdate = (\n _toolName: string,\n _description: string,\n options?: { restored?: boolean },\n ) => {\n showToast(\n options?.restored ? t('tool.restoreDefaultSuccess') : t('tool.descriptionUpdateSuccess'),\n 'success',\n );\n if (onRefresh) {\n onRefresh();\n }\n };\n\n const handlePromptDescriptionUpdate = (\n _promptName: string,\n _description: string,\n options?: { restored?: boolean },\n ) => {\n showToast(\n options?.restored ? t('prompt.restoreDefaultSuccess') : t('prompt.descriptionUpdateSuccess'),\n 'success',\n );\n if (onRefresh) {\n onRefresh();\n }\n };\n\n const handleOAuthAuthorization = (e: React.MouseEvent) => {\n e.stopPropagation();\n // Open the OAuth authorization URL in a new window\n if (server.oauth?.authorizationUrl) {\n const width = 600;\n const height = 700;\n const left = window.screen.width / 2 - width / 2;\n const top = window.screen.height / 2 - height / 2;\n\n window.open(\n server.oauth.authorizationUrl,\n 'OAuth Authorization',\n `width=${width},height=${height},left=${left},top=${top}`,\n );\n\n showToast(t('status.oauthWindowOpened'), 'info');\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(\n t(enabled ? 'tool.enableSuccess' : 'tool.disableSuccess', { name: resourceUri }),\n 'success',\n );\n if (onRefresh) {\n onRefresh();\n }\n } else {\n showToast(result.error || t('tool.toggleFailed'), 'error');\n }\n } catch (error) {\n console.error('Error toggling resource:', error);\n showToast(t('tool.toggleFailed'), 'error');\n }\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 if (onRefresh) {\n onRefresh();\n }\n } else {\n showToast(\n result.error ||\n (options?.restored\n ? t('builtinResources.restoreDefaultFailed')\n : t('builtinResources.descriptionUpdateFailed')),\n 'error',\n );\n }\n } catch (error) {\n console.error('Error updating resource description:', error);\n showToast(\n options?.restored\n ? t('builtinResources.restoreDefaultFailed')\n : t('builtinResources.descriptionUpdateFailed'),\n 'error',\n );\n }\n };\n\n return (\n <>\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg mb-6 page-card transition-all duration-200\">\n <div\n className=\"flex justify-between items-center p-4\"\n >\n <div className=\"flex items-center space-x-2\">\n <h2\n className={`text-xl font-semibold ${server.enabled === false ? 'text-gray-600' : 'text-gray-900'}`}\n >\n {server.name}\n </h2>\n {server.config?.description && (\n <span className=\"text-sm text-gray-500\">({server.config.description})</span>\n )}\n <StatusBadge status={server.status} onAuthClick={handleOAuthAuthorization} />\n\n {/* Server type badge */}\n {server.config?.type && (\n <div className=\"flex items-center px-2 py-1 bg-gray-100 dark:bg-gray-800 text-gray-700 rounded-full text-xs\">\n <span>\n {server.config.type === 'stdio' && t('server.typeStdio')}\n {server.config.type === 'sse' && t('server.typeSse')}\n {server.config.type === 'streamable-http' && t('server.typeStreamableHttp')}\n {server.config.type === 'openapi' && t('server.typeOpenapi')}\n </span>\n </div>\n )}\n\n {/* Tool count display */}\n <div \n className={`flex items-center px-2 py-1 rounded-full text-sm cursor-pointer transition-colors ${expandedTab === 'tools' ? 'bg-blue-100 text-blue-800 dark:bg-blue-900/50 dark:text-blue-300' : 'bg-blue-50 text-blue-700 hover:bg-blue-100 dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700'}`}\n onClick={(e) => {\n e.stopPropagation();\n setExpandedTab(prev => prev === 'tools' ? null : 'tools');\n }}\n >\n <Wrench className=\"w-4 h-4 mr-1\" />\n <span>\n {totalTools === 0 ? '0' : `${enabledTools}/${totalTools}`} {t('server.tools')}\n </span>\n </div>\n\n {/* Prompt count display */}\n <div \n className={`flex items-center px-2 py-1 rounded-full text-sm cursor-pointer transition-colors ${expandedTab === 'prompts' ? 'bg-purple-100 text-purple-800 dark:bg-purple-900/50 dark:text-purple-300' : 'bg-purple-50 text-purple-700 hover:bg-purple-100 dark:bg-gray-800 dark:text-purple-400 dark:hover:bg-gray-700'}`}\n onClick={(e) => {\n e.stopPropagation();\n setExpandedTab(prev => prev === 'prompts' ? null : 'prompts');\n }}\n >\n <MessageSquare className=\"w-4 h-4 mr-1\" />\n <span>\n {totalPrompts === 0 ? '0' : `${enabledPrompts}/${totalPrompts}`} {t('server.prompts')}\n </span>\n </div>\n\n {/* Resource count display */}\n <div \n className={`flex items-center px-2 py-1 rounded-full text-sm cursor-pointer transition-colors ${expandedTab === 'resources' ? 'bg-emerald-100 text-emerald-800 dark:bg-emerald-900/50 dark:text-emerald-300' : 'bg-emerald-50 text-emerald-700 hover:bg-emerald-100 dark:bg-gray-800 dark:text-emerald-400 dark:hover:bg-gray-700'}`}\n onClick={(e) => {\n e.stopPropagation();\n setExpandedTab(prev => prev === 'resources' ? null : 'resources');\n }}\n >\n <FileText className=\"w-4 h-4 mr-1\" />\n <span>\n {totalResources === 0 ? '0' : `${enabledResources}/${totalResources}`} {t('nav.resources')}\n </span>\n </div>\n\n {server.error && (\n <div className=\"relative\">\n <div\n className=\"cursor-pointer\"\n onClick={handleErrorIconClick}\n aria-label={t('server.viewErrorDetails')}\n >\n <AlertCircle className=\"text-red-500 hover:text-red-600\" size={18} />\n </div>\n\n {showErrorPopover && (\n <div\n ref={errorPopoverRef}\n className=\"absolute z-10 mt-2 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-md shadow-lg p-0 w-120\"\n style={{\n left: '-231px',\n top: '24px',\n maxHeight: '300px',\n overflowY: 'auto',\n width: '480px',\n transform: 'translateX(50%)',\n }}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex justify-between items-center sticky top-0 bg-white dark:bg-gray-800 py-2 px-4 border-b border-gray-200 dark:border-gray-700 z-20 shadow-sm\">\n <div className=\"flex items-center space-x-2\">\n <h4 className=\"text-sm font-medium text-red-600\">\n {t('server.errorDetails')}\n </h4>\n <button\n onClick={copyToClipboard}\n className=\"p-1 text-gray-400 hover:text-gray-600 transition-colors btn-secondary\"\n title={t('common.copy')}\n >\n {copied ? (\n <Check size={14} className=\"text-green-500\" />\n ) : (\n <Copy size={14} />\n )}\n </button>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setShowErrorPopover(false);\n }}\n className=\"text-gray-400 hover:text-gray-600\"\n >\n ✕\n </button>\n </div>\n <div className=\"p-4 pt-2\">\n <pre className=\"text-sm text-gray-700 break-words whitespace-pre-wrap\">\n {server.error}\n </pre>\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n <div className=\"flex space-x-2\">\n <button onClick={handleCopyServerConfig} className={`px-3 py-1 btn-secondary`}>\n {t('server.copy')}\n </button>\n <button\n onClick={handleEdit}\n className=\"px-3 py-1 bg-blue-100 text-blue-800 rounded hover:bg-blue-200 text-sm btn-primary\"\n >\n {t('server.edit')}\n </button>\n <div className=\"flex items-center\">\n <button\n onClick={handleToggle}\n className={`px-3 py-1 text-sm rounded transition-colors ${\n isToggling\n ? 'bg-gray-200 text-gray-500'\n : server.enabled !== false\n ? 'bg-green-100 text-green-800 hover:bg-green-200 btn-secondary'\n : 'bg-blue-100 text-blue-800 hover:bg-blue-200 btn-primary'\n }`}\n disabled={isToggling || isReloading}\n >\n {isToggling\n ? t('common.processing')\n : server.enabled !== false\n ? t('server.disable')\n : t('server.enable')}\n </button>\n </div>\n {onReload && (\n <button\n onClick={handleReload}\n className=\"px-3 py-1 bg-purple-100 text-purple-800 rounded hover:bg-purple-200 text-sm btn-secondary disabled:opacity-70 disabled:cursor-not-allowed\"\n disabled={isReloading || isToggling || server.enabled === false}\n >\n {isReloading ? t('common.processing') : t('server.reload')}\n </button>\n )}\n <button\n onClick={handleRemove}\n className=\"px-3 py-1 bg-red-100 text-red-800 rounded hover:bg-red-200 text-sm btn-danger\"\n >\n {t('server.delete')}\n </button>\n <button className=\"text-gray-400 hover:text-gray-600 btn-secondary\">\n {expandedTab ? <ChevronDown size={18} /> : <ChevronRight size={18} />}\n </button>\n </div>\n </div>\n\n {expandedTab === 'tools' && server.tools && (\n <div className=\"px-4\">\n <h6\n className={`font-medium ${server.enabled === false ? 'text-gray-600' : 'text-gray-900'} mb-2`}\n >\n {t('server.tools')}\n </h6>\n <div className=\"space-y-4\">\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 </div>\n )}\n\n {expandedTab === 'prompts' && server.prompts && (\n <div className=\"px-4 pb-2\">\n <h6\n className={`font-medium ${server.enabled === false ? 'text-gray-600' : 'text-gray-900'}`}\n >\n {t('server.prompts')}\n </h6>\n <div className=\"space-y-4\">\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 </div>\n )}\n\n {expandedTab === 'resources' && server.resources && (\n <div className=\"px-4 pb-2\">\n <h6\n className={`font-medium ${server.enabled === false ? 'text-gray-600' : 'text-gray-900'}`}\n >\n {t('nav.resources')}\n </h6>\n {server.resources.length === 0 ? (\n <div className=\"text-sm text-gray-500 py-2\">\n {t('builtinResources.noResources')}\n </div>\n ) : (\n <div className=\"space-y-4\">\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 <DeleteDialog\n isOpen={showDeleteDialog}\n onClose={() => setShowDeleteDialog(false)}\n onConfirm={handleConfirmDelete}\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=\"w-full bg-blue-100 text-blue-800 rounded hover:bg-blue-200 py-2 px-4 flex items-center justify-center btn-primary\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4 mr-2\" 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=\"bg-white dark:bg-gray-800 rounded-lg 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=\"px-4 py-2 text-gray-600 border border-gray-300 rounded hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700 btn-secondary\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={handleConfirmSubmit}\n className=\"px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 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=\"px-4 py-2 text-gray-700 bg-gray-200 rounded hover:bg-gray-300 disabled:opacity-50 btn-secondary\"\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=\"px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 flex items-center 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=\"px-4 py-2 text-gray-700 bg-gray-200 rounded hover:bg-gray-300 disabled:opacity-50 btn-secondary\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={handleUpload}\n disabled={!selectedFile || isUploading}\n className=\"px-4 py-2 text-white rounded hover:bg-blue-700 disabled:opacity-50 flex items-center 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.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=\"px-4 py-2 text-gray-700 bg-gray-200 rounded hover:bg-gray-300 btn-secondary\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={handlePreview}\n disabled={!jsonInput.trim()}\n className=\"px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 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=\"px-4 py-2 text-gray-700 bg-gray-200 rounded hover:bg-gray-300 disabled:opacity-50 btn-secondary\"\n >\n {t('common.back')}\n </button>\n <button\n onClick={handleImport}\n disabled={isImporting}\n className=\"px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 flex items-center 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, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router-dom';\nimport { Server } from '@/types';\nimport ServerCard from '@/components/ServerCard';\nimport AddServerForm from '@/components/AddServerForm';\nimport EditServerForm from '@/components/EditServerForm';\nimport { useServerData } from '@/hooks/useServerData';\nimport McpbUploadForm from '@/components/McpbUploadForm';\nimport JSONImportForm from '@/components/JSONImportForm';\nimport Pagination from '@/components/ui/Pagination';\n\nconst ServersPage: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const {\n servers,\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 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\n const handleEditClick = async (server: Server) => {\n const fullServerData = await handleServerEdit(server);\n if (fullServerData) {\n setEditingServer(fullServerData);\n }\n };\n\n const handleEditComplete = () => {\n setEditingServer(null);\n triggerRefresh();\n };\n\n const handleRefresh = async () => {\n setIsRefreshing(true);\n try {\n triggerRefresh();\n // Add a slight delay to make the spinner visible\n await new Promise((resolve) => setTimeout(resolve, 500));\n } finally {\n setIsRefreshing(false);\n }\n };\n\n const handleMcpbUploadSuccess = (_serverConfig: any) => {\n // Close upload dialog and refresh servers\n setShowMcpbUpload(false);\n triggerRefresh();\n };\n\n const handleJsonImportSuccess = () => {\n // Close import dialog and refresh servers\n setShowJsonImport(false);\n triggerRefresh();\n };\n\n return (\n <div>\n <div className=\"flex justify-between items-center mb-8\">\n <h1 className=\"text-2xl font-bold text-gray-900\">{t('pages.servers.title')}</h1>\n <div className=\"flex space-x-4\">\n <button\n onClick={() => navigate('/market')}\n className=\"px-4 py-2 bg-blue-100 text-blue-800 rounded hover:bg-blue-200 flex items-center btn-primary transition-all duration-200\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4 mr-2\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path d=\"M3 1a1 1 0 000 2h1.22l.305 1.222a.997.997 0 00.01.042l1.358 5.43-.893.892C3.74 11.846 4.632 14 6.414 14H15a1 1 0 000-2H6.414l1-1H14a1 1 0 00.894-.553l3-6A1 1 0 0017 3H6.28l-.31-1.243A1 1 0 005 1H3z\" />\n </svg>\n {t('nav.market')}\n </button>\n <AddServerForm onAdd={handleServerAdd} />\n <button\n onClick={() => setShowJsonImport(true)}\n className=\"px-4 py-2 bg-blue-100 text-blue-800 rounded hover:bg-blue-200 flex items-center btn-primary transition-all duration-200\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4 mr-2\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM6.293 6.707a1 1 0 010-1.414l3-3a1 1 0 011.414 0l3 3a1 1 0 01-1.414 1.414L11 5.414V13a1 1 0 11-2 0V5.414L7.707 6.707a1 1 0 01-1.414 0z\"\n clipRule=\"evenodd\"\n />\n </svg>\n {t('jsonImport.button')}\n </button>\n <button\n onClick={() => setShowMcpbUpload(true)}\n className=\"px-4 py-2 bg-blue-100 text-blue-800 rounded hover:bg-blue-200 flex items-center btn-primary transition-all duration-200\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4 mr-2\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path d=\"M5.5 13a3.5 3.5 0 01-.369-6.98 4 4 0 117.753-1.977A4.5 4.5 0 1113.5 13H11V9.413l1.293 1.293a1 1 0 001.414-1.414l-3-3a1 1 0 00-1.414 0l-3 3a1 1 0 001.414 1.414L9 9.413V13H5.5z\" />\n </svg>\n {t('mcpb.upload')}\n </button>\n <button\n onClick={handleRefresh}\n disabled={isRefreshing}\n className={`px-4 py-2 bg-blue-100 text-blue-800 rounded hover:bg-blue-200 flex items-center btn-primary transition-all duration-200 ${isRefreshing ? 'opacity-70 cursor-not-allowed' : ''}`}\n >\n {isRefreshing ? (\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 ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4 mr-2\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z\"\n clipRule=\"evenodd\"\n />\n </svg>\n )}\n {t('common.refresh')}\n </button>\n </div>\n </div>\n\n {error && (\n <div className=\"mb-6 bg-red-50 border-l-4 border-red-500 p-4 rounded shadow-sm error-box\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-gray-600 mt-1\">{error}</p>\n </div>\n <button\n onClick={() => setError(null)}\n className=\"ml-4 text-gray-500 hover:text-gray-700 transition-colors duration-200 btn-secondary\"\n aria-label={t('app.closeButton')}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-5 w-5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 011.414 0L10 8.586l4.293-4.293a1 1 111.414 1.414L11.414 10l4.293 4.293a1 1 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 01-1.414-1.414L8.586 10 4.293 5.707a1 1 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n </div>\n </div>\n )}\n\n {isLoading ? (\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg p-6 flex items-center justify-center loading-container\">\n <div className=\"flex flex-col items-center\">\n <svg\n className=\"animate-spin h-10 w-10 text-blue-500 mb-4\"\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 <p className=\"text-gray-600\">{t('app.loading')}</p>\n </div>\n </div>\n ) : servers.length === 0 ? (\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg p-6 empty-state\">\n <p className=\"text-gray-600\">{t('app.noServers')}</p>\n </div>\n ) : (\n <>\n <div className=\"space-y-6\">\n {servers.map((server, index) => (\n <ServerCard\n key={index}\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 mb-4\">\n <div className=\"flex-[2] text-sm text-gray-500\">\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', {\n start: 1,\n end: servers.length,\n total: servers.length,\n })}\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 space-x-2\">\n <label htmlFor=\"perPage\" className=\"text-sm text-gray-600\">\n {t('common.itemsPerPage')}:\n </label>\n <select\n id=\"perPage\"\n value={serversPerPage}\n onChange={(e) => setServersPerPage(Number(e.target.value))}\n disabled={isLoading}\n className=\"border rounded p-1 text-sm btn-secondary outline-none disabled:opacity-50 disabled:cursor-not-allowed\"\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={handleEditComplete}\n onCancel={() => setEditingServer(null)}\n />\n )}\n\n {showMcpbUpload && (\n <McpbUploadForm\n onSuccess={handleMcpbUploadSuccess}\n onCancel={() => setShowMcpbUpload(false)}\n />\n )}\n\n {showJsonImport && (\n <JSONImportForm\n onSuccess={handleJsonImportSuccess}\n onCancel={() => setShowJsonImport(false)}\n />\n )}\n </div>\n );\n};\n\nexport default ServersPage;\n"],"file":"assets/ServersPage-CtS1I4yS.js"}
|