Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions .changeset/eighty-dryers-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@storybook/addon-mcp': patch
Comment thread
JReinhold marked this conversation as resolved.
---

Add support for MCP App, rendering stories directly in the agent chat in MCP clients that support it
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tool has been renamed from get-story-urls to preview-stories, which is a breaking change for users who have configured MCP client permissions to allow/deny the old tool name. While the changeset marks this as a patch, consider documenting this breaking change in the changeset description and providing migration guidance (e.g., updating MCP client configuration files like .claude/settings.local.json).

Suggested change
Add support for MCP App, rendering stories directly in the agent chat in MCP clients that support it
Add support for MCP App, rendering stories directly in the agent chat in MCP clients that support it.
Note: the story preview tool has been renamed from `get-story-urls` to `preview-stories`. This can be a
breaking change for MCP clients that have explicit allow/deny lists based on tool names.
Migration guidance:
- Update your MCP client configuration (for example, `.claude/settings.local.json` or equivalent) to
allow the new `preview-stories` tool.
- If you previously allowed or denied `get-story-urls`, replace it with `preview-stories` in your
configuration. Some clients may allow you to list both names during a transition period.

Copilot uses AI. Check for mistakes.
2 changes: 1 addition & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"Bash(git checkout:*)",
"Bash(git add:*)",
"mcp__storybook-addon-mcp__get-storybook-story-instructions",
"mcp__storybook-addon-mcp__get-story-urls"
"mcp__storybook-addon-mcp__preview-stories"
],
"deny": [],
"ask": []
Expand Down
10 changes: 7 additions & 3 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ The addon supports configuring which toolsets are enabled:
name: '@storybook/addon-mcp',
options: {
toolsets: {
dev: true, // get-story-urls, get-storybook-story-instructions
docs: true, // list-all-components, get-component-documentation
dev: true, // preview-stories, get-storybook-story-instructions
docs: true, // list-all-documentation, get-component-documentation
},
experimentalFormat: 'markdown' // Output format: 'markdown' (default) or 'xml'
}
Expand Down Expand Up @@ -171,7 +171,7 @@ import pkgJson from '../package.json' with { type: 'json' };

**Naming:**

- Constants: `SCREAMING_SNAKE_CASE` (e.g., `GET_STORY_URLS_TOOL_NAME`)
- Constants: `SCREAMING_SNAKE_CASE` (e.g., `PREVIEW_STORIES_TOOL_NAME`)
- Functions: `camelCase`
- Types: `PascalCase`

Expand Down Expand Up @@ -376,3 +376,7 @@ When working on data validation, refer to the following resources:

- https://valibot.dev/
- https://github.com/paoloricciuti/tmcp/tree/main/packages/adapter-valibot

When working with MCP Apps and/or the `preview-stories.ts` file, refer to the MCP App specification:

- https://raw.githubusercontent.com/modelcontextprotocol/ext-apps/refs/heads/main/specification/draft/apps.mdx
14 changes: 7 additions & 7 deletions .github/instructions/addon-mcp.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ This is a Storybook addon that runs an MCP (Model Context Protocol) server withi
The addon supports two toolsets that can be enabled/disabled:

1. **`dev`** (default: true)
- `get-story-urls`: Retrieve story URLs from Storybook
- `preview-stories`: Retrieve story preview URLs from Storybook
- `get-storybook-story-instructions`: Provide UI development guidelines

2. **`docs`** (default: true)
Expand Down Expand Up @@ -80,7 +80,7 @@ src/
types.ts # Valibot schemas and AddonContext type
ui-building-instructions.md # Template for agent UI development instructions
tools/
get-story-urls.ts # Tool to retrieve story URLs from Storybook
preview-stories.ts # Tool to retrieve story preview URLs from Storybook
get-storybook-story-instructions.ts # Tool to provide UI development guidelines
utils/
errors.ts # Error handling utilities
Expand Down Expand Up @@ -173,7 +173,7 @@ pnpm test:ci # Run tests with coverage and CI reporters

- **Overall Target**: >70% statement coverage
- **src/utils**: 100% coverage (errors.ts, fetch-story-index.ts)
- **src/tools**: >90% coverage (get-story-urls.ts, get-storybook-story-instructions.ts)
- **src/tools**: >90% coverage (preview-stories.ts, get-storybook-story-instructions.ts)
- **src**: Integration files (preset.ts, mcp-handler.ts, telemetry.ts) have partial coverage

