Storybook故事生成服务器

一个用于Storybook故事生成、组件分析和验证的Model Context Protocol (MCP)服务器,支持自动检测Next.js、Chakra UI等多种React框架。

  • by the-single-gentlemans-club
  • TypeScript
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 effinrich/storybook-mcp-v2

使用说明

forgekit故事书mcp

A. 模型上下文协议(MCP)服务器 用于故事书故事生成、组件分析和验证。

自动检测 Next.js、Chakra UI、shadcn/UI、Tamagui和Gluestack UI。适用于任何React项目——无法识别的框架使用vanilla默认值。


🎉 v1.2的新增功能

▲ Next.js支持——一流

  • 自动检测Next.js项目 当 next 处于依赖关系中 和 一 next.config.{js,ts,mjs,cjs} 存在于项目根目录。两个信号都必须存在(避免传递错误 next deps)。
  • 脚手架 @storybook/nextjs --官方Storybook框架包——而不是 @storybook/react-vite.Stories类型检查与Next.js框架的 StorybookConfig,与 next/image, next/link, next/font,以及 next/navigation 开箱即用。
  • 生成的故事从导入 @storybook/nextjs — import type { Meta, StoryObj } from '@storybook/nextjs' 对于Next.js项目, '@storybook/react' 对于其他一切。
  • 不再 withRouter Next.js故事中的装饰器 — @storybook/nextjs 船舶内置模拟 next/navigation / next/router 有线直通 parameters.nextjs.appDirectory: true 在生成 preview.tsx.
  • UI库+Next.js组合正确 --Next.js+Chakra仍然会发出 <ChakraProvider> 室内装饰师 preview.tsxNext.js赢得了框架包的决定,但UI库仍然驱动着提供者。
  • 新 isNextjs 场上 storybook-mcp.config.json (仅在以下情况下持续存在 true).
  • 新 validator.ts 接受 @storybook/react, @storybook/react-vite, 和 @storybook/nextjs 作为有效的Meta/StoryObj导入源。

🛠 设置检修

  • 检测到的故事书版本受到尊重 — runSetup 现在读取已安装的 storybook 版本(从 node_modules 首先,回到 package.json 声明的范围)和引脚全部 @storybook/* 精确到这个范围。较旧的v9及以下安装会发出升级 notice 而不是默默地降级。
  • @nx/storybook 对等依赖检测 --当没有直接安装时,会回退到Nx插件声明的Storybook版本。
  • 更严格的检测合同 --出口 detectInstalledStorybookVersion(), detectNxStorybookVersion(),以及 detectNextjs() 对于程序化消费者。
  • addons 明确地发出 — @storybook/addon-docs 和 @storybook/addon-a11y 现在显示在 main.ts 对于v10(基本要素/交互仍然捆绑在主 storybook 包装)。
  • shadcn检测撒下了更宽的网 --比赛开始 components.json,任何 @radix-ui/*, @base-ui-components/react, class-variance-authority, tailwindcss, 或 lucide-react.
  • 单一事实来源 — cli.ts 和 setup.ts 不再重复框架检测; cli.ts 现在进口自 setup.ts.

✅ 同步是最终任务

  • sync_all 仍然是扫描、生成和充值的协调器。缺乏交互测试的现有故事是 非破坏性 增强 appendMissingGeneratedStories --您的自定义导出将保留,缺少模板导出(变体、尺寸、, 互动游戏故事)附。

🐛 修复

  • TypeScript不再出错 NON_COMPONENT_FILES.includes(...) --the as const 数组的窄类型拒绝任意字符串。

升级? 跑 npm install forgekit-storybook-mcp@latest 和 npx forgekit-storybook-mcp --setup --force 刷新 .storybook/main.ts 如果你想选择加入Next.js框架包。对现有的非Next.js设置没有突破性的更改。看 更新日志 了解全部细节。


目录


快速开始

# 1. Install the package
npm install forgekit-storybook-mcp

# 2. Create storybook-mcp.config.json in your project root (see Configuration)

# 3. Add to your MCP client (see MCP Client Setup below)

先决条件

安装之前,请确保您的项目已设置Storybook及其核心依赖项。

故事书

如果你还没有故事书:

npx storybook@latest init

这个脚手架 .storybook/ config目录,安装核心包,并添加示例故事。 需要故事书10.2+。 不支持早期版本。

所需套餐

  • node ≥ 20
  • react ≥ 18
  • react-dom ≥ 18
  • storybook ≥ 10.2
  • @storybook/react ≥ 10.2
  • @storybook/react-vite ≥10.2(或 @storybook/react-webpack5 如果使用Webpack)

安装核心故事书包:

npm i -D storybook@^10.2.0 @storybook/react@^10.2.0 @storybook/react-vite@^10.2.0

推荐插件

安装这些插件后,一些模板和功能效果最佳:

插件 使用人 安装
storybook/test 交互式模板、播放功能 随附 storybook@10+
@storybook/addon-vitest 测试(Vite项目) npm i -D @storybook/addon-vitest
@storybook/addon-a11y 无障碍故事生成 npm i -D @storybook/addon-a11y
msw + msw-storybook-addon with-msw 模板 npm i -D msw msw-storybook-addon
@storybook/addon-interactions 交互测试面板 npm i -D @storybook/addon-interactions

您不需要预先了解所有这些内容——MCP可以在没有它们的情况下工作,并在模板需要缺少依赖关系时建议安装什么。


主要功能:启动时自动同步

当MCP服务器启动时,它会自动:

  1. 扫描 已配置库中的所有组件
  2. 创造 缺少故事、测试和MDX文档
  3. 更新 组件更改时的现有文件
  4. 缓存 用于高效变化检测的组件哈希

这意味着您的故事书文档会自动与您的组件保持同步。


安装

npm install forgekit-storybook-mcp
# or
pnpm add forgekit-storybook-mcp
# or
yarn add forgekit-storybook-mcp

配置

按优先级顺序,您有三个配置选项:

选项1:配置文件(推荐)

创建 storybook-mcp.config.json 在项目根目录中:

{
  "framework": "chakra",
  "libraries": [
    {
      "name": "ui",
      "path": "libs/ui/src",
      "storyTitlePrefix": "UI",
      "importAlias": "@ui"
    },
    {
      "name": "shared",
      "path": "libs/shared/src",
      "storyTitlePrefix": "Shared",
      "decorators": ["withRouter"]
    }
  ],
  "storyFilePattern": "**/*.stories.{ts,tsx}",
  "componentPatterns": [
    "**/src/**/*.tsx",
    "!**/*.stories.tsx",
    "!**/*.test.tsx"
  ],
  "excludePatterns": ["**/node_modules/**", "**/dist/**"]
}

