Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,35 @@ The addon uses a **Vite plugin workaround** to inject middleware (see `packages/
- Solution: Inject a Vite plugin via `viteFinal` that adds `/mcp` endpoint
- Handler in `mcp-handler.ts` creates MCP servers using `tmcp` with HTTP transport

**Toolset Configuration:**

The addon supports configuring which toolsets are enabled:

- **Addon Options**: Configure default toolsets in `.storybook/main.js`:
```typescript
{
name: '@storybook/addon-mcp',
options: {
toolsets: {
storiesDevelopment: true, // get-story-urls, get-ui-building-instructions
componentDocumentation: true, // list-all-components, get-component-documentation
}
}
}
```
- **Per-Request Override**: MCP clients can override toolsets per-request using the `X-MCP-Toolsets` header:
- Header format: comma-separated list (e.g., `storiesDevelopment,componentDocumentation`)
- When header is present, only specified toolsets are enabled (others are disabled)
- When header is absent, addon options are used
- **Tool Enablement**: Tools use the `enabled` callback to check if their toolset is active:
```typescript
server.tool({
name: 'my-tool',
enabled: () => server.ctx.custom?.toolsets?.storiesDevelopment ?? true,
}, handler);
```
- **Context-Aware**: The `getToolsets()` function in `mcp-handler.ts` parses the header and returns enabled toolsets, which are passed to tools via `AddonContext.toolsets`

### MCP Library Architecture

The `@storybook/mcp` package (in `packages/mcp`) is framework-agnostic:
Expand Down
82 changes: 79 additions & 3 deletions .github/instructions/addon-mcp.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,61 @@ This is a Storybook addon that runs an MCP (Model Context Protocol) server withi
- **MCP Server**: Built using `tmcp` library with HTTP transport
- **Vite Plugin Middleware**: Workaround to inject `/mcp` endpoint into Storybook's dev server
- **Tools System**: Extensible tool registration using `server.tool()` method
- **Toolsets Configuration**: Configurable tool groups that can be toggled via addon options or per-request headers
- **Context-Based Architecture**: AddonContext passed through to all tools containing Storybook options and runtime info
- **Schema Validation**: Uses Valibot for JSON schema validation via `@tmcp/adapter-valibot`
- **Telemetry**: Usage tracking with opt-out via Storybook's `disableTelemetry` config

### Toolsets

The addon supports two toolsets that can be enabled/disabled:

1. **`storiesDevelopment`** (default: true)
- `get-story-urls`: Retrieve story URLs from Storybook
- `get-ui-building-instructions`: Provide UI development guidelines

2. **`componentDocumentation`** (default: true)
- `list-all-components`: List all available components from manifest
- `get-component-documentation`: Get detailed component documentation
- Requires experimental feature flag `features.experimentalComponentsManifest`

**Configuration Methods:**

1. **Addon Options** (`.storybook/main.js`):

```typescript
{
name: '@storybook/addon-mcp',
options: {
toolsets: {
storiesDevelopment: true,
componentDocumentation: true,
}
}
}
```

2. **Per-Request Header** (`X-MCP-Toolsets`):
- Comma-separated list of toolset names
- Example: `X-MCP-Toolsets: storiesDevelopment,componentDocumentation`
- When present, overrides addon options (all toolsets default to disabled except those in header)
- When absent, uses addon options

**Implementation:**

- `getToolsets()` function in `mcp-handler.ts` parses the header and merges with addon options
- Tools use `enabled` callback to check if their toolset is active:
```typescript
server.tool(
{
name: 'my-tool',
enabled: () => server.ctx.custom?.toolsets?.storiesDevelopment ?? true,
},
handler,
);
```
- `AddonContext.toolsets` contains the resolved toolset configuration

### File Structure

```
Expand Down Expand Up @@ -250,6 +301,8 @@ To add a new MCP tool to the addon:
title: 'My Tool',
description: 'What this tool does',
schema: MyToolInput,
// Optional: Enable/disable based on toolset configuration
enabled: () => server.ctx.custom?.toolsets?.storiesDevelopment ?? true,
},
async (input: MyToolInput) => {
try {
Expand All @@ -267,7 +320,7 @@ To add a new MCP tool to the addon:
}
```

5. Import and register in `src/mcp-handler.ts` within `createAddonMcpHandler()`:
5. Import and register in `src/mcp-handler.ts` within `initializeMCPServer()`:

```typescript
import { addMyTool } from './tools/my-tool.ts';
Expand All @@ -276,7 +329,26 @@ To add a new MCP tool to the addon:
await addMyTool(server);
```

6. Add telemetry tracking if needed (see existing tools for examples)
6. If adding a new toolset, update the `AddonOptions` schema in `src/types.ts` to include the new toolset:

```typescript
export const AddonOptions = v.object({
toolsets: v.optional(
v.object({
storiesDevelopment: v.exactOptional(v.boolean(), true),
componentDocumentation: v.exactOptional(v.boolean(), true),
myNewToolset: v.exactOptional(v.boolean(), true), // Add your toolset
}),
{
storiesDevelopment: true,
componentDocumentation: true,
myNewToolset: true,
},
),
});
```

7. Add telemetry tracking if needed (see existing tools for examples)

## Storybook Integration

Expand Down Expand Up @@ -366,7 +438,11 @@ const addonContext: AddonContext = {
});
}
},
onGetComponentDocumentation: async ({ input, foundComponents, notFoundIds }) => {
onGetComponentDocumentation: async ({
input,
foundComponents,
notFoundIds,
}) => {
if (!disableTelemetry && server) {
await collectTelemetry({
event: 'tool:getComponentDocumentation',
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ on:

jobs:
build-mcp:
permissions:
id-token: write # used to upload artifacts to codecov
name: Build @storybook/mcp
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -151,8 +153,6 @@ jobs:
run: pnpm format --check

collect-coverage:
permissions:
id-token: write
name: Collect coverage and test results
runs-on: ubuntu-latest
needs: [test-mcp, test-addon-mcp]
Expand Down
13 changes: 12 additions & 1 deletion apps/internal-storybook/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,18 @@ const config = defineMain({
files: '**/*.stories.@(js|jsx|ts|tsx)',
},
],
addons: ['@storybook/addon-docs', '@storybook/addon-mcp'],
addons: [
'@storybook/addon-docs',
{
name: '@storybook/addon-mcp',
options: {
toolsets: {
// storiesDevelopment: false,
// componentDocumentation: false,
},
},
},
],
framework: '@storybook/react-vite',
logLevel: 'debug',
core: {
Expand Down
46 changes: 46 additions & 0 deletions packages/addon-mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,52 @@ npm run storybook

The MCP server will be available at `<your_storybook_dev_server_origin>/mcp` when Storybook is running.

### Configuration

#### Addon Options

You can configure which toolsets are enabled by default in your `.storybook/main.js`:

```javascript
// .storybook/main.js
export default {
addons: [
{
name: '@storybook/addon-mcp',
options: {
toolsets: {
storiesDevelopment: true, // Tools for story URL retrieval and UI building instructions (default: true)
componentDocumentation: true, // Tools for component manifest and documentation (default: true, requires experimental feature)
},
},
},
],
};
```

**Available Toolsets:**

- `storiesDevelopment`: Enables [Core Tools](#core-tools)
- `componentDocumentation`: Enables [Component Documentation Tools](#component-documentation-tools-experimental)

Disabling the Core Tools is useful when you want to try out the same experience that your external component consumers will get, because they only get the Component Documentation Tools.

#### Configuring toolsets with headers

You can also configure the available toolsets when setting up the MCP Server in your MCP Client by setting the `X-MCP-Toolsets` header. The header is a comma-separated list of toolset names, `X-MCP-Toolsets: storiesDevelopment,componentDocumentation`. Eg. to configure your client to only have the Component Documentation Tools, the `.mcp.json`-file could look like this (format depends on the exact client you're using):

```json
{
"storybook-mcp": {
"url": "http://localhost:6006/mcp",
"type": "http",
"headers": {
"X-MCP-Toolsets": "componentDocumentation"
}
}
}
```

### Configuring Your Agent

> [!NOTE]
Expand Down
Loading
Loading