UNPKG

n8n

Version:

n8n Workflow Automation Tool

127 lines 5.87 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createGetWorkflowBestPracticesTool = void 0; const best_practices_1 = require("@n8n/workflow-sdk/prompts/best-practices"); const sdk_reference_1 = require("@n8n/workflow-sdk/prompts/sdk-reference"); const zod_1 = __importDefault(require("zod")); const constants_1 = require("./constants"); const mcp_constants_1 = require("../../mcp.constants"); const LIST_SENTINEL = 'list'; const inputSchema = { technique: zod_1.default .union([zod_1.default.nativeEnum(best_practices_1.WorkflowTechnique), zod_1.default.literal(LIST_SENTINEL)]) .describe(`Workflow technique key (e.g. "chatbot", "scheduling", "triage") to fetch best-practices guidance for. Pass "${LIST_SENTINEL}" to discover all available techniques.`), }; const availableTechniqueSchema = zod_1.default.object({ technique: zod_1.default.string(), description: zod_1.default.string(), hasDocumentation: zod_1.default.boolean(), }); const outputSchema = { technique: zod_1.default .string() .describe('The requested technique key, or "list" when listing all available techniques.'), message: zod_1.default.string().describe('Human-readable summary of the response.'), documentation: zod_1.default .string() .optional() .describe('Best-practices documentation for the requested technique, when one with documentation was requested.'), availableTechniques: zod_1.default .array(availableTechniqueSchema) .optional() .describe('All available techniques, returned when "list" was requested.'), }; function buildListResponse(canvasGroupsEnabled) { const availableTechniques = Object.entries(best_practices_1.TechniqueDescription).map(([key, description]) => ({ technique: key, description, hasDocumentation: best_practices_1.bestPracticesRegistry[key] !== undefined, })); const documentedCount = availableTechniques.filter((t) => t.hasDocumentation).length; const message = `Found ${availableTechniques.length} workflow techniques. ${documentedCount} have detailed best-practices documentation. Call this tool again with a specific technique key to fetch its guidance.`; const text = [ message, '', ...availableTechniques.map((t) => `- ${t.technique}${t.hasDocumentation ? '' : ' (no detailed documentation yet)'}${t.description}`), ...(canvasGroupsEnabled ? ['', sdk_reference_1.GROUPING_GUIDANCE] : []), ].join('\n'); return { text, hasDocumentation: false, structured: { technique: LIST_SENTINEL, message, availableTechniques, }, }; } function buildTechniqueResponse(technique) { const doc = best_practices_1.bestPracticesRegistry[technique]; if (doc) { const documentation = doc.getDocumentation(); return { text: documentation, hasDocumentation: true, structured: { technique, message: `Best-practices documentation for "${technique}" retrieved.`, documentation, }, }; } const description = best_practices_1.TechniqueDescription[technique]; const message = `Technique "${technique}" (${description}) does not have detailed best-practices documentation yet — proceed with general n8n knowledge.`; return { text: message, hasDocumentation: false, structured: { technique, message } }; } const createGetWorkflowBestPracticesTool = (user, telemetry, { canvasGroupsEnabled }) => ({ name: constants_1.MCP_GET_WORKFLOW_BEST_PRACTICES_TOOL.toolName, config: { description: 'Required planning step when building a workflow, and only then. Get best-practices guidance (recommended nodes, patterns, and common pitfalls) for a specific workflow technique before searching for nodes or writing code. Call once per relevant technique. Use technique="list" first if unsure which techniques apply.', inputSchema, outputSchema, annotations: { title: constants_1.MCP_GET_WORKFLOW_BEST_PRACTICES_TOOL.displayTitle, readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false, }, }, handler: async ({ technique }) => { const telemetryPayload = { user_id: user.id, tool_name: constants_1.MCP_GET_WORKFLOW_BEST_PRACTICES_TOOL.toolName, parameters: { technique }, }; try { const response = technique === LIST_SENTINEL ? buildListResponse(canvasGroupsEnabled) : buildTechniqueResponse(technique); telemetryPayload.results = { success: true, data: { technique, hasDocumentation: response.hasDocumentation, }, }; telemetry.track(mcp_constants_1.USER_CALLED_MCP_TOOL_EVENT, telemetryPayload); return { content: [{ type: 'text', text: response.text }], structuredContent: response.structured, }; } catch (error) { telemetryPayload.results = { success: false, error: error instanceof Error ? error.message : String(error), }; telemetry.track(mcp_constants_1.USER_CALLED_MCP_TOOL_EVENT, telemetryPayload); throw error; } }, }); exports.createGetWorkflowBestPracticesTool = createGetWorkflowBestPracticesTool; //# sourceMappingURL=get-workflow-best-practices.tool.js.map