Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Forgekit Storybook

БесплатноНе проверен

MCP server for automatic Storybook story generation, component analysis, and validation. Auto-detects React frameworks and syncs component documentation.

GitHubEmbed

Описание

MCP server for automatic Storybook story generation, component analysis, and validation. Auto-detects React frameworks and syncs component documentation.

README

A Model Context Protocol (MCP) server for Storybook story generation, component analysis, and validation.

Auto-detects Next.js, Chakra UI, shadcn/ui, Tamagui, and Gluestack UI. Works with any React project — unrecognized frameworks use vanilla defaults.


🎉 What's New in v1.2

▲ Next.js support — first-class

  • Auto-detects Next.js projects when next is in dependencies and a next.config.{js,ts,mjs,cjs} exists at the project root. Both signals must be present (avoids false positives from transitive next deps).
  • Scaffolds with @storybook/nextjs — the official Storybook framework package — instead of @storybook/react-vite. Stories type-check against the Next.js framework's StorybookConfig, with next/image, next/link, next/font, and next/navigation working out of the box.
  • Generated stories import from @storybook/nextjsimport type { Meta, StoryObj } from '@storybook/nextjs' for Next.js projects, '@storybook/react' for everything else.
  • No more withRouter decorator on Next.js stories@storybook/nextjs ships built-in mocks for next/navigation / next/router wired through parameters.nextjs.appDirectory: true in the generated preview.tsx.
  • UI lib + Next.js compose correctly — Next.js + Chakra still emits <ChakraProvider> decorators in preview.tsx; Next.js wins the framework-package decision but the UI lib still drives the providers.
  • New isNextjs field on storybook-mcp.config.json (persisted only when true).
  • New validator.ts accepts @storybook/react, @storybook/react-vite, and @storybook/nextjs as valid Meta/StoryObj import sources.

