V4.9.6 feature (#4565)
* Dashboard submenu (#4545) * add app submenu (#4452) * add app submenu * fix * width & i18n * optimize submenu code (#4515) * optimize submenu code * fix * fix * fix * fix ts * perf: dashboard sub menu * doc --------- Co-authored-by: heheer <heheer@sealos.io> * feat: value format test * doc * Mcp export (#4555) * feat: mcp server * feat: mcp server * feat: mcp server build * update doc * perf: path selector (#4556) * perf: path selector * fix: docker file path * perf: add image endpoint to dataset search (#4557) * perf: add image endpoint to dataset search * fix: mcp_server url * human in loop (#4558) * Support interactive nodes for loops, and enhance the function of merging nested and loop node history messages. (#4552) * feat: add LoopInteractive definition * feat: Support LoopInteractive type and update related logic * fix: Refactor loop handling logic and improve output value initialization * feat: Add mergeSignId to dispatchLoop and dispatchRunAppNode responses * feat: Enhance mergeChatResponseData to recursively merge plugin details and improve response handling * refactor: Remove redundant comments in mergeChatResponseData for clarity * perf: loop interactive * perf: human in loop --------- Co-authored-by: Theresa <63280168+sd0ric4@users.noreply.github.com> * mcp server ui * integrate mcp (#4549) * integrate mcp * delete unused code * fix ts * bug fix * fix * support whole mcp tools * add try catch * fix * fix * fix ts * fix test * fix ts * fix: interactive in v1 completions * doc * fix: router path * fix mcp integrate (#4563) * fix mcp integrate * fix ui * fix: mcp ux * feat: mcp call title * remove repeat loading * fix mcp tools avatar (#4564) * fix * fix avatar * fix update version * update doc * fix: value format * close server and remove cache * perf: avatar --------- Co-authored-by: heheer <heheer@sealos.io> Co-authored-by: Theresa <63280168+sd0ric4@users.noreply.github.com>
This commit is contained in:
179
projects/app/src/pages/dashboard/mcpServer/index.tsx
Normal file
179
projects/app/src/pages/dashboard/mcpServer/index.tsx
Normal file
@@ -0,0 +1,179 @@
|
||||
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, 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 { McpKeyType } from '@fastgpt/global/support/mcp/type';
|
||||
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||
|
||||
const UsageWay = dynamic(() => import('@/pageComponents/dashboard/mcp/usageWay'), {
|
||||
ssr: false
|
||||
});
|
||||
|
||||
const McpServer = () => {
|
||||
const { t } = useTranslation();
|
||||
const { isPc } = useSystem();
|
||||
|
||||
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 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 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']))
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user