选项2:package.json

添加一个 storybook-mcp 字段到您的 package.json:

{
  "name": "my-app",
  "storybook-mcp": {
    "framework": "shadcn",
    "libraries": [
      {
        "name": "components",
        "path": "src/components",
        "storyTitlePrefix": "Components"
      }
    ]
  }
}

选项3:自动检测

如果没有找到配置,MCP将自动检测:

  • 组件目录: src/components, libs/ui/src, packages/ui/src等等。
  • 框架:从您的 package.json 依赖关系(脉轮、shadcn、Tamagui、Gluestack)

配置参考

属性 类型 默认值 描述
rootDir string 自动检测到 项目根目录
framework string 'vanilla' UI框架: 'chakra', 'shadcn', 'tamagui', 'gluestack', 'vanilla'
libraries array [] 组件库位置(见下文)
storyFilePattern string '**/*.stories.{ts,tsx}' 故事文件的球形图案
componentPatterns string[] ['**/src/**/*.tsx', '!**/*.stories.tsx', '!**/*.test.tsx'] 组件文件的球形图案
excludePatterns string[] ['**/node_modules/**', '**/dist/**'] 要排除的目录
templatesDir string - 自定义模板目录
storybookVersion number 10 故事书版本(要求10+)

库配置

每个图书馆 libraries 阵列支持:

属性 类型 必填 描述
name string ✅ 用于筛选的库标识符
path string ✅ 相对于的路径 rootDir
storyTitlePrefix string ✅ 故事书标题的前缀(例如。, "UI" → "UI/Button")
decorators string[] - 应用于所有故事的默认装饰器
importAlias string - 导入路径别名(例如。, "@ui")

CLI标志

# Run with auto-sync (default behavior)
npx forgekit-storybook-mcp

# Skip auto-sync on startup - useful when you just want the MCP tools
npx forgekit-storybook-mcp --skip-init

# Preview what would be synced without writing any files
npx forgekit-storybook-mcp --dry-run

# Only run sync, then exit (useful for CI pipelines)
npx forgekit-storybook-mcp --init-only

# Disable specific generators during sync
npx forgekit-storybook-mcp --no-stories    # Don't generate story files
npx forgekit-storybook-mcp --no-tests      # Don't generate test files
npx forgekit-storybook-mcp --no-docs       # Don't generate MDX docs

