diff --git a/.changeset/clean-bears-brush.md b/.changeset/clean-bears-brush.md new file mode 100644 index 00000000..dee897fc --- /dev/null +++ b/.changeset/clean-bears-brush.md @@ -0,0 +1,5 @@ +--- +'@storybook/addon-mcp': patch +--- + +Improve `/mcp` HTML response diff --git a/packages/addon-mcp/src/preset.test.ts b/packages/addon-mcp/src/preset.test.ts index effe1b7f..723fcbe4 100644 --- a/packages/addon-mcp/src/preset.test.ts +++ b/packages/addon-mcp/src/preset.test.ts @@ -1,6 +1,7 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'; import type { Options } from 'storybook/internal/types'; import { experimental_devServer } from './preset.ts'; +import * as runStoryTests from './tools/run-story-tests.ts'; describe('experimental_devServer', () => { let mockApp: any; @@ -67,6 +68,53 @@ describe('experimental_devServer', () => { expect(mockRes.end).toHaveBeenCalledWith(expect.stringContaining(' { + vi.spyOn(runStoryTests, 'getAddonVitestConstants').mockResolvedValue(undefined); + const manifestEnabledOptions = { + presets: { + apply: vi.fn((key: string) => { + if (key === 'features') { + return Promise.resolve({ experimentalComponentsManifest: true }); + } + if (key === 'experimental_manifests') { + return Promise.resolve({}); + } + return Promise.resolve(undefined); + }), + }, + } as unknown as Options; + + const handlers: Record = {}; + mockApp.get = vi.fn((path: string, handler: any) => { + handlers[path] = handler; + }); + + await (experimental_devServer as any)(mockApp, manifestEnabledOptions); + const getMcpHandler = handlers['/mcp']; + expect(getMcpHandler).toBeDefined(); + + const mockReq = { + headers: { + accept: 'text/html', + }, + } as any; + const mockRes = { + writeHead: vi.fn(), + end: vi.fn(), + } as any; + + await getMcpHandler(mockReq, mockRes); + + expect(mockRes.end).toHaveBeenCalledWith( + expect.stringContaining('This toolset requires Storybook 10.3.0+ with'), + ); + expect(mockRes.end).toHaveBeenCalledWith( + expect.stringContaining( + 'View the component manifest debugger.', + ), + ); + }); + it('should handle POST requests as MCP protocol', async () => { await (experimental_devServer as any)(mockApp, mockOptions); diff --git a/packages/addon-mcp/src/preset.ts b/packages/addon-mcp/src/preset.ts index 50797336..56ad41c9 100644 --- a/packages/addon-mcp/src/preset.ts +++ b/packages/addon-mcp/src/preset.ts @@ -120,7 +120,7 @@ export const experimental_devServer: PresetPropertyFn<'experimental_devServer'> }); } - // Browser request - send HTML with redirect + // Browser request - send HTML res.writeHead(200, { 'Content-Type': 'text/html' }); let docsNotice = ''; @@ -137,7 +137,7 @@ export const experimental_devServer: PresetPropertyFn<'experimental_devServer'> const testNoticeLines = [ !addonVitestConstants && - `This toolset requires @storybook/addon-vitest. Learn how to set it up`, + `This toolset requires Storybook 10.3.0+ with @storybook/addon-vitest. Learn how to set it up`, !a11yEnabled && `Add @storybook/addon-a11y for accessibility testing. Learn more`, ].filter(Boolean); @@ -150,19 +150,17 @@ export const experimental_devServer: PresetPropertyFn<'experimental_devServer'> : ''; const html = htmlTemplate - .replace( - '{{REDIRECT_META}}', - manifestStatus.available - ? // redirect the user to the component manifest page after 10 seconds - '' - : // ... or hide the message about redirection - '', - ) .replaceAll('{{DEV_STATUS}}', isDevEnabled ? 'enabled' : 'disabled') .replaceAll('{{DOCS_STATUS}}', isDocsEnabled ? 'enabled' : 'disabled') .replace('{{DOCS_NOTICE}}', docsNotice) .replaceAll('{{TEST_STATUS}}', isTestEnabled ? 'enabled' : 'disabled') .replace('{{TEST_NOTICE}}', testNotice) + .replace( + '{{MANIFEST_DEBUGGER_LINK}}', + manifestStatus.available + ? '

View the component manifest debugger.

' + : '', + ) .replace('{{A11Y_BADGE}}', a11yBadge); res.end(html); }); diff --git a/packages/addon-mcp/src/template.html b/packages/addon-mcp/src/template.html index 429e8359..4a9ab260 100644 --- a/packages/addon-mcp/src/template.html +++ b/packages/addon-mcp/src/template.html @@ -1,7 +1,6 @@ - {{REDIRECT_META}}