@storybook/addon-mcp 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -191,18 +191,15 @@ export default {
191
191
  };
192
192
  ```
193
193
 
194
- #### 3. List All Components (`list-all-components`)
194
+ #### 3. List All Documentation (`list-all-documentation`)
195
195
 
196
- Returns a list of all available UI components in your component library. Useful for the LLM as discovery and understanding what components are available to use.
196
+ Returns a list of all available UI components as well as standalone docs in your component library. Useful for the LLM as discovery and understanding what components are available to use.
197
197
 
198
- #### 4. Get Component Documentation (`get-component-documentation`)
198
+ #### 4. Get Documentation (`get-documentation`)
199
199
 
200
- Retrieves detailed documentation for a specific component, including:
200
+ Retrieves detailed documentation for a specific component or docs entry.
201
201
 
202
- - Component documentation
203
- - Usage examples
204
-
205
- The agent provides a component ID to retrieve its documentation. To get documentation for multiple components, call this tool multiple times.
202
+ The agent provides a component/docs ID to retrieve its documentation. To get documentation for multiple entries, call this tool multiple times.
206
203
 
207
204
  ## Contributing
208
205
 
package/dist/preset.js CHANGED
@@ -6,12 +6,12 @@ import { storyNameFromExport } from "storybook/internal/csf";
6
6
  import { logger } from "storybook/internal/node-logger";
7
7
  import * as v from "valibot";
8
8
  import { telemetry } from "storybook/internal/telemetry";
9
- import { addGetComponentDocumentationTool, addListAllComponentsTool } from "@storybook/mcp";
9
+ import { addGetDocumentationTool, addListAllDocumentationTool } from "@storybook/mcp";
10
10
  import { buffer } from "node:stream/consumers";
11
11
 
12
12
  //#region package.json
13
13
  var name = "@storybook/addon-mcp";
14
- var version = "0.1.6";
14
+ var version = "0.1.7";
15
15
  var description = "Help agents automatically write and test stories for your UI components";
16
16
 
17
17
  //#endregion
@@ -209,12 +209,12 @@ const frameworkToRendererMap = {
209
209
  //#endregion
210
210
  //#region src/tools/is-manifest-available.ts
211
211
  const getManifestStatus = async (options) => {
212
- const [features, componentManifestGenerator] = await Promise.all([options.presets.apply("features"), options.presets.apply("experimental_componentManifestGenerator")]);
213
- const hasGenerator = !!componentManifestGenerator;
212
+ const [features, manifests] = await Promise.all([options.presets.apply("features"), options.presets.apply("experimental_manifests", void 0, { manifestEntries: [] })]);
213
+ const hasManifests = !!manifests;
214
214
  const hasFeatureFlag = !!features?.experimentalComponentsManifest;
215
215
  return {
216
- available: hasFeatureFlag && hasGenerator,
217
- hasGenerator,
216
+ available: hasFeatureFlag && hasManifests,
217
+ hasManifests,
218
218
  hasFeatureFlag
219
219
  };
220
220
  };
@@ -246,8 +246,8 @@ const initializeMCPServer = async (options) => {
246
246
  if ((await getManifestStatus(options)).available) {
247
247
  logger.info("Experimental components manifest feature detected - registering component tools");
248
248
  const contextAwareEnabled = () => server.ctx.custom?.toolsets?.docs ?? true;
249
- await addListAllComponentsTool(server, contextAwareEnabled);
250
- await addGetComponentDocumentationTool(server, contextAwareEnabled);
249
+ await addListAllDocumentationTool(server, contextAwareEnabled);
250
+ await addGetDocumentationTool(server, contextAwareEnabled);
251
251
  }
252
252
  transport = new HttpTransport(server, { path: null });
253
253
  origin = `http://localhost:${options.port}`;
