From 61f0f3c243e1038b9da48ba9d269b064f3be2bdf Mon Sep 17 00:00:00 2001 From: Jack Wotherspoon Date: Wed, 19 Nov 2025 09:44:30 -0500 Subject: [PATCH] fix: allow MCP prompts with spaces in name (#12910) Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com> --- .../cli/src/services/McpPromptLoader.test.ts | 34 +++++++++++++++++++ packages/cli/src/services/McpPromptLoader.ts | 3 +- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/services/McpPromptLoader.test.ts b/packages/cli/src/services/McpPromptLoader.test.ts index e90a3720b4..44efefafc1 100644 --- a/packages/cli/src/services/McpPromptLoader.test.ts +++ b/packages/cli/src/services/McpPromptLoader.test.ts @@ -175,6 +175,40 @@ describe('McpPromptLoader', () => { expect(commands[0].kind).toBe(CommandKind.MCP_PROMPT); }); + it('should sanitize prompt names by replacing spaces with hyphens', async () => { + const mockPromptWithSpaces = { + ...mockPrompt, + name: 'Prompt Name', + }; + vi.spyOn(cliCore, 'getMCPServerPrompts').mockReturnValue([ + mockPromptWithSpaces, + ]); + + const loader = new McpPromptLoader(mockConfigWithPrompts); + const commands = await loader.loadCommands(new AbortController().signal); + + expect(commands).toHaveLength(1); + expect(commands[0].name).toBe('Prompt-Name'); + expect(commands[0].kind).toBe(CommandKind.MCP_PROMPT); + }); + + it('should trim whitespace from prompt names before sanitizing', async () => { + const mockPromptWithWhitespace = { + ...mockPrompt, + name: ' Prompt Name ', + }; + vi.spyOn(cliCore, 'getMCPServerPrompts').mockReturnValue([ + mockPromptWithWhitespace, + ]); + + const loader = new McpPromptLoader(mockConfigWithPrompts); + const commands = await loader.loadCommands(new AbortController().signal); + + expect(commands).toHaveLength(1); + expect(commands[0].name).toBe('Prompt-Name'); + expect(commands[0].kind).toBe(CommandKind.MCP_PROMPT); + }); + it('should handle prompt invocation successfully', async () => { const loader = new McpPromptLoader(mockConfigWithPrompts); const commands = await loader.loadCommands(new AbortController().signal); diff --git a/packages/cli/src/services/McpPromptLoader.ts b/packages/cli/src/services/McpPromptLoader.ts index 35cc80313e..76c13474e7 100644 --- a/packages/cli/src/services/McpPromptLoader.ts +++ b/packages/cli/src/services/McpPromptLoader.ts @@ -38,7 +38,8 @@ export class McpPromptLoader implements ICommandLoader { for (const serverName in mcpServers) { const prompts = getMCPServerPrompts(this.config, serverName) || []; for (const prompt of prompts) { - const commandName = `${prompt.name}`; + // Sanitize prompt names to ensure they are valid slash commands (e.g. "Prompt Name" -> "Prompt-Name") + const commandName = `${prompt.name}`.trim().replace(/\s+/g, '-'); const newPromptCommand: SlashCommand = { name: commandName, description: prompt.description || `Invoke prompt ${prompt.name}`,