Files
FastGPT/projects/app/src/pages/dashboard/mcpServer/index.tsx
Archer 4e83840c14 perf: tool call check (#4818)
* i18n

* tool call

* fix: mcp create permission;Plugin unauth tip

* fix: mcp create permission;Plugin unauth tip

* fix: Cite modal permission

* remove invalide cite

* perf: prompt

* filter fulltext search

* fix: ts

* fix: ts

* fix: ts
2025-05-15 15:51:34 +08:00

192 lines
6.3 KiB
TypeScript

'use client';
import { serviceSideProps } from '@/web/common/i18n/utils';
import React, { useState } from 'react';
import DashboardContainer from '@/pageComponents/dashboard/Container';
import {
Box,
Button,
Flex,
HStack,
Table,
TableContainer,
Tbody,
Td,
Th,
Thead,
Tr
} from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { deleteMcpServer, getMcpServerList } from '@/web/support/mcp/api';
import MyBox from '@fastgpt/web/components/common/MyBox';
import EditMcpModal, {
defaultForm,
type EditMcForm
} from '@/pageComponents/dashboard/mcp/EditModal';
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
import MyIconButton from '@fastgpt/web/components/common/Icon/button';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import dynamic from 'next/dynamic';
import { type McpKeyType } from '@fastgpt/global/support/mcp/type';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
import { useUserStore } from '@/web/support/user/useUserStore';
const UsageWay = dynamic(() => import('@/pageComponents/dashboard/mcp/usageWay'), {
ssr: false
});
const McpServer = () => {
const { t } = useTranslation();
const { isPc } = useSystem();
const { userInfo } = useUserStore();
const {
data: mcpServerList = [],
loading: loadingList,
refresh: loadMcpList
} = useRequest2(getMcpServerList, {
manual: false
});
const [editMcp, setEditMcp] = useState<EditMcForm>();
const [usageWay, setUsageWay] = useState<McpKeyType>();
const { openConfirm: openDelConfirm, ConfirmModal: DelConfirmModal } = useConfirm({
type: 'delete',
content: t('dashboard_mcp:delete_mcp_server_confirm_tip')
});
const { runAsync: onDeleteMcpServer } = useRequest2(deleteMcpServer, {
manual: true,
onSuccess: () => {
loadMcpList();
}
});
const isLoading = loadingList;
return (
<>
<DashboardContainer>
{({ MenuIcon }) => (
<MyBox isLoading={isLoading} h={'100%'} p={6}>
{isPc ? (
<Flex alignItems={'flex-end'} justifyContent={'space-between'}>
<Box>
<Box fontSize={'lg'} color={'myGray.900'} fontWeight={500}>
{t('dashboard_mcp:mcp_server')}
</Box>
<Box fontSize={'xs'} color={'myGray.500'}>
{t('dashboard_mcp:mcp_server_description')}
</Box>
</Box>
<Button
isDisabled={!userInfo?.permission.hasApikeyCreatePer}
onClick={() => setEditMcp(defaultForm)}
>
{t('dashboard_mcp:create_mcp_server')}
</Button>
</Flex>
) : (
<>
<HStack>
<Box>{MenuIcon}</Box>
<Box fontSize={'lg'} color={'myGray.900'} fontWeight={500}>
{t('dashboard_mcp:mcp_server')}
</Box>
</HStack>
<Box fontSize={'xs'} color={'myGray.500'}>
{t('dashboard_mcp:mcp_server_description')}
</Box>
<Flex mt={2} justifyContent={'flex-end'}>
<Button
isDisabled={!userInfo?.permission.hasApikeyCreatePer}
onClick={() => setEditMcp(defaultForm)}
>
{t('dashboard_mcp:create_mcp_server')}
</Button>
</Flex>
</>
)}
{/* table */}
<TableContainer mt={4} bg={'white'} borderRadius={'md'}>
<Table>
<Thead>
<Tr borderBottom={'base'}>
<Th bg={'white'}>{t('dashboard_mcp:mcp_name')}</Th>
<Th bg={'white'}>{t('dashboard_mcp:mcp_apps')}</Th>
<Th bg={'white'}></Th>
</Tr>
</Thead>
<Tbody fontSize={'sm'}>
{mcpServerList.map((mcp) => {
return (
<Tr key={mcp._id} fontWeight={500} fontSize={'sm'} color={'myGray.900'}>
<Td>{mcp.name}</Td>
<Td>{mcp.apps.length}</Td>
<Td>
<HStack>
<Button
mr={4}
variant={'whiteBase'}
size={'sm'}
onClick={() => setUsageWay(mcp)}
>
{t('dashboard_mcp:start_use')}
</Button>
<MyIconButton
icon="edit"
onClick={() =>
setEditMcp({
id: mcp._id,
name: mcp.name,
apps: mcp.apps
})
}
/>
<MyIconButton
icon="delete"
hoverColor={'red.600'}
onClick={() => openDelConfirm(() => onDeleteMcpServer(mcp._id))()}
/>
</HStack>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
{mcpServerList.length === 0 && <EmptyTip />}
</TableContainer>
</MyBox>
)}
</DashboardContainer>
<DelConfirmModal />
{!!usageWay && <UsageWay mcp={usageWay} onClose={() => setUsageWay(undefined)} />}
{!!editMcp && (
<EditMcpModal
editMcp={editMcp}
onClose={() => setEditMcp(undefined)}
onSuccess={() => {
setEditMcp(undefined);
loadMcpList();
}}
/>
)}
</>
);
};
export default McpServer;
export async function getServerSideProps(content: any) {
return {
props: {
...(await serviceSideProps(content, ['dashboard_mcp']))
}
};
}