'use client' import React, { useCallback } from 'react' import { useRouter } from 'next/navigation' import type { FC } from 'react' import { useBoolean } from 'ahooks' import { useTranslation } from 'react-i18next' import { useAppContext } from '@/context/app-context' import { RiCloseLine, RiLoader2Line, RiLoopLeftLine, } from '@remixicon/react' import type { ToolWithProvider } from '../../../workflow/types' import Icon from '@/app/components/plugins/card/base/card-icon' import ActionButton from '@/app/components/base/action-button' import Button from '@/app/components/base/button' import Confirm from '@/app/components/base/confirm' import Indicator from '@/app/components/header/indicator' import MCPModal from '../modal' import OperationDropdown from './operation-dropdown' import ListLoading from './list-loading' import ToolItem from './tool-item' import { useAuthorizeMCP, useDeleteMCP, useInvalidateMCPTools, useMCPTools, useUpdateMCP, useUpdateMCPTools, } from '@/service/use-tools' import cn from '@/utils/classnames' type Props = { detail: ToolWithProvider onUpdate: (isDelete?: boolean) => void onHide: () => void } const MCPDetailContent: FC = ({ detail, onUpdate, onHide, }) => { const { t } = useTranslation() const router = useRouter() const { isCurrentWorkspaceManager } = useAppContext() const { data, isFetching: isGettingTools } = useMCPTools(detail.is_team_authorization ? detail.id : '') const invalidateMCPTools = useInvalidateMCPTools() const { mutateAsync: updateTools, isPending: isUpdating } = useUpdateMCPTools() const { mutateAsync: authorizeMcp, isPending: isAuthorizing } = useAuthorizeMCP() const toolList = data?.tools || [] const handleUpdateTools = useCallback(async () => { if (!detail) return await updateTools(detail.id) invalidateMCPTools(detail.id) onUpdate() }, [detail, updateTools]) const { mutate: updateMCP } = useUpdateMCP({ onSuccess: onUpdate, }) const { mutate: deleteMCP } = useDeleteMCP({ onSuccess: onUpdate, }) const [isShowUpdateModal, { setTrue: showUpdateModal, setFalse: hideUpdateModal, }] = useBoolean(false) const [isShowDeleteConfirm, { setTrue: showDeleteConfirm, setFalse: hideDeleteConfirm, }] = useBoolean(false) const [deleting, { setTrue: showDeleting, setFalse: hideDeleting, }] = useBoolean(false) const handleAuthorize = useCallback(async () => { if (!detail) return const res = await authorizeMcp({ provider_id: detail.id, server_url: detail.server_url!, }) if (res.result === 'success') handleUpdateTools() else if (res.authorization_url) router.push(res.authorization_url) }, [detail, updateMCP, hideUpdateModal, onUpdate]) const handleUpdate = useCallback(async (data: any) => { if (!detail) return const res = await updateMCP({ ...data, provider_id: detail.id, }) if ((res as any)?.result === 'success') { hideUpdateModal() onUpdate() } }, [detail, updateMCP, hideUpdateModal, onUpdate]) const handleDelete = useCallback(async () => { if (!detail) return showDeleting() const res = await deleteMCP(detail.id) hideDeleting() if ((res as any)?.result === 'success') { hideDeleteConfirm() onUpdate(true) } }, [detail, showDeleting, hideDeleting, hideDeleteConfirm, onUpdate]) if (!detail) return null return ( <>
{detail.name}
{detail.server_url}
{detail.is_team_authorization && ( )} {!detail.is_team_authorization && !isAuthorizing && ( )} {isAuthorizing && ( )}
{((detail.is_team_authorization && isGettingTools) || isUpdating) && ( <>
{!isUpdating &&
{t('tools.mcp.gettingTools')}
} {isUpdating &&
{t('tools.mcp.updateTools')}
}
)} {detail.is_team_authorization && !isGettingTools && !toolList.length && (
{t('tools.mcp.toolsEmpty')}
)} {!isGettingTools && toolList.length > 0 && ( <>
{toolList.length > 1 &&
{t('tools.mcp.toolsNum', { count: toolList.length })}
} {toolList.length === 1 &&
{t('tools.mcp.onlyTool')}
}
{toolList.map(tool => ( ))}
)} {!detail.is_team_authorization && (
{!isAuthorizing &&
{t('tools.mcp.authorizingRequired')}
} {isAuthorizing &&
{t('tools.mcp.authorizing')}
}
{t('tools.mcp.authorizeTip')}
)}
{isShowUpdateModal && ( )} {isShowDeleteConfirm && ( {t('tools.mcp.deleteConfirmTitle', { mcp: detail.name })} } onCancel={hideDeleteConfirm} onConfirm={handleDelete} isLoading={deleting} isDisabled={deleting} /> )} ) } export default MCPDetailContent