# @storybook/mcp

> MCP server that serves knowledge about your components based on your Storybook stories and documentation

Latest version **10.6.0** (published 2026-09-02) · MIT license · 0 weekly downloads

## Install

```sh
npm install @storybook/mcp
pnpm add @storybook/mcp
yarn add @storybook/mcp
bun add @storybook/mcp
```

## Health

**Score 75/100 (B)** — status: active.

Positive: esm support; no vulnerabilities; has provenance; recently updated; high maintenance score; popular repo; extremely popular.

Warnings: low downloads; no types.

## Facts

| | |
|---|---|
| Version | 10.6.0 |
| Published | 2026-09-02 |
| First published | 2025-10-22 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | ESM |
| Dependencies | 4 |
| Unpacked size | 149.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 91059 |
| Author | Storybook Core Team |
| Maintainers | ndelangen, shilman, tmeasday, ghengeveld, winkervsbecks, yannbf, kylegach, jreinhold, kasperpeulen, valentinpalkovic, domyen, storybook-bot |
| Keywords | mcp, storybook |

## Links

- npm: https://www.npmjs.com/package/@storybook/mcp
- Repository: https://github.com/storybookjs/storybook
- Homepage: https://github.com/storybookjs/storybook/tree/next/code/lib/mcp
- Issues: https://github.com/storybookjs/storybook/issues
- Funding: https://opencollective.com/storybook
- npm.io page: https://npm.io/package/@storybook/mcp

## Dependencies (4)

