From 347cb2685eb960a456c0464ce042d745dd576cfd Mon Sep 17 00:00:00 2001 From: Joel Date: Thu, 8 May 2025 14:55:22 +0800 Subject: [PATCH] feat: add mcp tab and merge tool with server ts define --- web/app/components/tools/mcp/mock.ts | 12 ++++++++++++ web/app/components/tools/mcp/provider-card.tsx | 12 ++++++------ web/app/components/tools/mcp/provider-detail.tsx | 4 ++-- web/app/components/tools/types.ts | 15 +++------------ .../workflow/block-selector/all-tools.tsx | 8 ++++++-- .../components/workflow/block-selector/hooks.ts | 4 ++++ .../components/workflow/block-selector/tabs.tsx | 4 +++- .../workflow/block-selector/tool-picker.tsx | 4 +++- .../components/workflow/block-selector/types.ts | 1 + web/service/use-tools.ts | 7 +++---- 10 files changed, 43 insertions(+), 28 deletions(-) diff --git a/web/app/components/tools/mcp/mock.ts b/web/app/components/tools/mcp/mock.ts index 083e84bddb..2d497f7a22 100644 --- a/web/app/components/tools/mcp/mock.ts +++ b/web/app/components/tools/mcp/mock.ts @@ -9,6 +9,10 @@ export const listData = [ is_team_authorization: true, tools: ['aaa', 'bbb'], update_elapsed_time: 1744793369, + label: { + en_US: 'GOGOGO', + zh_Hans: 'GOGOGO', + }, }, { id: 'fdjklajfkljadslf222', @@ -20,6 +24,10 @@ export const listData = [ is_team_authorization: false, tools: [], update_elapsed_time: 1744793369, + label: { + en_US: 'GOGOGO2', + zh_Hans: 'GOGOGO2', + }, }, { id: 'fdjklajfkljadslf333', @@ -31,5 +39,9 @@ export const listData = [ is_team_authorization: true, tools: ['aaa', 'bbb'], update_elapsed_time: 1744793369, + label: { + en_US: 'GOGOGO3', + zh_Hans: 'GOGOGO3', + }, }, ] diff --git a/web/app/components/tools/mcp/provider-card.tsx b/web/app/components/tools/mcp/provider-card.tsx index 9080c45e53..53d387eb70 100644 --- a/web/app/components/tools/mcp/provider-card.tsx +++ b/web/app/components/tools/mcp/provider-card.tsx @@ -9,13 +9,13 @@ import { RiHammerFill } from '@remixicon/react' import Indicator from '@/app/components/header/indicator' import Icon from '@/app/components/plugins/card/base/card-icon' import { useFormatTimeFromNow } from './hooks' -import type { MCPProvider } from '@/app/components/tools/types' +import type { ToolWithProvider } from '../../workflow/types' import cn from '@/utils/classnames' type Props = { - currentProvider?: MCPProvider - data: MCPProvider - handleSelect: (provider: MCPProvider) => void + currentProvider?: ToolWithProvider + data: ToolWithProvider + handleSelect: (provider: ToolWithProvider) => void } const MCPCard = ({ @@ -27,7 +27,7 @@ const MCPCard = ({ const { formatTimeFromNow } = useFormatTimeFromNow() // const { locale } = useContext(I18n) // const language = getLanguage(locale) -// const { isCurrentWorkspaceManager } = useAppContext() + // const { isCurrentWorkspaceManager } = useAppContext() return (
/
-
{`${t('tools.mcp.updateTime')} ${formatTimeFromNow(data.update_elapsed_time * 1000)}`}
+
{`${t('tools.mcp.updateTime')} ${formatTimeFromNow(data.update_elapsed_time! * 1000)}`}
diff --git a/web/app/components/tools/mcp/provider-detail.tsx b/web/app/components/tools/mcp/provider-detail.tsx index 46d3077378..849736b7aa 100644 --- a/web/app/components/tools/mcp/provider-detail.tsx +++ b/web/app/components/tools/mcp/provider-detail.tsx @@ -2,11 +2,11 @@ import React from 'react' import type { FC } from 'react' import Drawer from '@/app/components/base/drawer' -import type { MCPProvider } from '@/app/components/tools/types' import cn from '@/utils/classnames' +import type { ToolWithProvider } from '../../workflow/types' type Props = { - detail?: MCPProvider + detail?: ToolWithProvider onUpdate: () => void onHide: () => void } diff --git a/web/app/components/tools/types.ts b/web/app/components/tools/types.ts index a2e5fc135d..c5a8a00acd 100644 --- a/web/app/components/tools/types.ts +++ b/web/app/components/tools/types.ts @@ -51,6 +51,9 @@ export type Collection = { labels: string[] plugin_id?: string letter?: string + // MCP Server + server_url?: string + update_elapsed_time?: number } export type ToolParameter = { @@ -169,15 +172,3 @@ export type WorkflowToolProviderResponse = { } privacy_policy: string } - -export type MCPProvider = { - id: string - author: string - name: string - icon: string | Emoji - server_url: string - type: CollectionType - is_team_authorization: boolean - tools: string[] - update_elapsed_time: number -} diff --git a/web/app/components/workflow/block-selector/all-tools.tsx b/web/app/components/workflow/block-selector/all-tools.tsx index 3ad0a41d54..7b3f62d5a7 100644 --- a/web/app/components/workflow/block-selector/all-tools.tsx +++ b/web/app/components/workflow/block-selector/all-tools.tsx @@ -31,6 +31,7 @@ type AllToolsProps = { buildInTools: ToolWithProvider[] customTools: ToolWithProvider[] workflowTools: ToolWithProvider[] + mcpTools: ToolWithProvider[] onSelect: OnSelectBlock supportAddCustomTool?: boolean onAddedCustomTool?: () => void @@ -49,6 +50,7 @@ const AllTools = ({ buildInTools, workflowTools, customTools, + mcpTools = [], supportAddCustomTool, onShowAddCustomCollectionModal, selectedTools, @@ -64,13 +66,15 @@ const AllTools = ({ const tools = useMemo(() => { let mergedTools: ToolWithProvider[] = [] if (activeTab === ToolTypeEnum.All) - mergedTools = [...buildInTools, ...customTools, ...workflowTools] + mergedTools = [...buildInTools, ...customTools, ...workflowTools, ...mcpTools] if (activeTab === ToolTypeEnum.BuiltIn) mergedTools = buildInTools if (activeTab === ToolTypeEnum.Custom) mergedTools = customTools if (activeTab === ToolTypeEnum.Workflow) mergedTools = workflowTools + if (activeTab === ToolTypeEnum.MCP) + mergedTools = mcpTools if (!hasFilter) return mergedTools.filter(toolWithProvider => toolWithProvider.tools.length > 0) @@ -80,7 +84,7 @@ const AllTools = ({ return tool.label[language].toLowerCase().includes(searchText.toLowerCase()) || tool.name.toLowerCase().includes(searchText.toLowerCase()) }) }) - }, [activeTab, buildInTools, customTools, workflowTools, searchText, language, hasFilter]) + }, [activeTab, buildInTools, customTools, workflowTools, mcpTools, searchText, language, hasFilter]) const { queryPluginsWithDebounced: fetchPlugins, diff --git a/web/app/components/workflow/block-selector/hooks.ts b/web/app/components/workflow/block-selector/hooks.ts index a8b1759506..791eb7f73f 100644 --- a/web/app/components/workflow/block-selector/hooks.ts +++ b/web/app/components/workflow/block-selector/hooks.ts @@ -51,5 +51,9 @@ export const useToolTabs = () => { key: ToolTypeEnum.Workflow, name: t('workflow.tabs.workflowTool'), }, + { + key: ToolTypeEnum.MCP, + name: 'MCP', + }, ] } diff --git a/web/app/components/workflow/block-selector/tabs.tsx b/web/app/components/workflow/block-selector/tabs.tsx index 67aaaba1a5..457315b5b8 100644 --- a/web/app/components/workflow/block-selector/tabs.tsx +++ b/web/app/components/workflow/block-selector/tabs.tsx @@ -1,6 +1,6 @@ import type { FC } from 'react' import { memo } from 'react' -import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools } from '@/service/use-tools' +import { useAllBuiltInTools, useAllCustomTools, useAllMCPTools, useAllWorkflowTools } from '@/service/use-tools' import type { BlockEnum } from '../types' import { useTabs } from './hooks' import type { ToolDefaultValue } from './types' @@ -31,6 +31,7 @@ const Tabs: FC = ({ const { data: buildInTools } = useAllBuiltInTools() const { data: customTools } = useAllCustomTools() const { data: workflowTools } = useAllWorkflowTools() + const { data: mcpTools } = useAllMCPTools() return (
e.stopPropagation()}> @@ -75,6 +76,7 @@ const Tabs: FC = ({ buildInTools={buildInTools || []} customTools={customTools || []} workflowTools={workflowTools || []} + mcpTools={mcpTools || []} /> ) } diff --git a/web/app/components/workflow/block-selector/tool-picker.tsx b/web/app/components/workflow/block-selector/tool-picker.tsx index dbb49fde75..3d2ac1cb1f 100644 --- a/web/app/components/workflow/block-selector/tool-picker.tsx +++ b/web/app/components/workflow/block-selector/tool-picker.tsx @@ -23,7 +23,7 @@ import { } from '@/service/tools' import type { CustomCollectionBackend } from '@/app/components/tools/types' import Toast from '@/app/components/base/toast' -import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools, useInvalidateAllCustomTools } from '@/service/use-tools' +import { useAllBuiltInTools, useAllCustomTools, useAllMCPTools, useAllWorkflowTools, useInvalidateAllCustomTools } from '@/service/use-tools' import cn from '@/utils/classnames' type Props = { @@ -61,6 +61,7 @@ const ToolPicker: FC = ({ const { data: customTools } = useAllCustomTools() const invalidateCustomTools = useInvalidateAllCustomTools() const { data: workflowTools } = useAllWorkflowTools() + const { data: mcpTools } = useAllMCPTools() const { builtinToolList, customToolList, workflowToolList } = useMemo(() => { if (scope === 'plugins') { @@ -162,6 +163,7 @@ const ToolPicker: FC = ({ buildInTools={builtinToolList || []} customTools={customToolList || []} workflowTools={workflowToolList || []} + mcpTools={mcpTools || []} supportAddCustomTool={supportAddCustomTool} onAddedCustomTool={handleAddedCustomTool} onShowAddCustomCollectionModal={showEditCustomCollectionModal} diff --git a/web/app/components/workflow/block-selector/types.ts b/web/app/components/workflow/block-selector/types.ts index 0abf7b9031..50e3cc24a8 100644 --- a/web/app/components/workflow/block-selector/types.ts +++ b/web/app/components/workflow/block-selector/types.ts @@ -8,6 +8,7 @@ export enum ToolTypeEnum { BuiltIn = 'built-in', Custom = 'custom', Workflow = 'workflow', + MCP = 'mcp', } export enum BlockClassificationEnum { diff --git a/web/service/use-tools.ts b/web/service/use-tools.ts index 2a785a0150..9a61a0792d 100644 --- a/web/service/use-tools.ts +++ b/web/service/use-tools.ts @@ -4,7 +4,6 @@ import type { Tool, } from '@/app/components/tools/types' import type { ToolWithProvider } from '@/app/components/workflow/types' -import type { MCPProvider } from '@/app/components/tools/types' import { useInvalid } from './use-base' import { useMutation, @@ -66,11 +65,11 @@ export const useInvalidateAllWorkflowTools = () => { const useAllMCPToolsKey = [NAME_SPACE, 'MCPTools'] export const useAllMCPTools = () => { - return useQuery({ + return useQuery({ queryKey: useAllMCPToolsKey, - // queryFn: () => get('/workspaces/current/tools/mcp'), + // queryFn: () => get('/workspaces/current/tools/mcp'), queryFn: () => { - return listData as unknown as MCPProvider[] + return listData as unknown as ToolWithProvider[] }, }) }