'use client' import React, { useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { RiLoopLeftLine, } from '@remixicon/react' import { Mcp, } from '@/app/components/base/icons/src/vender/other' import Button from '@/app/components/base/button' import Tooltip from '@/app/components/base/tooltip' import Switch from '@/app/components/base/switch' import Divider from '@/app/components/base/divider' import CopyFeedback from '@/app/components/base/copy-feedback' import Confirm from '@/app/components/base/confirm' import type { AppDetailResponse } from '@/models/app' import { useAppContext } from '@/context/app-context' import type { AppSSO } from '@/types/app' import Indicator from '@/app/components/header/indicator' import MCPServerModal from '@/app/components/tools/mcp/mcp-server-modal' import { useAppWorkflow } from '@/service/use-workflow' import { useInvalidateMCPServerDetail, useMCPServerDetail, useRefreshMCPServerCode, useUpdateMCPServer, } from '@/service/use-tools' import { BlockEnum } from '@/app/components/workflow/types' import cn from '@/utils/classnames' export type IAppCardProps = { appInfo: AppDetailResponse & Partial } function MCPServiceCard({ appInfo, }: IAppCardProps) { const { t } = useTranslation() const { mutateAsync: updateMCPServer } = useUpdateMCPServer() const { mutateAsync: refreshMCPServerCode, isPending: genLoading } = useRefreshMCPServerCode() const invalidateMCPServerDetail = useInvalidateMCPServerDetail() const { isCurrentWorkspaceManager, isCurrentWorkspaceEditor } = useAppContext() const [showConfirmDelete, setShowConfirmDelete] = useState(false) const [showMCPServerModal, setShowMCPServerModal] = useState(false) const { data: currentWorkflow } = useAppWorkflow(appInfo.id) const { data: detail } = useMCPServerDetail(appInfo.id) const { id, status, server_code } = detail ?? {} const appUnpublished = !currentWorkflow?.graph const serverPublished = !!id const serverActivated = status === 'active' const serverURL = serverPublished ? `${globalThis.location.protocol}//${globalThis.location.host}/api/server/${server_code}/mcp` : '***********' const toggleDisabled = !isCurrentWorkspaceEditor || appUnpublished const [activated, setActivated] = useState(serverActivated) const latestParams = useMemo(() => { if (!currentWorkflow?.graph) return [] const startNode = currentWorkflow?.graph.nodes.find(node => node.data.type === BlockEnum.Start) as any return startNode?.data.variables as any[] || [] }, [currentWorkflow]) const onGenCode = async () => { await refreshMCPServerCode(detail?.id || '') invalidateMCPServerDetail(appInfo.id) } const onChangeStatus = async (state: boolean) => { setActivated(state) if (state) { if (!serverPublished) setShowMCPServerModal(true) await updateMCPServer({ appID: appInfo.id, id: id || '', description: detail?.description || '', parameters: detail?.parameters || {}, status: 'active', }) invalidateMCPServerDetail(appInfo.id) } else { await updateMCPServer({ appID: appInfo.id, id: id || '', description: detail?.description || '', parameters: detail?.parameters || {}, status: 'inactive', }) invalidateMCPServerDetail(appInfo.id) } } const handleServerModalHide = () => { setShowMCPServerModal(false) if (!serverActivated) setActivated(false) } useEffect(() => { setActivated(serverActivated) }, [serverActivated]) if (!currentWorkflow) return null return ( <>
{t('tools.mcp.server.title')}
{serverActivated ? t('appOverview.overview.status.running') : t('appOverview.overview.status.disable')}
{t('tools.mcp.server.url')}
{serverURL}
{serverPublished && ( <> {isCurrentWorkspaceManager && (
setShowConfirmDelete(true)} >
)} )}
{showMCPServerModal && ( )} {/* button copy link/ button regenerate */} {showConfirmDelete && ( { onGenCode() setShowConfirmDelete(false) }} onCancel={() => setShowConfirmDelete(false)} /> )} ) } export default MCPServiceCard