🛠 Setup overhaul

  • Detected Storybook version is honoredrunSetup now reads the installed storybook version (from node_modules first, falling back to the package.json declared range) and pins all @storybook/* deps to that exact range. Older v9-and-below installs emit an upgrade notice instead of silently downgrading.
  • @nx/storybook peerDependency detection — falls back to the Storybook version declared by Nx's plugin when no direct install is present.
  • Stricter detection contract — exported detectInstalledStorybookVersion(), detectNxStorybookVersion(), and detectNextjs() for programmatic consumers.
  • addons are emitted explicitly@storybook/addon-docs and @storybook/addon-a11y now show up in main.ts for v10 (essentials/interactions are still bundled into the main storybook package).
  • shadcn detection casts a wider net — matches on components.json, any @radix-ui/*, @base-ui-components/react, class-variance-authority, tailwindcss, or lucide-react.
  • Single source of truthcli.ts and setup.ts no longer duplicate framework detection; cli.ts now imports from setup.ts.

✅ Sync stays the final task

  • sync_all continues to be the orchestrator that scans, generates, and tops up. Existing stories that lack interaction tests are non-destructively augmented by appendMissingGeneratedStories — your custom exports are preserved, missing template exports (Variants, Sizes, Interactive play stories) are appended.

🐛 Fixes

  • TypeScript no longer errors on NON_COMPONENT_FILES.includes(...) — the as const array's narrowed type was rejecting arbitrary strings.

Upgrading? Run npm install forgekit-storybook-mcp@latest and npx forgekit-storybook-mcp --setup --force to refresh .storybook/main.ts if you want to opt into the Next.js framework package. No breaking changes for existing non-Next.js setups. See CHANGELOG for full details.


Table of Contents


Quick Start

# 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)

Prerequisites

Before installing, make sure your project has Storybook and its core dependencies set up.

Storybook

If you don't have Storybook yet:

npx storybook@latest init

This scaffolds the .storybook/ config directory, installs core packages, and adds example stories. Requires Storybook 10.2+. Earlier versions are not supported.

Required Packages

  • node ≥ 20
  • react ≥ 18
  • react-dom ≥ 18
  • storybook ≥ 10.2
  • @storybook/react ≥ 10.2
  • @storybook/react-vite ≥ 10.2 (or @storybook/react-webpack5 if using Webpack)

Install the core Storybook packages:

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

Recommended Addons

Some templates and features work best with these addons installed:

Addon Used By Install
storybook/test Interactive templates, play functions Included with storybook@10+
@storybook/addon-vitest Testing (Vite projects) npm i -D @storybook/addon-vitest
@storybook/addon-a11y Accessibility story generation npm i -D @storybook/addon-a11y
msw + msw-storybook-addon with-msw template npm i -D msw msw-storybook-addon
@storybook/addon-interactions Interaction testing panel npm i -D @storybook/addon-interactions

You don't need all of these upfront — the MCP will work without them and will suggest what to install when a template requires a missing dependency.


Key Feature: Auto-Sync on Startup

When the MCP server starts, it automatically:

  1. Scans all components in configured libraries
  2. Creates missing stories, tests, and MDX docs
  3. Updates existing files when components have changed
  4. Caches component hashes for efficient change detection

This means your Storybook documentation stays in sync with your components automatically.


Installation

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

Configuration

You have three options for configuration, in order of priority:

Option 1: Config File (Recommended)

Create storybook-mcp.config.json in your project root:

{
  "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/**"]
}

Option 2: package.json

Add a storybook-mcp field to your package.json:

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

Option 3: Auto-Detection

If no config is found, the MCP will auto-detect:

  • Component directories: src/components, libs/ui/src, packages/ui/src, etc.
  • Framework: Detected from your package.json dependencies (Chakra, shadcn, Tamagui, Gluestack)

Configuration Reference

Property Type Default Description
rootDir string Auto-detected Project root directory
framework string 'vanilla' UI framework: 'chakra', 'shadcn', 'tamagui', 'gluestack', 'vanilla'
libraries array [] Component library locations (see below)
storyFilePattern string '**/*.stories.{ts,tsx}' Glob pattern for story files
componentPatterns string[] ['**/src/**/*.tsx', '!**/*.stories.tsx', '!**/*.test.tsx'] Glob patterns for component files
excludePatterns string[] ['**/node_modules/**', '**/dist/**'] Directories to exclude
templatesDir string - Custom templates directory
storybookVersion number 10 Storybook version (10+ required)

Library Configuration

Each library in the libraries array supports:

Property Type Required Description
name string Library identifier for filtering
path string Path relative to rootDir
storyTitlePrefix string Prefix for Storybook titles (e.g., "UI""UI/Button")
decorators string[] - Default decorators to apply to all stories
importAlias string - Import path alias (e.g., "@ui")

CLI Flags

# 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

Combining Flags

# 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 Client Setup

Cursor / VS Code

Add to .cursor/mcp.json (or .vscode/mcp.json):

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

With CLI flags:

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

If installed locally (faster startup):

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

Claude Desktop

Add to claude_desktop_config.json:

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

Tools Reference

Tool Description
list_components List all React components, filter by library or story status
analyze_component Extract props, dependencies, and get story suggestions
generate_story Generate complete story files with variants and tests
update_story Regenerate a story while preserving your custom exports
generate_test Generate Vitest or Playwright test files
generate_docs Generate MDX documentation
generate_code_connect Generate Figma Code Connect .figma.tsx files
validate_story Check stories for best practices and issues
sync_all Sync all components at once
sync_component Sync a single component's story/test/docs
get_story_template Get a specific template
list_templates List all available templates
get_component_coverage Get story coverage statistics
suggest_stories Get prioritized list of components needing stories
check_health Check Storybook installation health

list_components

List all React components in configured libraries.

Parameters:

Parameter Type Required Default Description
library string - all Filter by library name
hasStory boolean - all Filter by story status: true = only with stories, false = only without

Examples:

// 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
}

Response:

{
  "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

Analyze a React component to extract its structure, props, and dependencies.

Parameters:

Parameter Type Required Description
componentPath string Path to the component file

Example:

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

Response:

{
  "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

Generate a Storybook story file for a component.

Parameters:

Parameter Type Required Default Description
componentPath string - Path to the component file
includeVariants boolean - true Add stories showcasing all size/variant combinations
includeInteractive boolean - true Add play function tests for user interactions
includeA11y boolean - false Add accessibility test story
includeResponsive boolean - false Add mobile/tablet/desktop viewport stories
template string - auto Template to use (see Templates)
overwrite boolean - false Replace existing story file
dryRun boolean - false Preview without writing to disk

Examples:

// 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
}

Response:

{
  "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

Generate a test file for a component. Uses vitest + @testing-library by default. Uses Playwright only if @playwright/test is in your project's dependencies.

Parameters:

Parameter Type Required Default Description
componentPath string - Path to the component file
overwrite boolean - false Replace existing test file
dryRun boolean - false Preview without writing to disk

Examples:

// 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
}

Response:

{
  "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

Generate MDX documentation for a component.

Parameters:

Parameter Type Required Default Description
componentPath string - Path to the component file
overwrite boolean - false Replace existing docs file
dryRun boolean - false Preview without writing to disk

Examples:

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

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

Response:

{
  "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

Validate an existing story file for best practices and issues.

Parameters:

Parameter Type Required Description
storyPath string Path to the story file

Example:

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

Response:

{
  "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

Sync all components - create missing stories/tests/docs and update changed ones.

Parameters:

Parameter Type Required Default Description
library string - all Only sync components in this library
generateStories boolean - true Generate story files
generateTests boolean - true Generate test files
generateDocs boolean - true Generate MDX docs
updateExisting boolean - true Update files when components change
dryRun boolean - false Preview without writing to disk

Examples:

// 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
}

Response:

{
  "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

Sync a single component's story, test, and docs.

Parameters:

Parameter Type Required Default Description
componentPath string - Path to the component file
generateStories boolean - true Generate story file
generateTests boolean - true Generate test file
generateDocs boolean - true Generate MDX docs
dryRun boolean - false Preview without writing to disk

Examples:

// 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
}

Response:

{
  "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

Get a specific template by name.

Parameters:

Parameter Type Required Description
template string Template name (see Templates)

Example:

{
  "template": "with-msw"
}

Response:

{
  "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

List all available story templates.

Parameters: None

Example:

{}

Response:

{
  "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

Get story coverage statistics for the project.

Parameters:

Parameter Type Required Default Description
library string - all Filter by library name

Examples:

// Coverage for entire project
{}

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

Response:

{
  "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

Get a prioritized list of components that need stories.

Parameters:

Parameter Type Required Default Description
limit number - 10 Max number of suggestions
library string - all Filter by library name

Examples:

// Get top 10 suggestions
{}

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

Response:

{
  "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

Check Storybook installation health — missing packages, outdated configs, and version mismatches. Useful for diagnosing setup issues, especially when migrating to Storybook 10.

Parameters: None

Example:

{}

Response:

{
  "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

Regenerate a story file using the latest component analysis while preserving any exports you have written by hand.

Unlike generate_story with overwrite: true (which clobbers everything), update_story detects which export const X: Story blocks you added and appends them below the regenerated content, separated by a comment marker.

Parameters:

Parameter Type Default Description
componentPath string required Path to the component file
includeVariants boolean true Regenerate variant stories
includeInteractive boolean true Regenerate play function tests
includeA11y boolean false Regenerate accessibility stories
includeResponsive boolean false Regenerate viewport stories
template string auto Specific template to use
dryRun boolean false Preview merged result without writing

Example:

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

Response includes:

  • preserved — array of user-written story names that were kept
  • removed — stories not in the merged output (usually empty)
  • validation.warnings — non-blocking import warnings
  • summary — human-readable result with list of preserved stories

How it works:

The tool looks for export const X: Story blocks that are not in the freshly generated content. Those are your custom stories. They get appended after a separator:

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

Note: A version entry is recorded in .forgekit/story-history.json on every write (action: merged).


generate_code_connect

Generate a @figma/code-connect .figma.tsx file that links your component to Figma Dev Mode.

When published with npx figma connect publish, designers inspecting your component in Figma see your real React code — props, variants, and usage examples — instead of auto-generated snippets.

Parameters:

Parameter Type Default Description
componentPath string required Path to the component file
figmaNodeUrl string Figma component URL (https://figma.com/design/<fileId>/...?node-id=...). Omit to use a placeholder.
overwrite boolean false Replace existing .figma.tsx file
dryRun boolean false Preview output without writing

Example:

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

Prop type mapping:

TypeScript type Figma binding
string figma.string('PropName')
boolean figma.boolean('PropName')
'a' | 'b' union figma.enum('PropName', { a: 'a', b: 'b' })
ReactNode / children figma.children(['*'])
number figma.number('PropName')

Event handlers, className, style, and ref are excluded automatically.

Generated output (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>
  ),
})

Publishing to Figma:

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

See Figma Integration for the full workflow.


Figma Integration

This project supports two complementary Figma integrations:

Code Connect — link components to Figma Dev Mode

Figma Code Connect attaches your real React component to a Figma component. Designers in Dev Mode see your actual props, variants, and a working code example instead of placeholder snippets.

Workflow:

  1. Generate a Code Connect file for each component:

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

    npm install --save-dev @figma/code-connect
    npx figma connect login
    npx figma connect publish
    
  3. Open the component in Figma → Dev Mode → Code panel. Your component code appears.

Tip: Copy the Figma node URL by right-clicking a component on the canvas → "Copy link".

Code to Canvas — push story renders into Figma (via forgekit-context)

The sync_stories_to_figma tool (part of forgekit-context) connects to the Figma desktop app's Dev Mode MCP server and pushes each component's Default story as an editable frame on your canvas.

Requirements:

  • Figma desktop app (not browser)
  • Dev Mode MCP server enabled: Figma menu → Preferences → Enable Dev Mode MCP Server
  • forgekit-context installed and running
  • Local Storybook running (npm run storybook)

Example call via forgekit-context:

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

Remove dryRun to push stories to the canvas.


Templates

Templates are pre-built story structures for different use cases. Use them with the template parameter in generate_story.

Template Use Case Example
basic Quick documentation, minimal setup Simple presentational components
with-controls Interactive exploration with all props Design system components
with-variants Showcase all sizes/variants Buttons, badges, avatars
with-msw Components that fetch data User lists, dashboards
with-router Components using React Router Navigation, breadcrumbs
page Full-page components Landing pages, dashboards
interactive Components with user interactions Forms, modals, dropdowns
form Form components with validation Login forms, settings panels

Template Examples

basic - Minimal setup:

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 - Showcase all combinations:

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 - Mock API responses:

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 - Play function tests:

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}')
  },
}

Resources

The MCP provides these read-only resources:

Resource URI Description
storybook://libraries Configured library information
storybook://patterns Common story patterns and best practices
storybook://config Current MCP configuration

Programmatic Usage

You can also use the MCP server programmatically:

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

See ROADMAP.md for what's coming next — migration assistant, watch mode, Figma integration, and more.


Related Projects

This MCP focuses on generating stories, while the official one focuses on reading existing Storybook data. They complement each other.


License

MIT

from github.com/the-single-gentlemans-club/storybook-mcp

Установка Forgekit Storybook

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/the-single-gentlemans-club/storybook-mcp

FAQ

Forgekit Storybook MCP бесплатный?

Да, Forgekit Storybook MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Forgekit Storybook?

Нет, Forgekit Storybook работает без API-ключей и переменных окружения.

Forgekit Storybook — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Forgekit Storybook в Claude Desktop, Claude Code или Cursor?

Открой Forgekit Storybook на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Forgekit Storybook with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development