**Key Testing Patterns:**
Expand Down Expand Up @@ -244,8 +244,8 @@ Tests run automatically on PRs and main branch pushes via `.github/workflows/che

### Naming Conventions

- Constants: SCREAMING_SNAKE_CASE (e.g., `GET_STORY_URLS_TOOL_NAME`)
- Functions: camelCase (e.g., `addGetStoryUrlsTool`, `createAddonMcpHandler`)
- Constants: SCREAMING_SNAKE_CASE (e.g., `PREVIEW_STORIES_TOOL_NAME`)
- Functions: camelCase (e.g., `addPreviewStoriesTool`, `createAddonMcpHandler`)
- Types/Interfaces: PascalCase (e.g., `AddonContext`, `StoryInput`)

## Important Files
Expand All @@ -263,7 +263,7 @@ Tests run automatically on PRs and main branch pushes via `.github/workflows/che
- `src/mcp-handler.ts` - Main MCP server handler factory using tmcp
- `src/telemetry.ts` - Telemetry tracking for usage analytics
- `src/types.ts` - Valibot schemas and AddonContext interface
- `src/tools/get-story-urls.ts` - Tool to fetch story URLs from index.json
- `src/tools/preview-stories.ts` - Tool to preview stories from Storybook
- `src/tools/get-storybook-story-instructions.ts` - Tool to provide framework-specific UI instructions
- `src/utils/errors.ts` - Error handling utilities
- `src/utils/fetch-story-index.ts` - Utility to fetch Storybook's story index
Expand Down Expand Up @@ -483,7 +483,7 @@ pnpm test run --coverage # With coverage report

- `src/utils/errors.test.ts` - Tests error handling utilities
- `src/utils/fetch-story-index.test.ts` - Tests story index fetching
- `src/tools/get-story-urls.test.ts` - Tests story URL resolution tool
- `src/tools/preview-stories.test.ts` - Tests story preview tool
- `src/tools/get-storybook-story-instructions.test.ts` - Tests UI instructions tool
- `src/mcp-handler.test.ts` - Tests HTTP conversion utilities

Expand Down
3 changes: 1 addition & 2 deletions .github/instructions/eval.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,7 @@ export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
play: async ({ canvas }) => {
await userEvent.click(canvas.getByTestId('submit'));
await expect(canvas.getByText('Success')).toBeInTheDocument();
}
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,22 @@ pnpm storybook

This will build everything and start up Storybook with addon-mcp, and you can then connect your coding agent to it at `http://localhost:6006/mcp` and try it out.

### Working with the MCP App

To work with and debug the MCP app that is rendered as part of the preview-stories tool, you can:

