agentleFS
storybookjsstorybookjs/mcp/.github/copilot-instructions.md

mcp

Copilot instructions270 starsChanged 5 months agoMITArchived repositoryView on GitHub

This is a pnpm monorepo with two MCP implementations: Both packages use tmcp with HTTP transport and Valibot schema validation for consistent APIs. The addon uses a Vite plugin workaround to inject middleware (see packages/addon-mcp/src/preset.ts): Toolset Configuration: The addon supports configuring which toolsets are enabled: The @storybook/mcp package (in packages/mcp) is framework-agnostic: Prerequisites:

We split this copilot-instructions.md into the rules it gives an agent

34 rules. About 0 are common, 7 are distinctive, and 27 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈7

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 27

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Very specific:

    apps/internal-storybook: Test environment for addon integration

    line 14
  2. Distinctive:

    When header is present, only specified toolsets are enabled (others are disabled)

    line 44
  3. Distinctive:

    When header is absent, addon options are used

    line 45
  4. Very specific:

    Run pnpm dev at root for parallel development

    line 89
  5. Very specific:

    Run pnpm storybook to test addon (starts internal-storybook + addon dev mode)

    line 90
  6. Very specific:

    All packages use tsdown (rolldown-based bundler)

    line 94
  7. Very specific:

    Run pnpm test run --coverage in individual package directories

    line 101
  8. Very specific:

    Run pnpm test:run at root to run all unit tests

    line 102
  9. Distinctive:

    Prefer TDD when adding new tools

    line 103
  10. Very specific:

    Run pnpm test in apps/internal-storybook directory

    line 105
  11. Very specific:

    ALWAYS format code after making changes: Run pnpm run format before committing

    line 123
  12. Very specific:

    ALWAYS run checks after formatting: Run pnpm run check to ensure all checks pass

    line 124
  13. Very specific:

    Run pnpm run format to format all files

    line 129
  14. Very specific:

    Run pnpm run check to verify all checks pass

    line 130
  15. Distinctive:

    All packages have TypeScript strict mode enabled

    line 136
  16. Very specific:

    Run pnpm typecheck at root to check all packages

    line 137
  17. Very specific:

    Run pnpm typecheck in individual packages for focused checking

    line 138
  18. Very specific:

    All packages have "type": "module"

    line 152
  19. Very specific:

    Import and call in src/mcp-handler.ts within initializeMCPServer

    line 213
  20. Very specific:

    Import the tool from @storybook/mcp in src/mcp-handler.ts:

    line 217
  21. Distinctive:

    Call it conditionally based on feature flags (see component manifest tools example)

    line 223
  22. Very specific:

    Ensure AddonContext extends StorybookContext for compatibility

    line 224
  23. Very specific:

    Only registers addListAllDocumentationTool and addGetDocumentationTool when enabled

    line 258
  24. Very specific:

    Default manifest URL is constructed from request origin, replacing /mcp with /manifests/components.json

    line 260
  25. Very specific:

    Only includes specified package.json keys in bundle (name, version, description)

    line 295
  26. Very specific:

    If adding new package.json properties to code, update the jsonTreeShakePlugin keys array in shared config

    line 296
  27. Very specific:

    When making changes to @storybook/mcp or @storybook/addon-mcp that affect users (bug fixes, features, breaking changes, dependency …

    line 315
  28. Very specific:

    Create a new .md file in .changeset/ directory

    line 317
  29. Very specific:

    Use naming convention: <random-word>-<random-word>-<random-word>.md (e.g., brave-wolves-swim.md)

    line 318
  30. Very specific:

    Only include packages that have actual user-facing changes (ignore internal packages like @storybook/mcp-internal-storybook)

    line 342
  31. Very specific:

    Test with .mcp.json config pointing to localhost:6006

    line 350
  32. Distinctive:

    When working with the MCP server/tools related stuff, refer to the following resources:

    line 362
  33. Distinctive:

    When working on data validation, refer to the following resources:

    line 368
  34. Very specific:

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

    line 373

≈ “Common” is an estimate: at least 1 in 5 of the 3,669 Copilot instructions files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
copilot-instructions.md

Copilot Instructions for Storybook MCP Addon

Architecture Overview

This is a pnpm monorepo with two MCP implementations:

  • packages/addon-mcp: Storybook addon using tmcp, exposes MCP server at /mcp via Vite middleware
    • Provides addon-specific tools (story URLs, UI building instructions)
    • Imports and reuses tools from @storybook/mcp package for component manifest features
    • Extends StorybookContext with addon-specific configuration (AddonContext)
  • packages/mcp: Standalone MCP library using tmcp, reusable outside Storybook
    • Provides reusable component manifest tools (list components, get documentation)
    • Exports tools and types for consumption by addon-mcp
  • apps/internal-storybook: Test environment for addon integration

Both packages use tmcp with HTTP transport and Valibot schema validation for consistent APIs.

Addon Architecture

The addon uses a Vite plugin workaround to inject middleware (see packages/addon-mcp/src/preset.ts):

  • Storybook doesn't expose an API for addons to register server middleware
  • Solution: Inject a Vite plugin via viteFinal that adds /mcp endpoint
  • Handler in mcp-handler.ts creates MCP servers using tmcp with HTTP transport

Toolset Configuration:

The addon supports configuring which toolsets are enabled:

  • Addon Options: Configure default toolsets in .storybook/main.js:
    {
      name: '@storybook/addon-mcp',
      options: {
        toolsets: {
          dev: true,
          docs: true,
        }
      }
    }
  • Per-Request Override: MCP clients can override toolsets per-request using the X-MCP-Toolsets header:
    • Header format: comma-separated list (e.g., dev,docs)
    • When header is present, only specified toolsets are enabled (others are disabled)
    • When header is absent, addon options are used
  • Tool Enablement: Tools use the enabled callback to check if their toolset is active:
    server.tool(
    	{
    		name: 'my-tool',
    		enabled: () => server.ctx.custom?.toolsets?.dev ?? true,
    	},
    	handler,
    );
  • Context-Aware: The getToolsets() function in mcp-handler.ts parses the header and returns enabled toolsets, which are passed to tools via AddonContext.toolsets

MCP Library Architecture

The @storybook/mcp package (in packages/mcp) is framework-agnostic:

  • Uses tmcp with HTTP transport and Valibot schema validation
  • Factory pattern: createStorybookMcpHandler() returns a request handler
  • Context-based: handlers accept StorybookContext which includes the HTTP Request object and optional callbacks
  • Exports tools and types for reuse by addon-mcp and other consumers
  • Request-based manifest loading: The request property in context is passed to tools, which use it to determine the manifest URL (defaults to same origin, replacing /mcp with the manifest path)
  • Optional manifestProvider: Custom function to override default manifest fetching behavior
    • Signature: (request: Request, path: string) => Promise<string>
    • Receives the Request object and a path parameter (currently always './manifests/components.json')
    • The provider determines the base URL (e.g., mapping to S3 buckets) while the MCP server handles the path
    • Returns the manifest JSON as a string
  • Optional handlers: StorybookContext supports optional handlers that are called at various points, allowing consumers to track usage or collect telemetry:
    • onSessionInitialize: Called when an MCP session is initialized
    • onListAllDocumentation: Called when the list-all-documentation tool is invoked
    • onGetDocumentation: Called when the get-documentation tool is invoked
  • Output Format: Responses are markdown-only (token-efficient markdown with adaptive formatting).
    • Formatter implementations are in packages/mcp/src/utils/manifest-formatter/.

Development Environment

Prerequisites:

  • Node.js 24+ (enforced by .nvmrc)
  • pnpm 10.19.0+ (strict packageManager in root package.json)

Monorepo orchestration:

  • Turborepo manages build dependencies (see turbo.json)
  • Run pnpm dev at root for parallel development
  • Run pnpm storybook to test addon (starts internal-storybook + addon dev mode)

Build tools:

  • All packages use tsdown (rolldown-based bundler)
  • Shared configuration in tsdown-shared.config.ts at monorepo root
  • Individual packages extend shared config in their tsdown.config.ts

Testing:

  • Unit tests: Both packages/mcp and packages/addon-mcp have unit tests (Vitest with coverage)
    • Run pnpm test run --coverage in individual package directories
    • Run pnpm test:run at root to run all unit tests
    • Prefer TDD when adding new tools
  • E2E tests: apps/internal-storybook/tests contains E2E tests for the addon
    • Run pnpm test in apps/internal-storybook directory
    • Tests verify MCP endpoint works with latest Storybook prereleases
    • Uses inline snapshots for response validation
    • When to update E2E tests:
      • Adding or modifying MCP tools (update tool discovery snapshots)
      • Changing MCP protocol implementation (update session init tests)
      • Modifying tool responses or schemas (update tool-specific tests)
      • Adding new toolsets or changing toolset behavior (update filtering tests)
    • Running tests:
      • pnpm test in apps/internal-storybook - run E2E tests
      • pnpm vitest run -u - update snapshots when responses change
      • Tests start Storybook server automatically, wait for MCP endpoint, then run
    • Test structure:
      • mcp-endpoint.e2e.test.ts - MCP protocol and tool tests
      • check-deps.e2e.test.ts - Storybook version validation

Formatting and checks (CRITICAL):

  • ALWAYS format code after making changes: Run pnpm run format before committing
  • ALWAYS run checks after formatting: Run pnpm run check to ensure all checks pass
  • Fix any failing checks: Analyze check results and fix issues until all checks pass
  • This is mandatory for every commit - formatting checks will fail in CI if not done
  • The workflow is:
    1. Make your code changes
    2. Run pnpm run format to format all files
    3. Run pnpm run check to verify all checks pass
    4. Fix any failing checks and repeat step 3 until all pass
    5. Commit your changes

Type checking:

  • All packages have TypeScript strict mode enabled
  • Run pnpm typecheck at root to check all packages
  • Run pnpm typecheck in individual packages for focused checking
  • CI enforces type checking on all PRs
  • Type checking uses tsc --noEmit (no build artifacts, just validation)

Debugging MCP servers:

pnpm inspect  # Launches MCP inspector using .mcp.inspect.json config

Code Style & Conventions

ESM-only codebase:

  • All packages have "type": "module"
  • ALWAYS include file extensions in imports: import { foo } from './bar.ts' (not ./bar)
  • Exception: Package imports don't need extensions

JSON imports:

import pkgJson from '../package.json' with { type: 'json' };

TypeScript config:

  • Uses @tsconfig/node24 base
  • Module resolution: bundler
  • Module format: preserve

Naming:

  • Constants: SCREAMING_SNAKE_CASE (e.g., PREVIEW_STORIES_TOOL_NAME)
  • Functions: camelCase
  • Types: PascalCase

Adding MCP Tools

In addon package (packages/addon-mcp):

Option 1: Addon-specific tools (for tools that require Storybook addon context):

  1. Create src/tools/my-tool.ts:
import type { McpServer } from 'tmcp';
import * as v from 'valibot';
import type { AddonContext } from '../types.ts';

export const MY_TOOL_NAME = 'my_tool';

const MyToolInput = v.object({
	param: v.string(),
});

type MyToolInput = v.InferOutput<typeof MyToolInput>;

export async function addMyTool(server: McpServer<any, AddonContext>) {
	server.tool(
		{
			name: MY_TOOL_NAME,
			title: 'My Tool',
			description: 'What it does',
			schema: MyToolInput,
		},
		async (input: MyToolInput) => {
			// Implementation
			return {
				content: [{ type: 'text', text: 'result' }],
			};
		},
	);
}
  1. Import and call in src/mcp-handler.ts within initializeMCPServer

Option 2: Reuse tools from @storybook/mcp (for component manifest features):

  1. Import the tool from @storybook/mcp in src/mcp-handler.ts:
import { addMyTool, MY_TOOL_NAME } from '@storybook/mcp';
  1. Call it conditionally based on feature flags (see component manifest tools example)
  2. Ensure AddonContext extends StorybookContext for compatibility
  3. Pass the source URL in context for manifest-based tools

In mcp package (packages/mcp):

  1. Create src/tools/my-tool.ts:
export const MY_TOOL_NAME = 'my-tool';

export async function addMyTool(server: McpServer<any, StorybookContext>) {
	server.tool({ name: MY_TOOL_NAME, description: 'What it does' }, async () => ({
		content: [{ type: 'text', text: 'result' }],
	}));
}
  1. Import and call in src/index.ts within createStorybookMcpHandler
  2. Export for reuse in src/index.ts:
export { addMyTool, MY_TOOL_NAME } from './tools/my-tool.ts';

Integration Points

Tool Reuse Between Packages:

  • addon-mcp depends on @storybook/mcp (workspace dependency)
  • AddonContext extends StorybookContext to ensure type compatibility
  • Component manifest tools are conditionally registered based on feature flags:
    • Checks features.componentsManifest flag (or features.experimentalComponentsManifest for backwards compatibility)
    • Checks for experimental_manifests preset
    • Only registers addListAllDocumentationTool and addGetDocumentationTool when enabled
  • Context includes request (HTTP Request object) which tools use to determine manifest location
  • Default manifest URL is constructed from request origin, replacing /mcp with /manifests/components.json
  • Optional handlers for tracking:
    • onSessionInitialize: Called when an MCP session is initialized, receives context
    • onListAllDocumentation: Called when list tool is invoked, receives context and manifest
    • onGetDocumentation: Called when get tool is invoked, receives context, input with id, and optional foundDocumentation
    • Addon-mcp uses these handlers to collect telemetry on tool usage

Storybook internals used:

  • storybook/internal/csf - storyNameFromExport() for story name conversion
  • storybook/internal/types - TypeScript types for Options, StoryIndex
  • storybook/internal/node-logger - Logging utilities
  • Framework detection via options.presets.apply('framework')
  • Feature flags via options.presets.apply('features')
  • Component manifest generator via options.presets.apply('experimental_manifests')

Story URL generation:

  • Fetches http://localhost:${port}/index.json for story index
  • Matches stories by importPath (relative from cwd) and name
  • Returns URLs like http://localhost:6006/?path=/story/button--primary

Telemetry:

  • Addon collects usage data (see src/telemetry.ts)
  • Respects disableTelemetry from Storybook core config
  • Tracks session initialization and tool usage

Special Build Considerations

Shared tsdown configuration:

  • tsdown-shared.config.ts at monorepo root contains shared build settings
  • Targets Node 20.19 (minimum version supported by Storybook 10)
  • Includes custom JSON tree-shaking plugin to work around rolldown bug (see rolldown#6614)
  • Only includes specified package.json keys in bundle (name, version, description)
  • If adding new package.json properties to code, update the jsonTreeShakePlugin keys array in shared config
  • Individual packages extend this config and specify their entry points

Package exports:

  • Addon exports only ./preset (Storybook convention)
  • MCP package exports main module with types

Release Process

Uses Changesets for versioning:

pnpm changeset       # Create a changeset for your changes
pnpm release         # Build and publish (CI handles this)

Creating Changesets (MANDATORY for user-facing changes):

When making changes to @storybook/mcp or @storybook/addon-mcp that affect users (bug fixes, features, breaking changes, dependency updates), you MUST create a changeset:

  1. Create a new .md file in .changeset/ directory
  2. Use naming convention: <random-word>-<random-word>-<random-word>.md (e.g., brave-wolves-swim.md)
  3. File format:

    ---
    '@storybook/mcp': patch
    '@storybook/addon-mcp': patch
    ---
    
    Brief description of what changed
    
    More details about why the change was made and any migration notes if needed.
  4. Version bump types:
    • patch: Bug fixes, security updates, dependency updates (non-breaking)
    • minor: New features (backward compatible)
    • major: Breaking changes
  5. Include in changeset description:
    • WHAT the change is
    • WHY the change was made
    • HOW consumers should update their code (if applicable)
  6. Only include packages that have actual user-facing changes (ignore internal packages like @storybook/mcp-internal-storybook)

Testing with Internal Storybook

The apps/internal-storybook provides a real Storybook instance:

  • Runs on port 6006
  • Addon MCP endpoint: http://localhost:6006/mcp
  • Test with .mcp.json config pointing to localhost:6006

Package-Specific Instructions

For detailed package-specific guidance, see:

  • packages/addon-mcp/** → .github/instructions/addon-mcp.instructions.md
  • packages/mcp/** → .github/instructions/mcp.instructions.md
  • eval/** → .github/instructions/eval.instructions.md

Documentation resources

When working with the MCP server/tools related stuff, refer to the following resources:

When working on data validation, refer to the following resources:

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

Download now (ZIP)

  • Where files are headingNew Copilot instructions files have more rules about branches and pull requests, and fewer about code style.

    Of the Copilot instructions files we read, the 2,297 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.