Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/service/core/app/tool/utils/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ export async function getClientToolPreviewNode({
avatar: item.avatar,
id: appId,
name: tool.name,
intro: tool.description,
templateType: FlowNodeTemplateTypeEnum.tools,
workflow: {
nodes: [
Expand Down
44 changes: 44 additions & 0 deletions packages/service/test/core/app/tool/utils/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,48 @@ describe('getClientToolPreviewNode', () => {
expect(result.inputs[0]?.key).toBe('q');
expect((result as any).jsonSchema).toBeUndefined();
});

it('writes mcp tool description onto preview node intro', async () => {
mocks.findById.mockReturnValueOnce({
lean: vi.fn().mockResolvedValue({
_id: '507f1f77bcf86cd799439011',
teamId: '507f1f77bcf86cd799439012',
type: AppTypeEnum.mcpToolSet,
name: 'MCP Tools',
avatar: 'mcp.svg',
intro: 'MCP toolset'
})
});
mocks.getAppVersionById.mockResolvedValueOnce({
nodes: [
{
toolConfig: {
mcpToolSet: {
toolList: [
{
name: 'search',
description: 'Search MCP resources',
inputSchema: { type: 'object', properties: { q: { type: 'string' } } }
}
]
}
}
}
],
edges: [],
chatConfig: {},
versionId: 'version-id',
versionName: 'Version 1'
});

const result = await getClientToolPreviewNode({
appId: 'mcp-507f1f77bcf86cd799439011/search',
lang: 'en'
});

expect(result.intro).toBe('Search MCP resources');
expect(result.toolConfig?.mcpTool).toEqual({
toolId: 'mcp-507f1f77bcf86cd799439011/search'
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
import { WorkflowModalContext } from '../../../context/workflowModalContext';
import { isDebugToolSource } from '@fastgpt/global/core/app/tool/utils';
import DebugToolTag from '@fastgpt/web/components/core/plugin/tool/DebugToolTag';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';

export type TemplateListProps = {
onAddNode: ({ newNodes }: { newNodes: Node<FlowNodeItemType>[] }) => void;
Expand Down Expand Up @@ -81,14 +82,20 @@ const NodeTemplateListItem = ({
const { screenToFlowPosition } = useReactFlow();
const handleParams = useContextSelector(WorkflowModalContext, (v) => v.handleParams);
const isSystemTool = templateType === TemplateTypeEnum.systemTools;
const templateAppType = (template as NodeTemplateListItemType & { appType?: AppTypeEnum })
.appType;
const isSystemToolSet = isSystemTool && template.flowNodeType === FlowNodeTypeEnum.toolSet;
const isMcpToolSet =
templateType === TemplateTypeEnum.myTools &&
template.flowNodeType === FlowNodeTypeEnum.toolSet &&
templateAppType === AppTypeEnum.mcpToolSet;
const isToolSelector = handleParams?.handleId === NodeOutputKeyEnum.selectedTools;
// 系统工具集只有在工具调用的工具选择器里才允许直接创建节点
const allowDirectAddSystemToolSet = isSystemToolSet && isToolSelector;
// 工具集只有在工具调用的工具选择器里才允许直接创建节点
const allowDirectAddToolSet = (isSystemToolSet || isMcpToolSet) && isToolSelector;
const canDragCreateNode =
!isPopover &&
(!template.isFolder || template.flowNodeType === FlowNodeTypeEnum.toolSet) &&
(!isSystemToolSet || allowDirectAddSystemToolSet);
(!(isSystemToolSet || isMcpToolSet) || allowDirectAddToolSet);
const showExpandArrow = template.isFolder || isSystemToolSet;
const isDebugTool = isDebugToolSource(template.source);

Expand Down Expand Up @@ -155,7 +162,7 @@ const NodeTemplateListItem = ({
});
}}
onClick={() => {
if (isSystemToolSet && !allowDirectAddSystemToolSet) {
if ((isSystemToolSet || isMcpToolSet) && !allowDirectAddToolSet) {
onUpdateParentId(template.id, template.source);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ export const useNodeTemplates = () => {

useDebounceEffect(
() => {
if (templateType === TemplateTypeEnum.systemTools) {
return;
}

if (searchKeyLock.current) {
return;
}
Expand All @@ -143,7 +147,7 @@ export const useNodeTemplates = () => {
source: parentSource
});
},
[searchKey, parentSource],
[searchKey, parentSource, templateType],
{
wait: 300
}
Expand All @@ -167,9 +171,12 @@ export const useNodeTemplates = () => {
setSearchKey('');
setParentId(parentId);
setParentSource(nextParentSource);
loadNodeTemplates({ parentId, source: nextParentSource });

if (templateType !== TemplateTypeEnum.systemTools) {
loadNodeTemplates({ parentId, source: nextParentSource });
}
},
[loadNodeTemplates, parentSource]
[loadNodeTemplates, parentSource, templateType]
);
const onUpdateTemplateType = useCallback(
(type: TemplateTypeEnum) => {
Expand All @@ -179,16 +186,22 @@ export const useNodeTemplates = () => {
setParentSource(undefined);
setSelectedTagIds([]);
setTemplateType(type);
loadNodeTemplates({ type });

if (type !== TemplateTypeEnum.systemTools) {
loadNodeTemplates({ type });
}
},
[loadNodeTemplates]
);
const onUpdateSelectedTagIds = useCallback(
(tags: string[]) => {
setSelectedTagIds(tags);
loadNodeTemplates({ parentId, searchVal: searchKey, tags, source: parentSource });

if (templateType !== TemplateTypeEnum.systemTools) {
loadNodeTemplates({ parentId, searchVal: searchKey, tags, source: parentSource });
}
},
[loadNodeTemplates, parentId, parentSource, searchKey]
[loadNodeTemplates, parentId, parentSource, searchKey, templateType]
);

const templates = useMemo(() => {
Expand Down
Loading