55This is a ** pnpm monorepo** with two MCP implementations:
66
77- ** ` packages/addon-mcp ` ** : Storybook addon using ` tmcp ` , exposes MCP server at ` /mcp ` via Vite middleware
8+ - Provides addon-specific tools (story URLs, UI building instructions)
9+ - ** Imports and reuses tools from ` @storybook/mcp ` package** for component manifest features
10+ - Extends ` StorybookContext ` with addon-specific configuration (` AddonContext ` )
811- ** ` packages/mcp ` ** : Standalone MCP library using ` tmcp ` , reusable outside Storybook
12+ - Provides reusable component manifest tools (list components, get documentation)
13+ - Exports tools and types for consumption by addon-mcp
914- ** ` apps/internal-storybook ` ** : Test environment for addon integration
1015
1116** Both packages use ` tmcp ` ** with HTTP transport and Valibot schema validation for consistent APIs.
@@ -25,6 +30,7 @@ The `@storybook/mcp` package (in `packages/mcp`) is framework-agnostic:
2530- Uses ` tmcp ` with HTTP transport and Valibot schema validation
2631- Factory pattern: ` createStorybookMcpHandler() ` returns a request handler
2732- Context-based: handlers accept ` StorybookContext ` to override source URLs
33+ - ** Exports tools and types** for reuse by ` addon-mcp ` and other consumers
2834
2935## Development Environment
3036
@@ -95,6 +101,8 @@ import pkgJson from '../package.json' with { type: 'json' };
95101
96102### In addon package (` packages/addon-mcp ` ):
97103
104+ ** Option 1: Addon-specific tools** (for tools that require Storybook addon context):
105+
981061 . Create ` src/tools/my-tool.ts ` :
99107
100108``` typescript
@@ -104,8 +112,8 @@ import type { AddonContext } from '../types.ts';
104112
105113export const MY_TOOL_NAME = ' my_tool' ;
106114
107- const MyToolInput = v .object ({
108- param: v .string ()
115+ const MyToolInput = v .object ({
116+ param: v .string (),
109117});
110118
111119type MyToolInput = v .InferOutput <typeof MyToolInput >;
@@ -128,30 +136,65 @@ export async function addMyTool(server: McpServer<any, AddonContext>) {
128136}
129137```
130138
131- 2 . Import and call in ` src/mcp-handler.ts ` within ` createAddonMcpHandler `
139+ 2 . Import and call in ` src/mcp-handler.ts ` within ` initializeMCPServer `
140+
141+ ** Option 2: Reuse tools from ` @storybook/mcp ` ** (for component manifest features):
142+
143+ 1 . Import the tool from ` @storybook/mcp ` in ` src/mcp-handler.ts ` :
144+
145+ ``` typescript
146+ import { addMyTool , MY_TOOL_NAME } from ' @storybook/mcp' ;
147+ ```
148+
149+ 2 . Call it conditionally based on feature flags (see component manifest tools example)
150+ 3 . Ensure ` AddonContext ` extends ` StorybookContext ` for compatibility
151+ 4 . Pass the ` source ` URL in context for manifest-based tools
132152
133153### In mcp package (` packages/mcp ` ):
134154
1351551 . Create ` src/tools/my-tool.ts ` :
136156
137157``` typescript
158+ export const MY_TOOL_NAME = ' my-tool' ;
159+
138160export async function addMyTool(server : McpServer <any , StorybookContext >) {
139- server .tool ({ name: ' my_tool' , description: ' What it does' }, async () => ({
140- content: [{ type: ' text' , text: ' result' }],
141- }));
161+ server .tool (
162+ { name: MY_TOOL_NAME , description: ' What it does' },
163+ async () => ({
164+ content: [{ type: ' text' , text: ' result' }],
165+ }),
166+ );
142167}
143168```
144169
1451702 . Import and call in ` src/index.ts ` within ` createStorybookMcpHandler `
146171
172+ 3 . ** Export for reuse** in ` src/index.ts ` :
173+
174+ ``` typescript
175+ export { addMyTool , MY_TOOL_NAME } from ' ./tools/my-tool.ts' ;
176+ ```
177+
147178## Integration Points
148179
180+ ** Tool Reuse Between Packages:**
181+
182+ - ` addon-mcp ` depends on ` @storybook/mcp ` (workspace dependency)
183+ - ` AddonContext ` extends ` StorybookContext ` to ensure type compatibility
184+ - Component manifest tools are conditionally registered based on feature flags:
185+ - Checks ` features.experimentalComponentsManifest ` flag
186+ - Checks for ` experimental_componentManifestGenerator ` preset
187+ - Only registers ` addListAllComponentsTool ` and ` addGetComponentDocumentationTool ` when enabled
188+ - Context includes ` source ` URL pointing to ` /manifests/components.json ` endpoint
189+
149190** Storybook internals used:**
150191
151192- ` storybook/internal/csf ` - ` storyNameFromExport() ` for story name conversion
152193- ` storybook/internal/types ` - TypeScript types for Options, StoryIndex
153194- ` storybook/internal/node-logger ` - Logging utilities
154195- Framework detection via ` options.presets.apply('framework') `
196+ - Feature flags via ` options.presets.apply('features') `
197+ - Component manifest generator via ` options.presets.apply('experimental_componentManifestGenerator') `
155198
156199** Story URL generation:**
157200
0 commit comments