1. Use the Insiders build of VSCode
2. Ensure the [chat.mcp.apps.enabled](vscode-insiders://settings/chat.mcp.apps.enabled) setting is enabled
3. Start up the repo's Storybook in watch mode by running `pnpm storybook` in the root
4. Restart VSCode and, open the [`.vscode/mcp.json`](./.vscode/mcp.json) file and ensure the Storybook MCP is marked as Running, otherwise click Start.
5. Open up a chat in VSCode and write a prompt like this:

> Show me how all the button stories look, using the Storybook MCP

6. After this first prompt, whenever you make changes, Storybook automatically restarts. Wait for it to be fully ready, then you can prompt _"Run the tool again"_.

You can also use [the inspector from MCPJam](https://docs.mcpjam.com/getting-started) to have more low level control of the tool calls.

### Formatting & Linting

```bash
Expand Down
2 changes: 1 addition & 1 deletion apps/internal-storybook/.claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"permissions": {
"allow": [
"mcp__storybook-addon-mcp__preview-stories",
"mcp__storybook-addon-mcp__get-storybook-story-instructions",
"mcp__storybook-addon-mcp__get-story-urls",
"mcp__storybook-addon-mcp__list-all-documentation",
"mcp__storybook-addon-mcp__get-documentation"
]
Expand Down
3 changes: 2 additions & 1 deletion apps/internal-storybook/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const config = defineMain({
],
addons: [
'@storybook/addon-docs',
'@storybook/addon-themes',
{
name: '@storybook/addon-mcp',
options: {
Expand All @@ -23,7 +24,7 @@ const config = defineMain({
},
],
framework: '@storybook/react-vite',
logLevel: 'debug',
// logLevel: 'debug',
Comment thread
JReinhold marked this conversation as resolved.
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logLevel has been commented out, changing from 'debug' to the default level. While this is likely intentional to reduce noise during development, this change should either be committed separately or documented in the PR description since it's not directly related to MCP Apps support.

Copilot uses AI. Check for mistakes.
core: {
disableTelemetry: true,
},
Expand Down
15 changes: 14 additions & 1 deletion apps/internal-storybook/.storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type { Preview } from '@storybook/react-vite';
import { withThemeByDataAttribute } from '@storybook/addon-themes';

import '../stories/theme.css';

const preview: Preview = {
parameters: {
Expand All @@ -9,8 +12,18 @@ const preview: Preview = {
},
},
},
decorators: [
withThemeByDataAttribute({
themes: {
light: 'light',
dark: 'dark',
},
defaultTheme: 'light',
attributeName: 'data-theme',
}),
],
initialGlobals: {
background: { value: 'light' },
theme: 'light',
},
};

Expand Down
1 change: 1 addition & 0 deletions apps/internal-storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"devDependencies": {
"@storybook/addon-docs": "catalog:",
"@storybook/addon-mcp": "workspace:*",
"@storybook/addon-themes": "^10.2.0",
"@storybook/react-vite": "catalog:",
"@types/react": "^18.2.65",
"@types/react-dom": "^18.2.21",
Expand Down
15 changes: 11 additions & 4 deletions apps/internal-storybook/stories/components/button.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,22 @@
cursor: pointer;
display: inline-block;
line-height: 1;
transition:
background-color 0.2s ease,
color 0.2s ease;
}
.storybook-button--primary {
color: white;
background-color: #1ea7fd;
background-color: var(--color-primary, #1ea7fd);
}
.storybook-button--primary:hover {
background-color: var(--color-primary-hover, #1890d4);
}
.storybook-button--secondary {
color: #333;
background-color: transparent;
box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
color: var(--color-secondary-text, #333);
background-color: var(--color-secondary-bg, transparent);
box-shadow: var(--color-secondary-border, rgba(0, 0, 0, 0.15)) 0px 0px 0px 1px
inset;
}
.storybook-button--small {
font-size: 12px;
Expand Down
13 changes: 11 additions & 2 deletions apps/internal-storybook/stories/components/header.css
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
.wrapper {
font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
border-bottom: 1px solid var(--color-border, rgba(0, 0, 0, 0.1));
padding: 15px 20px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: var(--color-bg, #ffffff);
transition:
background-color 0.2s ease,
border-color 0.2s ease;
}

svg {
display: inline-block;
vertical-align: top;
}

svg g path:first-child {
fill: var(--color-logo-bg, #ffffff);
}

h1 {
font-weight: 700;
font-size: 20px;
line-height: 1;
margin: 6px 0 6px 10px;
display: inline-block;
vertical-align: top;
color: var(--color-text, #333);
}

button + button {
margin-left: 10px;
}

.welcome {
color: #333;
color: var(--color-text, #333);
font-size: 14px;
margin-right: 10px;
}
18 changes: 13 additions & 5 deletions apps/internal-storybook/stories/components/page.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ section {
padding: 48px 20px;
margin: 0 auto;
max-width: 600px;
color: #333;
color: var(--color-text, #333);
background-color: var(--color-bg, #ffffff);
transition:
background-color 0.2s ease,
color 0.2s ease;
}

section h2 {
Expand All @@ -15,20 +19,23 @@ section h2 {
margin: 0 0 4px;
display: inline-block;
vertical-align: top;
color: var(--color-text, #333);
}

section p {
margin: 1em 0;
color: var(--color-text-secondary, #666);
}

section a {
text-decoration: none;
color: #1ea7fd;
color: var(--color-link, #1ea7fd);
}

section ul {
padding-left: 30px;
margin: 1em 0;
color: var(--color-text-secondary, #666);
}

section li {
Expand All @@ -41,8 +48,8 @@ section .tip {
font-size: 11px;
line-height: 12px;
font-weight: 700;
background: #e7fdd8;
color: #66bf3c;
background: var(--color-tip-bg, #e7fdd8);
color: var(--color-tip-text, #66bf3c);
padding: 4px 12px;
margin-right: 10px;
vertical-align: top;
Expand All @@ -53,6 +60,7 @@ section .tip-wrapper {
line-height: 20px;
margin-top: 40px;
margin-bottom: 40px;
color: var(--color-text-secondary, #666);
}

section .tip-wrapper svg {
Expand All @@ -65,5 +73,5 @@ section .tip-wrapper svg {
}

section .tip-wrapper svg path {
fill: #1ea7fd;
fill: var(--color-link, #1ea7fd);
}
18 changes: 11 additions & 7 deletions apps/internal-storybook/stories/other/card/card.css
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
.storybook-card {
font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
border: 1px solid #e1e5e9;
border: 1px solid var(--color-border-strong, #e1e5e9);
border-radius: 8px;
padding: 16px;
max-width: 300px;
background-color: white;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
background-color: var(--color-bg, white);
box-shadow: 0 2px 4px var(--color-card-shadow, rgba(0, 0, 0, 0.1));
transition:
background-color 0.2s ease,
border-color 0.2s ease,
box-shadow 0.2s ease;
}

.storybook-card__title {
margin: 0 0 12px 0;
font-size: 18px;
font-weight: 700;
color: #333;
color: var(--color-text, #333);
}

.storybook-card__image {
Expand All @@ -27,7 +31,7 @@
margin: 0 0 16px 0;
font-size: 14px;
line-height: 1.5;
color: #666;
color: var(--color-text-secondary, #666);
}

.storybook-card__button {
Expand All @@ -41,10 +45,10 @@
display: inline-block;
line-height: 1;
color: white;
background-color: #1ea7fd;
background-color: var(--color-primary, #1ea7fd);
transition: background-color 0.2s ease;
}

.storybook-card__button:hover {
background-color: #1890d4;
background-color: var(--color-primary-hover, #1890d4);
}
Loading
Loading