@@ -266,21 +266,22 @@ const mcpServerHandler = async ({ req, res, options, addonOptions }) => {
266
266
  disableTelemetry,
267
267
  request: webRequest,
268
268
  ...!disableTelemetry && {
269
- onListAllComponents: async ({ manifest }) => {
269
+ onListAllDocumentation: async ({ manifests }) => {
270
270
  await collectTelemetry({
271
- event: "tool:listAllComponents",
271
+ event: "tool:listAllDocumentation",
272
272
  server,
273
273
  toolset: "docs",
274
- componentCount: Object.keys(manifest.components).length
274
+ componentCount: Object.keys(manifests.componentManifest.components).length,
275
+ docsCount: Object.keys(manifests.docsManifest?.docs || {}).length
275
276
  });
276
277
  },
277
- onGetComponentDocumentation: async ({ input, foundComponent }) => {
278
+ onGetDocumentation: async ({ input, foundDocumentation }) => {
278
279
  await collectTelemetry({
279
- event: "tool:getComponentDocumentation",
280
+ event: "tool:getDocumentation",
280
281
  server,
281
282
  toolset: "docs",
282
- componentId: input.componentId,
283
- found: !!foundComponent
283
+ componentId: input.id,
284
+ found: !!foundDocumentation
284
285
  });
285
286
  }
286
287
  }
@@ -341,7 +342,7 @@ function getToolsets(request, addonOptions) {
341
342
 
342
343
  //#endregion
343
344
  //#region src/template.html
344
- var template_default = "<!doctype html>\n<html>\n <head>\n {{REDIRECT_META}}\n <style>\n @font-face {\n font-family: 'Nunito Sans';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url('./sb-common-assets/nunito-sans-regular.woff2') format('woff2');\n }\n\n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n\n html,\n body {\n height: 100%;\n font-family:\n 'Nunito Sans',\n -apple-system,\n BlinkMacSystemFont,\n 'Segoe UI',\n Roboto,\n Oxygen,\n Ubuntu,\n Cantarell,\n sans-serif;\n }\n\n body {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n text-align: center;\n padding: 2rem;\n background-color: #ffffff;\n color: rgb(46, 52, 56);\n line-height: 1.6;\n }\n\n p {\n margin-bottom: 1rem;\n }\n\n code {\n font-family: 'Monaco', 'Courier New', monospace;\n background: #f5f5f5;\n padding: 0.2em 0.4em;\n border-radius: 3px;\n }\n\n a {\n color: #1ea7fd;\n }\n\n .container {\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .toolsets {\n margin: 1.5rem 0;\n text-align: left;\n max-width: 500px;\n }\n\n .toolsets h3 {\n font-size: 1rem;\n margin-bottom: 0.75rem;\n text-align: center;\n }\n\n .toolset {\n margin-bottom: 1rem;\n padding: 0.75rem 1rem;\n border-radius: 6px;\n background: #f8f9fa;\n border: 1px solid #e9ecef;\n }\n\n .toolset-header {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 600;\n margin-bottom: 0.5rem;\n }\n\n .toolset-status {\n display: inline-block;\n padding: 0.15em 0.5em;\n border-radius: 3px;\n font-size: 0.75rem;\n font-weight: 500;\n text-transform: uppercase;\n }\n\n .toolset-status.enabled {\n background: #d4edda;\n color: #155724;\n }\n\n .toolset-status.disabled {\n background: #f8d7da;\n color: #721c24;\n }\n\n .toolset-tools {\n font-size: 0.875rem;\n color: #6c757d;\n padding-left: 1.5rem;\n margin: 0;\n }\n\n .toolset-tools li {\n margin-bottom: 0.25rem;\n }\n\n .toolset-tools code {\n font-size: 0.8rem;\n }\n\n .toolset-notice {\n font-size: 0.8rem;\n color: #856404;\n background: #fff3cd;\n padding: 0.5rem;\n border-radius: 4px;\n margin-top: 0.5rem;\n }\n\n .toolset-notice a {\n color: #533f03;\n }\n\n @media (prefers-color-scheme: dark) {\n body {\n background-color: rgb(34, 36, 37);\n color: rgb(201, 205, 207);\n }\n\n code {\n background: rgba(255, 255, 255, 0.1);\n }\n\n .toolset {\n background: rgba(255, 255, 255, 0.05);\n border-color: rgba(255, 255, 255, 0.1);\n }\n\n .toolset-tools {\n color: #adb5bd;\n }\n\n .toolset-status.enabled {\n background: rgba(40, 167, 69, 0.2);\n color: #75d67e;\n }\n\n .toolset-status.disabled {\n background: rgba(220, 53, 69, 0.2);\n color: #f5a6ad;\n }\n\n .toolset-notice {\n background: rgba(255, 193, 7, 0.15);\n color: #ffc107;\n }\n\n .toolset-notice a {\n color: #ffe066;\n }\n }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <p>\n Storybook MCP server successfully running via\n <code>@storybook/addon-mcp</code>.\n </p>\n <p>\n See how to connect to it from your coding agent in\n <a\n target=\"_blank\"\n href=\"https://github.com/storybookjs/mcp/tree/main/packages/addon-mcp#configuring-your-agent\"\n >the addon's README</a\n >.\n </p>\n\n <div class=\"toolsets\">\n <h3>Available Toolsets</h3>\n\n <div class=\"toolset\">\n <div class=\"toolset-header\">\n <span>dev</span>\n <span class=\"toolset-status {{DEV_STATUS}}\">{{DEV_STATUS}}</span>\n </div>\n <ul class=\"toolset-tools\">\n <li><code>get-story-urls</code></li>\n <li><code>get-ui-building-instructions</code></li>\n </ul>\n </div>\n\n <div class=\"toolset\">\n <div class=\"toolset-header\">\n <span>docs</span>\n <span class=\"toolset-status {{DOCS_STATUS}}\">{{DOCS_STATUS}}</span>\n </div>\n <ul class=\"toolset-tools\">\n <li><code>list-all-components</code></li>\n <li><code>get-component-documentation</code></li>\n </ul>\n {{DOCS_NOTICE}}\n </div>\n </div>\n\n <p id=\"redirect-message\">\n Automatically redirecting to\n <a href=\"/manifests/components.html\">component manifest</a>\n in <span id=\"countdown\">10</span> seconds...\n </p>\n </div>\n <script>\n let countdown = 10;\n const countdownElement = document.getElementById('countdown');\n if (countdownElement) {\n setInterval(() => {\n countdown -= 1;\n countdownElement.textContent = countdown.toString();\n }, 1000);\n }\n <\/script>\n </body>\n</html>\n";
345
+ var template_default = "<!doctype html>\n<html>\n <head>\n {{REDIRECT_META}}\n <style>\n @font-face {\n font-family: 'Nunito Sans';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url('./sb-common-assets/nunito-sans-regular.woff2') format('woff2');\n }\n\n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n\n html,\n body {\n height: 100%;\n font-family:\n 'Nunito Sans',\n -apple-system,\n BlinkMacSystemFont,\n 'Segoe UI',\n Roboto,\n Oxygen,\n Ubuntu,\n Cantarell,\n sans-serif;\n }\n\n body {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n text-align: center;\n padding: 2rem;\n background-color: #ffffff;\n color: rgb(46, 52, 56);\n line-height: 1.6;\n }\n\n p {\n margin-bottom: 1rem;\n }\n\n code {\n font-family: 'Monaco', 'Courier New', monospace;\n background: #f5f5f5;\n padding: 0.2em 0.4em;\n border-radius: 3px;\n }\n\n a {\n color: #1ea7fd;\n }\n\n .container {\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .toolsets {\n margin: 1.5rem 0;\n text-align: left;\n max-width: 500px;\n }\n\n .toolsets h3 {\n font-size: 1rem;\n margin-bottom: 0.75rem;\n text-align: center;\n }\n\n .toolset {\n margin-bottom: 1rem;\n padding: 0.75rem 1rem;\n border-radius: 6px;\n background: #f8f9fa;\n border: 1px solid #e9ecef;\n }\n\n .toolset-header {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 600;\n margin-bottom: 0.5rem;\n }\n\n .toolset-status {\n display: inline-block;\n padding: 0.15em 0.5em;\n border-radius: 3px;\n font-size: 0.75rem;\n font-weight: 500;\n text-transform: uppercase;\n }\n\n .toolset-status.enabled {\n background: #d4edda;\n color: #155724;\n }\n\n .toolset-status.disabled {\n background: #f8d7da;\n color: #721c24;\n }\n\n .toolset-tools {\n font-size: 0.875rem;\n color: #6c757d;\n padding-left: 1.5rem;\n margin: 0;\n }\n\n .toolset-tools li {\n margin-bottom: 0.25rem;\n }\n\n .toolset-tools code {\n font-size: 0.8rem;\n }\n\n .toolset-notice {\n font-size: 0.8rem;\n color: #856404;\n background: #fff3cd;\n padding: 0.5rem;\n border-radius: 4px;\n margin-top: 0.5rem;\n }\n\n .toolset-notice a {\n color: #533f03;\n }\n\n @media (prefers-color-scheme: dark) {\n body {\n background-color: rgb(34, 36, 37);\n color: rgb(201, 205, 207);\n }\n\n code {\n background: rgba(255, 255, 255, 0.1);\n }\n\n .toolset {\n background: rgba(255, 255, 255, 0.05);\n border-color: rgba(255, 255, 255, 0.1);\n }\n\n .toolset-tools {\n color: #adb5bd;\n }\n\n .toolset-status.enabled {\n background: rgba(40, 167, 69, 0.2);\n color: #75d67e;\n }\n\n .toolset-status.disabled {\n background: rgba(220, 53, 69, 0.2);\n color: #f5a6ad;\n }\n\n .toolset-notice {\n background: rgba(255, 193, 7, 0.15);\n color: #ffc107;\n }\n\n .toolset-notice a {\n color: #ffe066;\n }\n }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <p>\n Storybook MCP server successfully running via\n <code>@storybook/addon-mcp</code>.\n </p>\n <p>\n See how to connect to it from your coding agent in\n <a\n target=\"_blank\"\n href=\"https://github.com/storybookjs/mcp/tree/main/packages/addon-mcp#configuring-your-agent\"\n >the addon's README</a\n >.\n </p>\n\n <div class=\"toolsets\">\n <h3>Available Toolsets</h3>\n\n <div class=\"toolset\">\n <div class=\"toolset-header\">\n <span>dev</span>\n <span class=\"toolset-status {{DEV_STATUS}}\">{{DEV_STATUS}}</span>\n </div>\n <ul class=\"toolset-tools\">\n <li><code>get-story-urls</code></li>\n <li><code>get-ui-building-instructions</code></li>\n </ul>\n </div>\n\n <div class=\"toolset\">\n <div class=\"toolset-header\">\n <span>docs</span>\n <span class=\"toolset-status {{DOCS_STATUS}}\">{{DOCS_STATUS}}</span>\n </div>\n <ul class=\"toolset-tools\">\n <li><code>list-all-documentation</code></li>\n <li><code>get-component-documentation</code></li>\n </ul>\n {{DOCS_NOTICE}}\n </div>\n </div>\n\n <p id=\"redirect-message\">\n Automatically redirecting to\n <a href=\"/manifests/components.html\">component manifest</a>\n in <span id=\"countdown\">10</span> seconds...\n </p>\n </div>\n <script>\n let countdown = 10;\n const countdownElement = document.getElementById('countdown');\n if (countdownElement) {\n setInterval(() => {\n countdown -= 1;\n countdownElement.textContent = countdown.toString();\n }, 1000);\n }\n <\/script>\n </body>\n</html>\n";
345
346
 
346
347
  //#endregion
347
348
  //#region src/preset.ts
@@ -368,7 +369,7 @@ const experimental_devServer = async (app, options) => {
368
369
  });
369
370
  res.writeHead(200, { "Content-Type": "text/html" });
370
371
  let docsNotice = "";
371
- if (!manifestStatus.hasGenerator) docsNotice = `<div class="toolset-notice">
372
+ if (!manifestStatus.hasManifests) docsNotice = `<div class="toolset-notice">
372
373
  This toolset is only supported in React-based setups.
373
374
  </div>`;
374
375
  else if (!manifestStatus.hasFeatureFlag) docsNotice = `<div class="toolset-notice">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/addon-mcp",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Help agents automatically write and test stories for your UI components",
5
5
  "keywords": [
6
6
  "storybook-addon",
@@ -29,10 +29,10 @@
29
29
  "@tmcp/transport-http": "^0.8.0",
30
30
  "tmcp": "^1.16.0",
31
31
  "valibot": "1.2.0",
32
- "@storybook/mcp": "0.1.1"
32
+ "@storybook/mcp": "0.2.0"
33
33
  },
34
34
  "devDependencies": {
35
- "storybook": "10.1.2"
35
+ "storybook": "10.2.0-alpha.14"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "storybook": "^9.1.16 || ^10.0.0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 || ^10.4.0-0"