mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-30 16:26:59 +02:00
feat(editor): Add New tag to MCP category and registry tools (#30439)
This commit is contained in:
parent
a2835d7e88
commit
563089ba70
|
|
@ -455,6 +455,7 @@ export type SimplifiedNodeType = Pick<
|
|||
| 'outputs'
|
||||
> & {
|
||||
tag?: NodeCreatorTag;
|
||||
isNew?: boolean;
|
||||
};
|
||||
export interface SubcategoryItemProps {
|
||||
description?: string;
|
||||
|
|
|
|||
|
|
@ -63,4 +63,4 @@ export const REQUEST_NODE_FORM_URL = 'https://n8n-community.typeform.com/to/K1fB
|
|||
export const RECOMMENDED_NODES: string[] = [DATA_TABLE_NODE_TYPE, DATA_TABLE_TOOL_NODE_TYPE];
|
||||
export const BETA_NODES: string[] = ['@n8n/n8n-nodes-langchain.microsoftAgent365Trigger'];
|
||||
|
||||
export const NEW_TOOL_CATEGORIES: string[] = [AI_CATEGORY_HUMAN_IN_THE_LOOP];
|
||||
export const NEW_TOOL_CATEGORIES: string[] = [AI_CATEGORY_MCP_NODES];
|
||||
|
|
|
|||
|
|
@ -150,6 +150,10 @@ const tag = computed(() => {
|
|||
return undefined;
|
||||
});
|
||||
|
||||
// Only surface the "new" badge in search results — under the category itself
|
||||
// the parent subcategory tile already carries the badge.
|
||||
const showNewBadge = computed(() => Boolean(props.nodeType.isNew && activeViewStack.search));
|
||||
|
||||
function onDragStart(event: DragEvent): void {
|
||||
if (event.dataTransfer) {
|
||||
event.dataTransfer.effectAllowed = 'copy';
|
||||
|
|
@ -190,6 +194,7 @@ function onCommunityNodeTooltipClick(event: MouseEvent) {
|
|||
:is-official="isOfficial"
|
||||
:data-test-id="dataTestId"
|
||||
:tag="tag"
|
||||
:is-new="showNewBadge"
|
||||
@dragstart="onDragStart"
|
||||
@dragend="onDragEnd"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import type {
|
|||
SimplifiedNodeType,
|
||||
} from '@/Interface';
|
||||
import {
|
||||
finalizeItems,
|
||||
formatTriggerActionName,
|
||||
filterAndSearchNodes,
|
||||
groupItemsInSections,
|
||||
|
|
@ -33,6 +34,9 @@ import {
|
|||
AI_CATEGORY_OTHER_TOOLS,
|
||||
AI_CATEGORY_VECTOR_STORES,
|
||||
AI_CATEGORY_HUMAN_IN_THE_LOOP,
|
||||
AI_CATEGORY_MCP_NODES,
|
||||
AI_CATEGORY_ROOT_NODES,
|
||||
AI_SUBCATEGORY,
|
||||
} from '@/app/constants';
|
||||
|
||||
vi.mock('@/app/stores/settings.store', () => ({
|
||||
|
|
@ -705,6 +709,35 @@ describe('NodeCreator - utils', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('finalizeItems - MCP registry tool isNew flag', () => {
|
||||
const makeMcpNode = (subcategoriesAi: string[]) =>
|
||||
mockNodeCreateElement(undefined, {
|
||||
name: 'mcpRegistryNode',
|
||||
codex: {
|
||||
categories: ['AI'],
|
||||
subcategories: { [AI_SUBCATEGORY]: subcategoriesAi },
|
||||
},
|
||||
});
|
||||
|
||||
it('should flag registry-generated MCP tools as new', () => {
|
||||
const node = makeMcpNode([AI_CATEGORY_MCP_NODES]);
|
||||
const [result] = finalizeItems([node]) as NodeCreateElement[];
|
||||
expect(result.properties.isNew).toBe(true);
|
||||
});
|
||||
|
||||
it('should not flag MCP nodes that are also Root Nodes (e.g. McpTrigger)', () => {
|
||||
const node = makeMcpNode([AI_CATEGORY_ROOT_NODES, AI_CATEGORY_MCP_NODES]);
|
||||
const [result] = finalizeItems([node]) as NodeCreateElement[];
|
||||
expect(result.properties.isNew).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not flag tools that are not in the MCP subcategory', () => {
|
||||
const node = makeMcpNode(['Tools']);
|
||||
const [result] = finalizeItems([node]) as NodeCreateElement[];
|
||||
expect(result.properties.isNew).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('mapToolSubcategoryIcon', () => {
|
||||
it('should return "globe" for AI_CATEGORY_OTHER_TOOLS', () => {
|
||||
expect(mapToolSubcategoryIcon(AI_CATEGORY_OTHER_TOOLS)).toBe('globe');
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
AI_CATEGORY_HUMAN_IN_THE_LOOP,
|
||||
AI_CATEGORY_MCP_NODES,
|
||||
AI_CATEGORY_OTHER_TOOLS,
|
||||
AI_CATEGORY_ROOT_NODES,
|
||||
AI_CATEGORY_VECTOR_STORES,
|
||||
AI_SUBCATEGORY,
|
||||
AI_TRANSFORM_NODE_TYPE,
|
||||
|
|
@ -288,7 +289,17 @@ export const removePreviewToken = (key: string) =>
|
|||
export const isNodePreviewKey = (key = '') => key.includes(COMMUNITY_NODE_TYPE_PREVIEW_TOKEN);
|
||||
|
||||
function applyNodeTags(element: INodeCreateElement): INodeCreateElement {
|
||||
if (element.type !== 'node' || element.properties.tag) return element;
|
||||
if (element.type !== 'node') return element;
|
||||
|
||||
const aiSubcategories = element.properties.codex?.subcategories?.[AI_SUBCATEGORY] ?? [];
|
||||
if (
|
||||
aiSubcategories.includes(AI_CATEGORY_MCP_NODES) &&
|
||||
!aiSubcategories.includes(AI_CATEGORY_ROOT_NODES)
|
||||
) {
|
||||
element.properties.isNew = true;
|
||||
}
|
||||
|
||||
if (element.properties.tag) return element;
|
||||
|
||||
if (RECOMMENDED_NODES.includes(element.properties.name)) {
|
||||
element.properties.tag = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user