# Only create missing files, don't update existing ones
npx forgekit-storybook-mcp --no-update

# Force overwrite existing story/test/doc files
npx forgekit-storybook-mcp --force

# Only sync a specific library (must match library.name in config)
npx forgekit-storybook-mcp --lib=ui

# Run interactive setup wizard (creates storybook-mcp.config.json)
npx forgekit-storybook-mcp --setup

组合标志

# CI pipeline: sync stories only, exit when done
npx forgekit-storybook-mcp --init-only --no-tests --no-docs

# Development: skip sync, just run the MCP server
npx forgekit-storybook-mcp --skip-init

# Preview: see what would change without modifying files
npx forgekit-storybook-mcp --dry-run --no-update

# Force-regenerate only the ui library, then exit
npx forgekit-storybook-mcp --init-only --force --lib=ui

MCP客户端设置

光标/VS代码

添加 .cursor/mcp.json (或 .vscode/mcp.json):

{
  "mcpServers": {
    "forgekit-storybook": {
      "command": "npx",
      "args": ["forgekit-storybook-mcp"]
    }
  }
}

使用CLI标志:

{
  "mcpServers": {
    "forgekit-storybook": {
      "command": "npx",
      "args": ["forgekit-storybook-mcp", "--skip-init"]
    }
  }
}

如果在本地安装(启动速度更快):

{
  "mcpServers": {
    "forgekit-storybook": {
      "command": "node",
      "args": ["node_modules/forgekit-storybook-mcp/dist/cli.js"]
    }
  }
}

克劳德桌面版

添加 claude_desktop_config.json:

{
  "mcpServers": {
    "forgekit-storybook": {
      "command": "npx",
      "args": ["forgekit-storybook-mcp"],
      "cwd": "/path/to/your/project"
    }
  }
}

工具参考

工具 说明
list_components 列出所有React组件,按库或故事状态过滤
analyze_component 提取道具、依赖关系,并获取故事建议
generate_story 生成包含变体和测试的完整故事文件
update_story 在保留自定义导出的同时重新生成故事
generate_test 生成Vitest或Playwright测试文件
generate_docs 生成MDX文档
generate_code_connect 生成Figma代码连接 .figma.tsx 文件
validate_story 查看故事以了解最佳实践和问题
sync_all 一次同步所有组件
sync_component 同步单个组件的故事/测试/文档
get_story_template 获取特定模板
list_templates 列出所有可用模板
get_component_coverage 获取故事报道统计数据
suggest_stories 获取需要故事的组件的优先级列表
check_health 检查故事书安装状况

list_components

列出已配置库中的所有React组件。

参数:

参数 类型 必填 默认 说明
library string - all 按库名称筛选
hasStory boolean - all 按故事状态筛选: true =只有故事, false =只有没有

示例:

// List ALL components across all libraries
{}

// List only components in the "ui" library
{
  "library": "ui"
}

// List components that DON'T have stories yet
{
  "hasStory": false
}

// List components in "shared" library that need stories
{
  "library": "shared",
  "hasStory": false
}

答复:

{
  "components": [
    {
      "name": "Button",
      "filePath": "libs/ui/src/button/button.tsx",
      "library": "ui",
      "hasStory": false,
      "exportType": "named"
    },
    {
      "name": "Card",
      "filePath": "libs/ui/src/card/card.tsx",
      "library": "ui",
      "hasStory": true,
      "storyPath": "libs/ui/src/card/card.stories.tsx",
      "exportType": "default"
    }
  ],
  "total": 2,
  "withStories": 1,
  "withoutStories": 1,
  "summary": "Found 2 components: 1 with stories, 1 without stories"
}

analyze_component

分析React组件以提取其结构、道具和依赖关系。

参数:

参数 类型 必填 说明
componentPath string ✅ 组件文件的路径

例子:

{
  "componentPath": "libs/ui/src/button/button.tsx"
}

答复:

{
  "analysis": {
    "name": "Button",
    "filePath": "libs/ui/src/button/button.tsx",
    "library": "ui",
    "hasStory": false,
    "exportType": "named",
    "props": [
      {
        "name": "variant",
        "type": "'solid' | 'outline' | 'ghost'",
        "required": false,
        "defaultValue": "'solid'",
        "description": "Visual style variant",
        "controlType": "select",
        "controlOptions": ["solid", "outline", "ghost"]
      },
      {
        "name": "size",
        "type": "'sm' | 'md' | 'lg'",
        "required": false,
        "defaultValue": "'md'",
        "controlType": "select",
        "controlOptions": ["sm", "md", "lg"]
      },
      {
        "name": "disabled",
        "type": "boolean",
        "required": false,
        "defaultValue": "false",
        "controlType": "boolean"
      },
      {
        "name": "children",
        "type": "ReactNode",
        "required": true,
        "controlType": "text"
      }
    ],
    "dependencies": {
      "usesRouter": false,
      "usesReactQuery": false,
      "usesChakra": true,
      "usesGluestack": false,
      "usesReactNative": false,
      "usesEmotion": false,
      "usesTailwind": false,
      "usesFramerMotion": true,
      "usesMSW": false,
      "usesGlobalState": false,
      "otherImports": ["@chakra-ui/react", "framer-motion"]
    },
    "suggestions": [
      "Use 'with-variants' template to showcase all size/variant combinations",
      "Add Framer Motion decorator for animation testing",
      "Consider adding interactive tests for click/focus states"
    ],
    "sourcePreview": "export const Button = ({ variant = 'solid', size = 'md', ... }) => { ... }"
  },
  "summary": "Analyzed Button: 4 props, no story",
  "recommendations": [
    "Use 'with-variants' template to showcase all size/variant combinations",
    "Add Framer Motion decorator for animation testing"
  ]
}

generate_story

为组件生成故事书故事文件。

参数:

参数 类型 必填 默认 说明
componentPath string ✅ - 组件文件的路径
includeVariants boolean - true 添加展示所有尺寸/变体组合的故事
includeInteractive boolean - true 为用户交互添加播放功能测试
includeA11y boolean - false 添加可访问性测试故事
includeResponsive boolean - false 添加移动/平板/桌面视口故事
template string - auto 要使用的模板(请参阅 模板)
overwrite boolean - false 替换现有故事文件
dryRun boolean - false 预览而不写入磁盘

示例:

// Basic: generate with defaults (variants + interactive)
{
  "componentPath": "libs/ui/src/button/button.tsx"
}

// Minimal: just the basic story, no extras
{
  "componentPath": "libs/ui/src/button/button.tsx",
  "includeVariants": false,
  "includeInteractive": false
}

// Full coverage: everything including a11y and responsive
{
  "componentPath": "libs/ui/src/button/button.tsx",
  "includeVariants": true,
  "includeInteractive": true,
  "includeA11y": true,
  "includeResponsive": true
}

// Use a specific template
{
  "componentPath": "libs/ui/src/user-list/user-list.tsx",
  "template": "with-msw"
}

// Preview what would be generated
{
  "componentPath": "libs/ui/src/button/button.tsx",
  "dryRun": true
}

// Replace an existing story
{
  "componentPath": "libs/ui/src/button/button.tsx",
  "overwrite": true
}

答复:

{
  "story": {
    "content": "import type { Meta, StoryObj } from '@storybook/react'\nimport { Button } from './Button'\n\nconst meta: Meta<typeof Button> = {\n  title: 'Components/Button',\n  component: Button,\n  tags: [],\n  ...\n}\n\nexport default meta\ntype Story = StoryObj<typeof Button>\n\nexport const Default: Story = { ... }\nexport const Sizes: Story = { ... }\nexport const Variants: Story = { ... }",
    "filePath": "libs/ui/src/button/button.stories.tsx",
    "imports": ["@storybook/react", "./Button"],
    "stories": ["Default", "Sizes", "Variants", "ClickTest"],
    "warnings": []
  },
  "written": true,
  "path": "libs/ui/src/button/button.stories.tsx",
  "summary": "Created story at libs/ui/src/button/button.stories.tsx"
}

generate_test

为组件生成测试文件。默认情况下使用vitest+@测试库。仅在以下情况下使用剧作家 @playwright/test 位于项目的依赖项中。

参数:

参数 类型 必填 默认 说明
componentPath string ✅ - 组件文件的路径
overwrite boolean - false 替换现有测试文件
dryRun boolean - false 预览而不写入磁盘

示例:

// Generate test for a component
{
  "componentPath": "libs/ui/src/button/button.tsx"
}

// Preview without writing
{
  "componentPath": "libs/ui/src/button/button.tsx",
  "dryRun": true
}

// Replace existing test
{
  "componentPath": "libs/ui/src/button/button.tsx",
  "overwrite": true
}

答复:

{
  "test": {
    "content": "import { describe, it, expect } from 'vitest'\nimport { render, screen } from '@testing-library/react'\nimport { Button } from './Button'\n\ndescribe('Button', () => {\n  it('renders correctly', () => {\n    render(<Button>Click me</Button>)\n    expect(screen.getByText('Click me')).toBeInTheDocument()\n  })\n})\n...",
    "filePath": "libs/ui/src/button/button.test.tsx"
  },
  "written": true,
  "path": "libs/ui/src/button/button.test.tsx",
  "summary": "Created test at libs/ui/src/button/button.test.tsx"
}

generate_docs

为组件生成MDX文档。

参数:

参数 类型 必填 默认 说明
componentPath string ✅ - 组件文件的路径
overwrite boolean - false 替换现有文档文件
dryRun boolean - false 预览而不写入磁盘

示例:

// Generate docs for a component
{
  "componentPath": "libs/ui/src/button/button.tsx"
}

// Preview without writing
{
  "componentPath": "libs/ui/src/button/button.tsx",
  "dryRun": true
}

答复:

{
  "docs": {
    "content": "import { Canvas, Meta, ArgTypes } from '@storybook/blocks'\nimport * as ButtonStories from './Button.stories'\n\n<Meta of={ButtonStories} />\n\n# Button\n\n## Usage\n\n<Canvas of={ButtonStories.Default} />\n\n## Props\n\n<ArgTypes of={ButtonStories} />\n...",
    "filePath": "libs/ui/src/button/button.mdx"
  },
  "written": true,
  "path": "libs/ui/src/button/button.mdx",
  "summary": "Created docs at libs/ui/src/button/button.mdx"
}

validate_story

验证现有的故事文件以了解最佳实践和问题。

参数:

参数 类型 必填 说明
storyPath string ✅ 故事文件的路径

例子:

{
  "storyPath": "libs/ui/src/button/button.stories.tsx"
}

答复:

{
  "validation": {
    "valid": false,
    "score": 72,
    "errors": [
      {
        "type": "error",
        "code": "MISSING_META_TITLE",
        "message": "Story is missing a title in meta",
        "line": 5,
        "fix": "Add 'title' property to meta object"
      }
    ],
    "warnings": [],
    "suggestions": [
      {
        "type": "suggestion",
        "code": "ADD_PLAY_FUNCTION",
        "message": "Consider adding interaction tests with play functions",
        "fix": "Add a story with a play function for testing user interactions"
      }
    ]
  },
  "summary": "Story has 1 errors (score: 72/100)"
}

sync_all

同步所有组件-创建缺失的故事/测试/文档并更新更改的内容。

参数:

参数 类型 必填 默认 说明
library string - all 仅同步此库中的组件
generateStories boolean - true 生成故事文件
generateTests boolean - true 生成测试文件
generateDocs boolean - true 生成MDX文档
updateExisting boolean - true 组件更改时更新文件
dryRun boolean - false 预览而不写入磁盘

示例:

// Sync everything with defaults
{}

// Sync only the "ui" library
{
  "library": "ui"
}

// Only generate stories, no tests or docs
{
  "generateStories": true,
  "generateTests": false,
  "generateDocs": false
}

// Only create missing files, don't update existing
{
  "updateExisting": false
}

// Preview what would change
{
  "dryRun": true
}

// Sync only stories for "shared" library, don't update existing
{
  "library": "shared",
  "generateStories": true,
  "generateTests": false,
  "generateDocs": false,
  "updateExisting": false
}

答复:

{
  "scanned": 24,
  "created": {
    "stories": 8,
    "tests": 8,
    "docs": 8
  },
  "updated": {
    "stories": 3,
    "tests": 2,
    "docs": 3
  },
  "skipped": 0,
  "errors": [],
  "summary": "Synced 24 components: Created 8 stories, 8 tests, 8 docs. Updated 8 files."
}

sync_component

同步单个组件的故事、测试和文档。

参数:

参数 类型 必填 默认 说明
componentPath string ✅ - 组件文件的路径
generateStories boolean - true 生成故事文件
generateTests boolean - true 生成测试文件
generateDocs boolean - true 生成MDX文档
dryRun boolean - false 预览而不写入磁盘

示例:

// Sync everything for one component
{
  "componentPath": "libs/ui/src/button/button.tsx"
}

// Only sync the story, not tests or docs
{
  "componentPath": "libs/ui/src/button/button.tsx",
  "generateStories": true,
  "generateTests": false,
  "generateDocs": false
}

// Preview what would change
{
  "componentPath": "libs/ui/src/button/button.tsx",
  "dryRun": true
}

答复:

{
  "result": {
    "component": "Button",
    "story": {
      "action": "created",
      "path": "libs/ui/src/button/button.stories.tsx"
    },
    "test": {
      "action": "created",
      "path": "libs/ui/src/button/button.test.tsx"
    },
    "docs": {
      "action": "skipped",
      "path": "libs/ui/src/button/button.mdx",
      "reason": "Already exists and unchanged"
    }
  },
  "summary": "Button: story: created, test: created"
}

get_story_template

按名称获取特定模板。

参数:

参数 类型 必填 说明
template string ✅ 模板名称(请参见 模板)

例子:

{
  "template": "with-msw"
}

答复:

{
  "template": {
    "name": "with-msw",
    "description": "Story with MSW API mocking",
    "useCase": "Components that fetch data and need mocked API responses",
    "content": "import type { Meta, StoryObj } from '@storybook/react'\nimport { http, HttpResponse } from 'msw'\nimport { {{ComponentName}} } from './{{ComponentName}}'\n\nconst meta: Meta<typeof {{ComponentName}}> = {\n  title: 'Components/{{ComponentName}}',\n  component: {{ComponentName}},\n  tags: [],\n}\n\nexport default meta\ntype Story = StoryObj<typeof {{ComponentName}}>\n\nexport const Default: Story = {\n  parameters: {\n    msw: {\n      handlers: [\n        http.get('/api/data', () => {\n          return HttpResponse.json({\n            items: [\n              { id: 1, name: 'Item 1' },\n            ],\n          })\n        }),\n      ],\n    },\n  },\n}\n...",
    "placeholders": ["ComponentName", "component-name"]
  },
  "usage": "Replace placeholders: ComponentName, component-name"
}

list_templates

列出所有可用的故事模板。

参数: 无

例子:

{}

答复:

{
  "templates": [
    {
      "name": "basic",
      "description": "Simple story with basic args",
      "useCase": "Quick component documentation with minimal setup",
      "available": true
    },
    {
      "name": "with-controls",
      "description": "Story with full argTypes controls",
      "useCase": "Interactive component exploration with all props exposed",
      "available": true
    },
    {
      "name": "with-variants",
      "description": "Story showcasing all variants and sizes",
      "useCase": "Design system documentation showing all visual options",
      "available": true
    }
  ],
  "count": 8
}

get_component_coverage

获取项目的故事报道统计数据。

参数:

参数 类型 必填 默认 说明
library string - all 按库名称筛选

示例:

// Coverage for entire project
{}

// Coverage for "ui" library only
{
  "library": "ui"
}

答复:

{
  "total": 24,
  "withStories": 16,
  "withoutStories": 8,
  "coverage": "67%",
  "byLibrary": {
    "ui": {
      "total": 15,
      "withStories": 12
    },
    "shared": {
      "total": 9,
      "withStories": 4
    }
  },
  "componentsNeedingStories": [
    {
      "name": "Tooltip",
      "path": "libs/ui/src/tooltip/tooltip.tsx",
      "library": "ui"
    },
    {
      "name": "DataTable",
      "path": "libs/shared/src/data-table/data-table.tsx",
      "library": "shared"
    }
  ]
}

suggest_stories

获取需要故事的组件的优先级列表。

参数:

参数 类型 必填 默认 说明
limit number - 10 建议的最大数量
library string - all 按库名称筛选

示例:

// Get top 10 suggestions
{}

// Get top 5 suggestions from "ui" library
{
  "limit": 5,
  "library": "ui"
}

答复:

{
  "suggestions": [
    {
      "component": "Button",
      "path": "libs/ui/src/button/button.tsx",
      "library": "ui",
      "command": "generate_story with componentPath: \"libs/ui/src/button/button.tsx\""
    },
    {
      "component": "Card",
      "path": "libs/ui/src/card/card.tsx",
      "library": "ui",
      "command": "generate_story with componentPath: \"libs/ui/src/card/card.tsx\""
    }
  ],
  "total": 8,
  "showing": 2,
  "summary": "8 components without stories. Showing top 2."
}

check_health

检查Storybook安装健康状况——缺少包、过时的配置和版本不匹配。可用于诊断安装问题,特别是在迁移到Storybook 10时。

参数: 无

例子:

{}

答复:

{
  "passed": false,
  "checks": [
    { "name": "package:storybook", "status": "pass", "message": "storybook is installed" },
    { "name": "config:main:addon:@storybook/addon-essentials", "status": "warn", "message": "@storybook/addon-essentials is bundled into storybook in v10 — can be removed from addons list", "fix": "Remove '@storybook/addon-essentials' from addons array in .storybook/main" }
  ],
  "installCommands": [],
  "summary": "Preflight: 1 warning(s) out of 8 checks"
}