- [tmcp](https://npm.io/package/tmcp.md) ^1.19.4
- [valibot](https://npm.io/package/valibot.md) ^1.4.0
- [@tmcp/transport-http](https://npm.io/package/@tmcp/transport-http.md) ^0.8.5
- [@tmcp/adapter-valibot](https://npm.io/package/@tmcp/adapter-valibot.md) ^0.1.5

## Recent versions

- 10.6.0 (latest) — 2026-09-02
- 11.0.0-alpha.1 (next) — 2026-09-19
- 0.0.0-pr-36141-sha-6ddbeb4a (canary) — 2026-09-03
- 11.0.0-alpha.0 — 2026-09-02
- 10.6.0-beta.3 — 2026-09-02
- 10.6.0-beta.2 — 2026-09-01
- 0.0.0-pr-36122-sha-bba02386 — 2026-09-01
- 0.0.0-pr-36098-sha-e4b924c1 — 2026-09-01
- 10.6.0-beta.1 — 2026-09-01
- 0.0.0-pr-36068-sha-1c1cc4bd — 2026-08-31
- 0.0.0-pr-36101-sha-c20fe381 — 2026-08-31
- 0.0.0-pr-35247-sha-1c305226 — 2026-08-27
- 10.6.0-beta.0 — 2026-08-27
- 0.0.0-pr-35949-sha-339a188f — 2026-08-26
- 0.0.0-pr-35949-sha-283efa72 — 2026-08-26
- … 45 more at https://npm.io/package/@storybook/mcp/versions

## README

# Storybook MCP

Reusable MCP package for Storybook component and docs knowledge.

Learn more about Storybook at [storybook.js.org](https://storybook.js.org/?ref=readme).

## Self-hosting `@storybook/mcp`

This package is a library: the tarball ships one module and no executable. It declares no `bin`,
starts no process, and has no CLI. You register its tools on an MCP server you own, using the
snippets below. If you want a running Storybook MCP server with no code at all, use the dev server
instead — `storybook dev` serves one at `/mcp` through `@storybook/addon-mcp`.

### Prerequisites

- Node.js 20+
- A [manifests](https://storybook.js.org/docs/next/ai/manifests) source containing:
  - `components.json` (required)
  - `docs.json` (optional)

### Example implementation

The Storybook repository has a local HTTP server built on this package,
[`serve.ts`](https://github.com/storybookjs/storybook/blob/next/code/lib/mcp/serve.ts), that loads
manifests from a directory or URL. It is a development harness and is not part of the published
package.

The snippets below cover the common self-hosting patterns.

#### Minimal implementation

```ts
import { createStorybookMcpHandler } from '@storybook/mcp';

const storybookMcpHandler = await createStorybookMcpHandler();

export async function handleRequest(request: Request): Promise<Response> {
	if (new URL(request.url).pathname === '/mcp') {
		return storybookMcpHandler(request);
	}

	return new Response('Not found', { status: 404 });
}
```

#### With custom manifest source

Use `manifestProvider` when your manifests are not available from the same origin/path layout:

```ts
const storybookMcpHandler = await createStorybookMcpHandler({
	manifestProvider: async (_request, path) => {
		return asyncReadManifestFromSomewhere(path);
	},
});
```

### API reference

#### `createStorybookMcpHandler`

Type:

```ts
(options?: StorybookMcpHandlerOptions) => Promise<Handler>;

type Handler = (req: Request, context?: StorybookContext) => Promise<Response>;
```

Creates and configures an MCP HTTP handler with all built-in docs tools registered.

##### Parameters

###### `options`

Type: [`StorybookMcpHandlerOptions`](#handler-options-and-request-context)

Default: `{}`

Server-level configuration. The handler uses this at creation time and as a fallback for per-request context.

##### Returns

Type: `Promise<Handler>`

A fetch-compatible request handler for your `/mcp` endpoint.

##### Behavior

- Registers these MCP tools:
  - [`docs-list`](https://storybook.js.org/docs/next/ai/mcp/overview/#docs-list)
  - [`docs-show`](https://storybook.js.org/docs/next/ai/mcp/overview/#docs-show)
  - [`docs-show-story`](https://storybook.js.org/docs/next/ai/mcp/overview/#docs-show-story)
- Uses HTTP transport from [`@tmcp/transport-http`](https://github.com/paoloricciuti/tmcp/).
- For each request, the handler always passes the current `Request` as `context.request`.
- Per-request `context` overrides handler-level `options` for:
  - [`manifestProvider`](#manifestprovider)
  - [`onListAllDocumentation`](#onlistalldocumentation)
  - [`onGetDocumentation`](#ongetdocumentation)

> Note: [`onSessionInitialize`](#handler-options-and-request-context) can only be set at handler creation time (in `options`).

##### Example

```ts
import { createStorybookMcpHandler } from '@storybook/mcp';

const mcp = await createStorybookMcpHandler({
	manifestProvider: async (_request, path) => {
		return await fetchManifest(path);
	},
});

export async function handleRequest(request: Request) {
	if (new URL(request.url).pathname !== '/mcp') {
		return new Response('Not found', { status: 404 });
	}

	return mcp(request);
}
```

#### Handler options and request context

`@storybook/mcp` uses the same core fields in two places:

- Handler creation (`createStorybookMcpHandler(options)`)
- Per-request override (`handler(request, context)`)

Type:

```ts
type StorybookContext = {
	request?: Request;
	manifestProvider?: (
		request: Request | undefined,
		path: string,
		source?: Source,
	) => Promise<string>;
	sources?: Source[];
	onListAllDocumentation?: (params: {
		context: StorybookContext;
		manifests: AllManifests;
		resultText: string;
		sources?: SourceManifests[];
	}) => void | Promise<void>;
	onGetDocumentation?: (
		params:
			| {
					context: StorybookContext;
					input: { id: string; storybookId?: string };
					foundDocumentation: ComponentManifest | Doc;
					resultText: string;
			  }
			| {
					context: StorybookContext;
					input: { id: string; storybookId?: string };
			  },
	) => void | Promise<void>;
};

type StorybookMcpHandlerOptions = StorybookContext & {
	onSessionInitialize?: (initializeRequestParams: InitializeRequestParams) => void | Promise<void>;
};
```

> [!NOTE]
> `onSessionInitialize` is only used when provided at handler creation time (`createStorybookMcpHandler(options)`). It is ignored in per-request `context`.
>
> `InitializeRequestParams` is the [`tmcp`](https://github.com/paoloricciuti/tmcp/) initialize payload type, and its exact structure may change in patch versions. Prefer treating it as an opaque protocol payload unless you need specific fields.

##### `manifestProvider`

Type:

```ts
(request: Request | undefined, path: string, source?: Source) => Promise<string>;
```

Primary extension point for production setups.

Use this when manifests are not available at the default same-origin paths. Your function returns the raw JSON string for each requested manifest path.

For a real customization example (switching between HTTP and filesystem-backed manifest loading), see the [Example implementation](#example-implementation) section above.

Manifest paths requested by built-in tools:

- `./manifests/components.json` (required)
- `./manifests/docs.json` (optional)

##### `request`

Type: `Request`

The incoming HTTP request for the current call, as a Web Fetch API (`WHATWG`) `Request`.

This is **not** a Node.js `http.IncomingMessage`. In Node runtimes, pass a fetch-compatible `Request` (for example, Node's global `Request` from Undici in modern Node versions), or convert your server's native request object before calling the handler.

`createStorybookMcpHandler` automatically sets this field when you invoke the returned handler with `(request, context?)`.

##### `onListAllDocumentation`

Type:

```ts
(params: {
  context: StorybookContext;
  manifests: AllManifests;
  resultText: string;
  sources?: SourceManifests[];
}) => void | Promise<void>
```

Optional callback after `docs-list` resolves successfully.

##### `onGetDocumentation`

Type:

```ts
(
  params:
    | {
        context: StorybookContext;
        input: { id: string; storybookId?: string };
        foundDocumentation: ComponentManifest | Doc;
        resultText: string;
      }
    | {
        context: StorybookContext;
        input: { id: string; storybookId?: string };
      },
) => void | Promise<void>
```

Optional callback after `docs-show` runs:

- When a component/docs entry is found, receives `foundDocumentation` and `resultText`.
- When not found, receives only `context` and `input`.

##### `sources`

Type: `Source[]`

Optional multi-source configuration for composing multiple Storybook MCP sources. This is supported but relatively uncommon for most user setups.

#### `Source`

Type:

```ts
type Source = {
	id: string;
	title: string;
	url?: string;
};
```

Represents one Storybook source in multi-source mode.

#### `SourceManifests`

Type:

```ts
type SourceManifests = {
	source: Source;
	componentManifest: ComponentManifestMap;
	docsManifest?: DocsManifestMap;
	error?: string;
	notice?: RequiresOwnMcpNotice;
};
```

Represents fetched manifests, an error, or non-error routing guidance for a single source.

#### `RequiresOwnMcpNotice`

Type:

```ts
type RequiresOwnMcpNotice = {
	kind: 'requires-own-mcp';
	endpoint: string;
};
```

Indicates that a composed Storybook source cannot be read through the local MCP proxy and should be accessed through its own MCP endpoint instead.

#### Tool registration exports

Use these when you want to build your own [`tmcp`](https://github.com/paoloricciuti/tmcp/) server instead of using `createStorybookMcpHandler`, while still reusing Storybook's docs tools.

This approach is useful when you need to:

- register Storybook tools alongside your own custom tools,
- customize transport/session setup yourself,
- or conditionally enable tools based on your own server context.

> [!IMPORTANT]
> These composition helpers are built for `tmcp`'s `McpServer` and **cannot** be directly composed into a server built with the [official MCP TypeScript SDK (`@modelcontextprotocol/sdk`)](https://github.com/modelcontextprotocol/typescript-sdk).

Minimal composition example:

```ts
import { McpServer } from 'tmcp';
import { ValibotJsonSchemaAdapter } from '@tmcp/adapter-valibot';
import {
	addGetStoryDocumentationTool,
	addGetDocumentationTool,
	addListAllDocumentationTool,
	type StorybookContext,
} from '@storybook/mcp';

const adapter = new ValibotJsonSchemaAdapter();
const server = new McpServer(
	{ name: 'custom-mcp', version: '1.0.0' },
	{
		adapter,
		capabilities: {
			tools: { listChanged: true },
		},
	},
).withContext<StorybookContext>();

await addListAllDocumentationTool(server);
await addGetDocumentationTool(server);
await addGetStoryDocumentationTool(server);
```

After registration, wire your own transport and pass `StorybookContext` per request so tools can resolve manifests (`request`, `manifestProvider`, and optional `sources`).

#### `addListAllDocumentationTool`

Type:

```ts
(server: McpServer<any, StorybookContext>, enabled?: () => boolean | Promise<boolean>) =>
	Promise<void>;
```

Registers the [list tool](https://storybook.js.org/docs/next/ai/mcp/overview/#docs-list) that returns all component/docs IDs from manifests.

#### `addGetDocumentationTool`

Type:

```ts
(
	server: McpServer<any, StorybookContext>,
	enabled?: () => boolean | Promise<boolean>,
	options?: { multiSource?: boolean },
) => Promise<void>;
```

Registers [documentation lookup](https://storybook.js.org/docs/next/ai/mcp/overview/#docs-show) by component/docs `id`.

When `options.multiSource` is `true`, the tool schema requires `storybookId` input.

#### `addGetStoryDocumentationTool`

Type:

```ts
(
	server: McpServer<any, StorybookContext>,
	enabled?: () => boolean | Promise<boolean>,
	options?: { multiSource?: boolean },
) => Promise<void>;
```

Registers [story-level documentation lookup](https://storybook.js.org/docs/next/ai/mcp/overview/#docs-show-story) for a specific story variant by `componentId` and `storyName`.

---
_Source: https://npm.io/package/@storybook/mcp · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
