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
- Very specific: line 14
apps/internal-storybook: Test environment for addon integration - Distinctive: line 44
When header is present, only specified toolsets are enabled (others are disabled)
- Distinctive: line 45
When header is absent, addon options are used
- Very specific: line 89
Run pnpm dev at root for parallel development
- Very specific: line 90
Run pnpm storybook to test addon (starts internal-storybook + addon dev mode)
- Very specific: line 94
All packages use tsdown (rolldown-based bundler)
- Very specific: line 101
Run pnpm test run --coverage in individual package directories
- Very specific: line 102
Run pnpm test:run at root to run all unit tests
- Distinctive: line 103
Prefer TDD when adding new tools
- Very specific: line 105
Run pnpm test in apps/internal-storybook directory
- Very specific: line 123
ALWAYS format code after making changes: Run pnpm run format before committing
- Very specific: line 124
ALWAYS run checks after formatting: Run pnpm run check to ensure all checks pass
- Very specific: line 129
Run pnpm run format to format all files
- Very specific: line 130
Run pnpm run check to verify all checks pass
- Distinctive: line 136
All packages have TypeScript strict mode enabled
- Very specific: line 137
Run pnpm typecheck at root to check all packages
- Very specific: line 138
Run pnpm typecheck in individual packages for focused checking
- Very specific: line 152
All packages have "type": "module"
- Very specific: line 213
Import and call in src/mcp-handler.ts within initializeMCPServer
- Very specific: line 217
Import the tool from @storybook/mcp in src/mcp-handler.ts:
- Distinctive: line 223
Call it conditionally based on feature flags (see component manifest tools example)
- Very specific: line 224
Ensure AddonContext extends StorybookContext for compatibility
- Very specific: line 258
Only registers addListAllDocumentationTool and addGetDocumentationTool when enabled
- Very specific: line 260
Default manifest URL is constructed from request origin, replacing /mcp with /manifests/components.json
- Very specific: line 295
Only includes specified package.json keys in bundle (name, version, description)
- Very specific: line 296
If adding new package.json properties to code, update the jsonTreeShakePlugin keys array in shared config
- Very specific: line 315
When making changes to @storybook/mcp or @storybook/addon-mcp that affect users (bug fixes, features, breaking changes, dependency …
- Very specific: line 317
Create a new .md file in .changeset/ directory
- Very specific: line 318
Use naming convention: <random-word>-<random-word>-<random-word>.md (e.g., brave-wolves-swim.md)
- Very specific: line 342
Only include packages that have actual user-facing changes (ignore internal packages like @storybook/mcp-internal-storybook)
- Very specific: line 350
Test with .mcp.json config pointing to localhost:6006
- Distinctive: line 362
When working with the MCP server/tools related stuff, refer to the following resources:
- Distinctive: line 368
When working on data validation, refer to the following resources:
- Very specific: line 373
When working with MCP Apps and/or the preview-stories.ts file, refer to the MCP App specification:
≈ “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.
Files
Copilot Instructions for Storybook MCP Addon
Architecture Overview
This is a pnpm monorepo with two MCP implementations:
packages/addon-mcp: Storybook addon usingtmcp, exposes MCP server at/mcpvia Vite middleware- Provides addon-specific tools (story URLs, UI building instructions)
- Imports and reuses tools from
@storybook/mcppackage for component manifest features - Extends
StorybookContextwith addon-specific configuration (AddonContext)
packages/mcp: Standalone MCP library usingtmcp, 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
viteFinalthat adds/mcpendpoint - Handler in
mcp-handler.tscreates MCP servers usingtmcpwith 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-Toolsetsheader:- 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
- Header format: comma-separated list (e.g.,
- Tool Enablement: Tools use the
enabledcallback 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 inmcp-handler.tsparses the header and returns enabled toolsets, which are passed to tools viaAddonContext.toolsets
MCP Library Architecture
The @storybook/mcp package (in packages/mcp) is framework-agnostic:
- Uses
tmcpwith HTTP transport and Valibot schema validation - Factory pattern:
createStorybookMcpHandler()returns a request handler - Context-based: handlers accept
StorybookContextwhich includes the HTTPRequestobject and optional callbacks - Exports tools and types for reuse by
addon-mcpand other consumers - Request-based manifest loading: The
requestproperty in context is passed to tools, which use it to determine the manifest URL (defaults to same origin, replacing/mcpwith the manifest path) - Optional manifestProvider: Custom function to override default manifest fetching behavior
- Signature:
(request: Request, path: string) => Promise<string> - Receives the
Requestobject and apathparameter (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
- Signature:
- Optional handlers:
StorybookContextsupports optional handlers that are called at various points, allowing consumers to track usage or collect telemetry:onSessionInitialize: Called when an MCP session is initializedonListAllDocumentation: Called when the list-all-documentation tool is invokedonGetDocumentation: 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/.
- Formatter implementations are in
Development Environment
Prerequisites:
- Node.js 24+ (enforced by
.nvmrc) - pnpm 10.19.0+ (strict
packageManagerin rootpackage.json)
Monorepo orchestration:
- Turborepo manages build dependencies (see
turbo.json) - Run
pnpm devat root for parallel development - Run
pnpm storybookto test addon (starts internal-storybook + addon dev mode)
Build tools:
- All packages use
tsdown(rolldown-based bundler) - Shared configuration in
tsdown-shared.config.tsat monorepo root - Individual packages extend shared config in their
tsdown.config.ts
Testing:
- Unit tests: Both
packages/mcpandpackages/addon-mcphave unit tests (Vitest with coverage)- Run
pnpm test run --coveragein individual package directories - Run
pnpm test:runat root to run all unit tests - Prefer TDD when adding new tools
- Run
- E2E tests:
apps/internal-storybook/testscontains E2E tests for the addon- Run
pnpm testinapps/internal-storybookdirectory - 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 testin apps/internal-storybook - run E2E testspnpm 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 testscheck-deps.e2e.test.ts- Storybook version validation
- Run
Formatting and checks (CRITICAL):
- ALWAYS format code after making changes: Run
pnpm run formatbefore committing - ALWAYS run checks after formatting: Run
pnpm run checkto 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:
- Make your code changes
- Run
pnpm run formatto format all files - Run
pnpm run checkto verify all checks pass - Fix any failing checks and repeat step 3 until all pass
- Commit your changes
Type checking:
- All packages have TypeScript strict mode enabled
- Run
pnpm typecheckat root to check all packages - Run
pnpm typecheckin 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 configCode 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/node24base - 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):
- 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' }],
};
},
);
}- Import and call in
src/mcp-handler.tswithininitializeMCPServer
Option 2: Reuse tools from @storybook/mcp (for component manifest features):
- Import the tool from
@storybook/mcpinsrc/mcp-handler.ts:
import { addMyTool, MY_TOOL_NAME } from '@storybook/mcp';- Call it conditionally based on feature flags (see component manifest tools example)
- Ensure
AddonContextextendsStorybookContextfor compatibility - Pass the
sourceURL in context for manifest-based tools
In mcp package (packages/mcp):
- 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' }],
}));
}- Import and call in
src/index.tswithincreateStorybookMcpHandler - Export for reuse in
src/index.ts:
export { addMyTool, MY_TOOL_NAME } from './tools/my-tool.ts';Integration Points
Tool Reuse Between Packages:
addon-mcpdepends on@storybook/mcp(workspace dependency)AddonContextextendsStorybookContextto ensure type compatibility- Component manifest tools are conditionally registered based on feature flags:
- Checks
features.componentsManifestflag (orfeatures.experimentalComponentsManifestfor backwards compatibility) - Checks for
experimental_manifestspreset - Only registers
addListAllDocumentationToolandaddGetDocumentationToolwhen enabled
- Checks
- Context includes
request(HTTP Request object) which tools use to determine manifest location - Default manifest URL is constructed from request origin, replacing
/mcpwith/manifests/components.json - Optional handlers for tracking:
onSessionInitialize: Called when an MCP session is initialized, receives contextonListAllDocumentation: Called when list tool is invoked, receives context and manifestonGetDocumentation: 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 conversionstorybook/internal/types- TypeScript types for Options, StoryIndexstorybook/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.jsonfor story index - Matches stories by
importPath(relative from cwd) andname - Returns URLs like
http://localhost:6006/?path=/story/button--primary
Telemetry:
- Addon collects usage data (see
src/telemetry.ts) - Respects
disableTelemetryfrom Storybook core config - Tracks session initialization and tool usage
Special Build Considerations
Shared tsdown configuration:
tsdown-shared.config.tsat 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
jsonTreeShakePluginkeys 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:
- Create a new
.mdfile in.changeset/directory - Use naming convention:
<random-word>-<random-word>-<random-word>.md(e.g.,brave-wolves-swim.md) 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.- Version bump types:
patch: Bug fixes, security updates, dependency updates (non-breaking)minor: New features (backward compatible)major: Breaking changes
- Include in changeset description:
- WHAT the change is
- WHY the change was made
- HOW consumers should update their code (if applicable)
- 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.jsonconfig pointing to localhost:6006
Package-Specific Instructions
For detailed package-specific guidance, see:
packages/addon-mcp/**→.github/instructions/addon-mcp.instructions.mdpackages/mcp/**→.github/instructions/mcp.instructions.mdeval/**→.github/instructions/eval.instructions.md
Documentation resources
When working with the MCP server/tools related stuff, refer to the following resources:
- https://github.com/paoloricciuti/tmcp/tree/main/packages/tmcp
- https://github.com/paoloricciuti/tmcp/tree/main/packages/transport-http
- https://github.com/paoloricciuti/tmcp
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:
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.