update_story

使用最新的组件分析重新生成故事文件,同时保留您手写的任何导出。

不像 generate_story 随着 overwrite: true (这会破坏一切), update_story 检测哪个 export const X: Story 您添加的块,并将其附加到重新生成的内容下方,用注释标记分隔。

参数:

参数 类型 默认值 说明
componentPath string 必需 组件文件的路径
includeVariants 布尔值 true 重新生成变体故事
includeInteractive 布尔值 true 重新生成播放功能测试
includeA11y 布尔值 false 重新生成可访问性故事
includeResponsive 布尔值 false 重新生成视口故事
template string auto 要使用的特定模板
dryRun 布尔值 false 预览合并结果而不写入

例子:

{
  "componentPath": "src/components/Button.tsx"
}

答复包括:

  • preserved --保留的用户编写的故事名称数组
  • removed --不在合并输出中的故事(通常为空)
  • validation.warnings --非阻塞导入警告
  • summary --保存故事列表的人类可读结果

它是如何工作的:

该工具寻找 export const X: Story 不在新生成内容中的块。这些是你的定制故事。它们被附加在分隔符之后:

// ─── User-added stories (preserved by update_story) ───
export const MyEdgeCase: Story = {
  args: { label: 'Edge case' },
}

注: 版本条目记录在 .forgekit/story-history.json 每次写作(动作: merged).


generate_code_connect

生成一个 @figma/code-connect .figma.tsx 将您的组件链接到Figma开发模式的文件。

当与一起发布时 npx figma connect publish在Figma中检查组件的设计师可以看到真实的React代码——道具、变体和使用示例——而不是自动生成的代码片段。

参数:

参数 类型 默认值 说明
componentPath string 必需 组件文件的路径
figmaNodeUrl string -- Figma组件URL(https://figma.com/design/<fileId>/...?node-id=...).省略使用占位符。
overwrite 布尔值 false 替换现有 .figma.tsx 文件
dryRun 布尔值 false 无需写入即可预览输出

例子:

{
  "componentPath": "src/components/Button.tsx",
  "figmaNodeUrl": "https://figma.com/design/abc123/MyDesignSystem?node-id=1%3A2"
}

道具类型映射:

TypeScript类型 Figma绑定
string figma.string('PropName')
boolean figma.boolean('PropName')
'a' | 'b' 工会 figma.enum('PropName', { a: 'a', b: 'b' })
ReactNode / children figma.children(['*'])
number figma.number('PropName')

事件处理程序, className, style,以及 ref 自动排除。

生成的输出 (src/components/Button.figma.tsx):

import figma from '@figma/code-connect/react'
import { Button } from './Button'

figma.connect(Button, 'https://figma.com/design/abc123/MyDesignSystem?node-id=1%3A2', {
  props: {
    variant: figma.enum('Variant', {
      "primary": "primary",
      "secondary": "secondary",
      "ghost": "ghost",
    }),
    disabled: figma.boolean('Disabled'),
    children: figma.children(['*']),
  },
  example: ({ variant, disabled, children }) => (
    <Button variant={variant} disabled={disabled}>{children}</Button>
  ),
})

发表给Figma:

npm install --save-dev @figma/code-connect
npx figma connect login
npx figma connect publish

看 Figma集成 完整的工作流程。


Figma集成

该项目支持两个互补的Figma集成:

代码连接——将组件链接到Figma开发模式

Figma代码连接 将真实的React组件附加到Figma组件。Dev模式下的设计师看到的是实际的道具、变体和工作代码示例,而不是占位符片段。

工作流程:

  1. 为每个组件生成一个代码连接文件:

    {
      "componentPath": "src/components/Button.tsx",
      "figmaNodeUrl": "https://figma.com/design/abc123/MyDesignSystem?node-id=1%3A2"
    }
    
  2. 安装并发布:

    npm install --save-dev @figma/code-connect
    npx figma connect login
    npx figma connect publish
    
  3. 打开Figma中的组件→ 开发模式→ 代码面板。将显示您的组件代码。

提示: 通过右键单击画布上的组件复制Figma节点URL→ “复制链接”。

Canvas代码——将故事渲染推送到Figma(通过 forgekit-context)

这 sync_stories_to_figma 工具(部分 forgekit-context)连接到Figma桌面应用程序的Dev Mode MCP服务器,并将每个组件的默认故事作为可编辑的框架推送到画布上。

要求:

  • Figma桌面应用程序(非浏览器)
  • 启用开发模式MCP服务器: Figma菜单→ 偏好→ 启用开发者模式MCP服务器
  • forgekit-context 已安装并正在运行
  • 本地故事书运行(npm run storybook)

示例呼叫方式 forgekit-context:

{
  "storybookUrl": "http://localhost:6006",
  "dryRun": true
}

移除 dryRun 把故事推到画布上。


模板

模板是为不同用例预先构建的故事结构。使用它们与 template 参数在 generate_story.

模板 用例 示例
basic 快速的文档记录,最少的设置 简单的演示组件
with-controls 与所有道具互动探索 设计系统组件
with-variants 展示所有尺寸/变体 按钮、徽章、头像
with-msw 获取数据的组件 用户列表、仪表板
with-router 使用React Router的组件 导航,面包屑
page 全页面组件 登录页面、仪表板
interactive 具有用户交互功能的组件 窗体、模态、下拉菜单
form 具有验证功能的表单组件 登录表单、设置面板

模板示例

basic -最小设置:

import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './Button'

const meta: Meta<typeof Button> = {
  title: 'Components/Button',
  component: Button,
  tags: [],
}

export default meta
type Story = StoryObj<typeof Button>

export const Default: Story = {
  args: {
    children: 'Button content',
  },
}

with-variants -展示所有组合:

export const Sizes: Story = {
  render: () => (
    <div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
      <Button size="sm">Small</Button>
      <Button size="md">Medium</Button>
      <Button size="lg">Large</Button>
    </div>
  ),
}

export const AllVariants: Story = {
  render: () => (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
      {(['solid', 'outline', 'ghost'] as const).map((variant) => (
        <div key={variant} style={{ display: 'flex', gap: '1rem' }}>
          <Button variant={variant} size="sm">Small</Button>
          <Button variant={variant} size="md">Medium</Button>
          <Button variant={variant} size="lg">Large</Button>
        </div>
      ))}
    </div>
  ),
}

with-msw -模拟API响应:

import { http, HttpResponse } from 'msw'

export const Default: Story = {
  parameters: {
    msw: {
      handlers: [
        http.get('/api/users', () => {
          return HttpResponse.json({
            users: [
              { id: 1, name: 'Alice' },
              { id: 2, name: 'Bob' },
            ],
          })
        }),
      ],
    },
  },
}

export const Loading: Story = {
  parameters: {
    msw: {
      handlers: [
        http.get('/api/users', async () => {
          await new Promise((r) => setTimeout(r, 5000))
          return HttpResponse.json({})
        }),
      ],
    },
  },
}

export const Error: Story = {
  parameters: {
    msw: {
      handlers: [
        http.get('/api/users', () => {
          return HttpResponse.json({ error: 'Failed' }, { status: 500 })
        }),
      ],
    },
  },
}

interactive -播放功能测试:

import { expect, userEvent, within } from 'storybook/test'

export const ClickTest: Story = {
  args: { children: 'Click me' },
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement)
    const button = canvas.getByText(/click me/i)

    await expect(button).toBeInTheDocument()
    await userEvent.click(button)
    // Add assertions for post-click state
  },
}

export const KeyboardNavigation: Story = {
  args: { children: 'Focus me' },
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement)
    const button = canvas.getByText(/focus me/i)

    await userEvent.tab()
    await expect(button).toHaveFocus()
    await userEvent.keyboard('{Enter}')
  },
}

资源

MCP提供以下只读资源:

资源URI 描述
storybook://libraries 已配置的库信息
storybook://patterns 常见的故事模式和最佳实践
storybook://config 当前MCP配置

程序化使用

您还可以通过编程方式使用MCP服务器:

import { createStorybookMCPServer } from 'forgekit-storybook-mcp'

const server = createStorybookMCPServer({
  rootDir: process.cwd(),
  framework: 'chakra',
  libraries: [
    {
      name: 'ui',
      path: 'src/components',
      storyTitlePrefix: 'UI',
      importAlias: '@ui',
    },
  ],
  storybookVersion: 10,
})

// Server is now ready to handle MCP requests

路线图

看 ROADMAP.md 接下来是什么——迁移助手、观察模式、Figma集成等等。


相关项目

本MCP侧重于 生成 故事,而官方的重点是 阅读 现有故事书数据。它们相辅相成。


许可证

麻省理工学院