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/dull-impalas-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@storybook/addon-mcp': patch
---

improve html bundling
112 changes: 11 additions & 101 deletions packages/addon-mcp/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { PresetProperty } from 'storybook/internal/types';
import { AddonOptions, type AddonOptionsInput } from './types.ts';
import * as v from 'valibot';
import { isManifestAvailable } from './tools/is-manifest-available.ts';
import htmlTemplate from './template.html';

export const experimental_devServer: PresetProperty<
'experimental_devServer'
Expand All @@ -29,107 +30,16 @@ export const experimental_devServer: PresetProperty<
if (acceptHeader.includes('text/html')) {
// Browser request - send HTML with redirect
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<!DOCTYPE html>
<html>
<head>
${shouldRedirect ? '<meta http-equiv="refresh" content="10;url=/manifests/components.html" />' : ''}
<style>
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-regular.woff2') format('woff2');
}

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

html, body {
height: 100%;
font-family: 'Nunito Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
}

body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 2rem;
background-color: #ffffff;
color: rgb(46, 52, 56);
line-height: 1.6;
}

p {
margin-bottom: 1rem;
}

code {
font-family: 'Monaco', 'Courier New', monospace;
background: #f5f5f5;
padding: 0.2em 0.4em;
border-radius: 3px;
}

a {
color: #1ea7fd;
}

@media (prefers-color-scheme: dark) {
body {
background-color: rgb(34, 36, 37);
color: rgb(201, 205, 207);
}

code {
background: rgba(255, 255, 255, 0.1);
}
}
</style>
</head>
<body>
<div>
<p>
Storybook MCP server successfully running via
<code>@storybook/addon-mcp</code>.
</p>
<p>
See how to connect to it from your coding agent in <a target="_blank" href="https://github.com/storybookjs/mcp/tree/main/packages/addon-mcp#configuring-your-agent">the addon's README</a>.
</p>
${
shouldRedirect
? `
<p>
Automatically redirecting to
<a href="/manifests/components.html">component manifest</a>
in <span id="countdown">10</span> seconds...
</p>`
: ''
}
</div>
${
shouldRedirect
? `
<script>
let countdown = 10;
const countdownElement = document.getElementById('countdown');
setInterval(() => {
countdown -= 1;
countdownElement.textContent = countdown.toString();
}, 1000);
</script>
`
: ''
}
</body>
</html>
`);

const html = htmlTemplate.replace(
'{{REDIRECT_META}}',
shouldRedirect
? // redirect the user to the component manifest page after 10 seconds
'<meta http-equiv="refresh" content="10;url=/manifests/components.html" />'
: // ... or hide the message about redirection
'<style>#redirect-message { display: none; }</style>',
);
res.end(html);
} else {
// Non-browser request (API, curl, etc.) - send plain text
res.writeHead(200, { 'Content-Type': 'text/plain' });
Expand Down
105 changes: 105 additions & 0 deletions packages/addon-mcp/src/template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<!doctype html>
<html>
<head>
{{REDIRECT_META}}
<style>
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-regular.woff2') format('woff2');
}

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

html,
body {
height: 100%;
font-family:
'Nunito Sans',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Oxygen,
Ubuntu,
Cantarell,
sans-serif;
}

body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 2rem;
background-color: #ffffff;
color: rgb(46, 52, 56);
line-height: 1.6;
}

p {
margin-bottom: 1rem;
}

code {
font-family: 'Monaco', 'Courier New', monospace;
background: #f5f5f5;
padding: 0.2em 0.4em;
border-radius: 3px;
}

a {
color: #1ea7fd;
}

@media (prefers-color-scheme: dark) {
body {
background-color: rgb(34, 36, 37);
color: rgb(201, 205, 207);
}

code {
background: rgba(255, 255, 255, 0.1);
}
}
</style>
</head>
<body>
<div>
<p>
Storybook MCP server successfully running via
<code>@storybook/addon-mcp</code>.
</p>
<p>
See how to connect to it from your coding agent in
<a
target="_blank"
href="https://github.com/storybookjs/mcp/tree/main/packages/addon-mcp#configuring-your-agent"
>the addon's README</a
>.
</p>
<p id="redirect-message">
Automatically redirecting to
<a href="/manifests/components.html">component manifest</a>
in <span id="countdown">10</span> seconds...
</p>
</div>
<script>
let countdown = 10;
const countdownElement = document.getElementById('countdown');
if (countdownElement) {
setInterval(() => {
countdown -= 1;
countdownElement.textContent = countdown.toString();
}, 1000);
}
</script>
</body>
</html>
4 changes: 4 additions & 0 deletions packages/addon-mcp/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ declare module '*.md' {
const content: string;
export default content;
}
declare module '*.html' {
const content: string;
export default content;
}
10 changes: 4 additions & 6 deletions packages/mcp/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { McpServer } from 'tmcp';
import { ValibotJsonSchemaAdapter } from '@tmcp/adapter-valibot';
import { HttpTransport } from '@tmcp/transport-http';
import packageJson from '../package.json' with { type: 'json' };
import pkgJson from '../package.json' with { type: 'json' };
import { addListAllComponentsTool } from './tools/list-all-components.ts';
import { addGetComponentDocumentationTool } from './tools/get-component-documentation.ts';
import type { StorybookContext } from './types.ts';
Expand Down Expand Up @@ -71,11 +71,9 @@ export const createStorybookMcpHandler = async (
const adapter = new ValibotJsonSchemaAdapter();
const server = new McpServer(
{
// package.json properties are tree-shaken during build via a rolldown plugin in tsdown.config.ts
// If we ever changed the used properties here, we would need to update that plugin as well
name: packageJson.name,
version: packageJson.version,
description: packageJson.description,
name: pkgJson.name,
version: pkgJson.version,
description: pkgJson.description,
},
{
adapter,
Expand Down
Loading
Loading