From 53b1ad7e5b6a53cdbe28a53e4db3ad8ba75fcae2 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Wed, 2 Sep 2026 11:50:46 +0000 Subject: [PATCH] fix(core): List the valid techniques when get_workflow_best_practices rejects input (#37580) --- .../get-workflow-best-practices.tool.test.ts | 31 +++++++++++++++++++ .../get-workflow-best-practices.tool.ts | 6 ++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/modules/mcp/__tests__/get-workflow-best-practices.tool.test.ts b/packages/cli/src/modules/mcp/__tests__/get-workflow-best-practices.tool.test.ts index c21452faa25..33fd5bca08b 100644 --- a/packages/cli/src/modules/mcp/__tests__/get-workflow-best-practices.tool.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/get-workflow-best-practices.tool.test.ts @@ -48,6 +48,37 @@ describe('get-workflow-best-practices MCP tool', () => { expect(tool.config.inputSchema?.technique).toBeDefined(); }); + describe('technique input schema', () => { + const techniqueSchema = () => createTool().config.inputSchema!.technique; + + test('accepts every technique key and the list sentinel', () => { + const schema = techniqueSchema(); + + for (const value of ['list', ...Object.values(WorkflowTechnique)]) { + expect(schema.safeParse(value).success).toBe(true); + } + }); + + test('names the accepted values when the technique is unknown', () => { + const result = techniqueSchema().safeParse('webhook'); + + expect(result.success).toBe(false); + const message = result.error?.issues[0]?.message ?? ''; + expect(message).not.toBe('Invalid input'); + expect(message).toContain('list'); + expect(message).toContain(WorkflowTechnique.CHATBOT); + expect(message).toContain(WorkflowTechnique.WEB_APP); + }); + + test('lists the accepted values in the parameter description', () => { + const description = techniqueSchema().description ?? ''; + + for (const value of ['list', ...Object.values(WorkflowTechnique)]) { + expect(description).toContain(value); + } + }); + }); + test('returns the full technique catalog when technique="list"', async () => { const tool = createTool(); const result = await tool.handler({ technique: 'list' }, {} as never); diff --git a/packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-best-practices.tool.ts b/packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-best-practices.tool.ts index 74e84e9c992..8d3dc06ad13 100644 --- a/packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-best-practices.tool.ts +++ b/packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-best-practices.tool.ts @@ -16,11 +16,13 @@ import type { ToolDefinition, UserCalledMCPToolEventPayload } from '../../mcp.ty const LIST_SENTINEL = 'list'; +const TECHNIQUE_CHOICES = [LIST_SENTINEL, ...Object.values(WorkflowTechnique)] as const; + const inputSchema = { technique: z - .union([z.nativeEnum(WorkflowTechnique), z.literal(LIST_SENTINEL)]) + .enum(TECHNIQUE_CHOICES) .describe( - `Workflow technique key (e.g. "chatbot", "scheduling", "triage") to fetch best-practices guidance for. Pass "${LIST_SENTINEL}" to discover all available techniques.`, + `Workflow technique key to fetch best-practices guidance for. Pass "${LIST_SENTINEL}" to discover all available techniques. One of: ${TECHNIQUE_CHOICES.join(', ')}.`, ), } satisfies z.ZodRawShape;