mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-19 11:01:15 +00:00
feat(MCP Client Tool Node): Add MCP Client Tool Node to connect to MCP servers over SSE (#14464)
Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in> Co-authored-by: JP van Oosten <jp@n8n.io>
This commit is contained in:
@@ -6,6 +6,7 @@ import type {
|
||||
SimplifiedNodeType,
|
||||
} from '@/Interface';
|
||||
import {
|
||||
AI_CATEGORY_MCP_NODES,
|
||||
AI_CATEGORY_ROOT_NODES,
|
||||
AI_CATEGORY_TOOLS,
|
||||
AI_CODE_NODE_TYPE,
|
||||
@@ -222,16 +223,17 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
|
||||
const aiSubNodes = difference(aiNodes, aiRootNodes);
|
||||
|
||||
aiSubNodes.forEach((node) => {
|
||||
const section = node.properties.codex?.subcategories?.[AI_SUBCATEGORY]?.[0];
|
||||
const subcategories = node.properties.codex?.subcategories ?? {};
|
||||
const section = subcategories[AI_SUBCATEGORY]?.[0];
|
||||
|
||||
if (section) {
|
||||
const subSection = node.properties.codex?.subcategories?.[section]?.[0];
|
||||
const subSection = subcategories[section]?.[0];
|
||||
const sectionKey = subSection ?? section;
|
||||
const currentItems = sectionsMap.get(sectionKey)?.items ?? [];
|
||||
const isSubnodesSection =
|
||||
!node.properties.codex?.subcategories?.[AI_SUBCATEGORY].includes(
|
||||
AI_CATEGORY_ROOT_NODES,
|
||||
);
|
||||
const isSubnodesSection = !(
|
||||
subcategories[AI_SUBCATEGORY].includes(AI_CATEGORY_ROOT_NODES) ||
|
||||
subcategories[AI_SUBCATEGORY].includes(AI_CATEGORY_MCP_NODES)
|
||||
);
|
||||
|
||||
let title = section;
|
||||
if (isSubnodesSection) {
|
||||
|
||||
@@ -57,12 +57,18 @@ export function subcategorizeItems(items: SimplifiedNodeType[]) {
|
||||
// Only some subcategories are allowed
|
||||
let subcategories: string[] = [DEFAULT_SUBCATEGORY];
|
||||
|
||||
WHITE_LISTED_SUBCATEGORIES.forEach((category) => {
|
||||
const matchedSubcategories = WHITE_LISTED_SUBCATEGORIES.flatMap((category) => {
|
||||
if (item.codex?.categories?.includes(category)) {
|
||||
subcategories = item.codex?.subcategories?.[category] ?? [];
|
||||
return item.codex?.subcategories?.[category] ?? [];
|
||||
}
|
||||
|
||||
return [];
|
||||
});
|
||||
|
||||
if (matchedSubcategories.length > 0) {
|
||||
subcategories = matchedSubcategories;
|
||||
}
|
||||
|
||||
subcategories.forEach((subcategory: string) => {
|
||||
if (!acc[subcategory]) {
|
||||
acc[subcategory] = [];
|
||||
|
||||
@@ -118,6 +118,7 @@ export const BAMBOO_HR_NODE_TYPE = 'n8n-nodes-base.bambooHr';
|
||||
export const CALENDLY_TRIGGER_NODE_TYPE = 'n8n-nodes-base.calendlyTrigger';
|
||||
export const CODE_NODE_TYPE = 'n8n-nodes-base.code';
|
||||
export const AI_CODE_NODE_TYPE = '@n8n/n8n-nodes-langchain.code';
|
||||
export const AI_MCP_TOOL_NODE_TYPE = '@n8n/n8n-nodes-langchain.mcpClientTool';
|
||||
export const CRON_NODE_TYPE = 'n8n-nodes-base.cron';
|
||||
export const CLEARBIT_NODE_TYPE = 'n8n-nodes-base.clearbit';
|
||||
export const FILTER_NODE_TYPE = 'n8n-nodes-base.filter';
|
||||
@@ -298,6 +299,7 @@ export const AI_CATEGORY_DOCUMENT_LOADERS = 'Document Loaders';
|
||||
export const AI_CATEGORY_TEXT_SPLITTERS = 'Text Splitters';
|
||||
export const AI_CATEGORY_OTHER_TOOLS = 'Other Tools';
|
||||
export const AI_CATEGORY_ROOT_NODES = 'Root Nodes';
|
||||
export const AI_CATEGORY_MCP_NODES = 'Model Context Protocol';
|
||||
export const AI_UNCATEGORIZED_CATEGORY = 'Miscellaneous';
|
||||
export const AI_CODE_TOOL_LANGCHAIN_NODE_TYPE = '@n8n/n8n-nodes-langchain.toolCode';
|
||||
export const AI_WORKFLOW_TOOL_LANGCHAIN_NODE_TYPE = '@n8n/n8n-nodes-langchain.toolWorkflow';
|
||||
|
||||
@@ -46,7 +46,12 @@ function sanitizeFromAiParameterName(s: string) {
|
||||
}
|
||||
|
||||
// nodeName | [nodeName, highestUnsupportedVersion]
|
||||
const NODE_DENYLIST = ['toolCode', 'toolHttpRequest', ['toolWorkflow', 1.2]] as const;
|
||||
const NODE_DENYLIST = [
|
||||
'toolCode',
|
||||
'toolHttpRequest',
|
||||
'mcpClientTool',
|
||||
['toolWorkflow', 1.2],
|
||||
] as const;
|
||||
|
||||
const PATH_DENYLIST = [
|
||||
'parameters.name',
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
AI_MCP_TOOL_NODE_TYPE,
|
||||
LIST_LIKE_NODE_OPERATIONS,
|
||||
MAIN_HEADER_TABS,
|
||||
NODE_POSITION_CONFLICT_ALLOWLIST,
|
||||
@@ -281,7 +282,11 @@ export function getGenericHints({
|
||||
const nodeHints: NodeHint[] = [];
|
||||
|
||||
// tools hints
|
||||
if (node?.type.toLocaleLowerCase().includes('tool') && hasNodeRun) {
|
||||
if (
|
||||
node?.type.toLocaleLowerCase().includes('tool') &&
|
||||
node?.type !== AI_MCP_TOOL_NODE_TYPE &&
|
||||
hasNodeRun
|
||||
) {
|
||||
const stringifiedParameters = JSON.stringify(workflowNode.parameters);
|
||||
if (!stringifiedParameters.includes('$fromAI')) {
|
||||
nodeHints.push({
|
||||
|
||||
Reference in New Issue
Block a user