Skip to content

fix(mcp): expand aliased enum values in react-docgen-typescript output#222

Open
keidy9 wants to merge 4 commits intostorybookjs:mainfrom
keidy9:fix/rdt-aliased-enum-values
Open

fix(mcp): expand aliased enum values in react-docgen-typescript output#222
keidy9 wants to merge 4 commits intostorybookjs:mainfrom
keidy9:fix/rdt-aliased-enum-values

Conversation

@keidy9
Copy link
Copy Markdown

@keidy9 keidy9 commented Apr 30, 2026

Summary

Fixes a serializer bug in parseComponentDocLike where a prop typed as a named alias of a string-literal union (e.g. variant?: ButtonVariant) renders as the alias name instead of the resolved members.

When react-docgen-typescript is configured with shouldExtractLiteralValuesFromEnum: true, it produces:

type: {
  name: "enum",
  raw: "ButtonVariant",            // alias name
  value: [{value: '"primary"'}, {value: '"neutral"'}, ...]   // resolved literals
}

The previous code did prop.type?.raw ?? prop.type?.name and never read type.value, so consumers received the alias name with no member list. The bug doesn't surface for inline unions (variant?: "primary" | "secondary") because type.raw already holds the literals — which is exactly the shape used in packages/mcp/fixtures/button.fixture.json, so the existing tests passed.

The companion react-docgen path (serializeTsType) handles aliased unions correctly by walking elements; only the RDT path was broken.

Change

  • New serializeRdtType helper: when type.name === "enum" and type.value is a non-empty array, join its members. Otherwise fall back to type.raw ?? type.name (preserving prior behavior for non-enum types and for enums with no value array).
  • Renamed the existing "prefers type.raw over type.name for enums" test to "expands enum members for inline string-literal unions" — the snapshot is unchanged because for inline unions the joined members equal the raw string.
  • Added a regression test covering the aliased-union case (type.raw === "ButtonVariant", type.value populated) — fails on main, passes here.
  • Added a fallback test for an enum with type.raw but no type.value, asserting the alias name is still returned in that degraded shape.

Why

Reported by a user whose Button design-system component uses type ButtonVariant = "primary" | "neutral" | "danger" | "dangerSecondary" | "muted" | "link" | "custom". Storybook's Controls panel correctly populates the select dropdown from __docgenInfo.type.value, so the data is present in the bundle — only the MCP's prop renderer was dropping it. After this patch, the get-documentation output enumerates the variants the same way it does for inline unions like iconPosition?: "left" | "right".

Test plan

  • pnpm vitest --project=@storybook/mcp run — 163/163 pass
  • New tests cover: inline union (snapshot unchanged), aliased union (regression), enum with raw but no value (fallback)
  • Reviewer: confirm no other call site reads type.raw directly and would break with the now-expanded form

🤖 Generated with Claude Code

When a prop's type is a named alias of a string-literal union (e.g.
`variant?: ButtonVariant`), `shouldExtractLiteralValuesFromEnum` makes
RDT record the alias name in `type.raw` and the resolved literals in
`type.value`. The serializer only read `type.raw`, so consumers got the
alias name and lost the member list (`variant?: ButtonVariant` instead
of `variant?: "primary" | "neutral" | ...`).

Walk `type.value` for `enum`-named types and fall back to `type.raw` /
`type.name` only when no members are present. Inline and aliased unions
now render the same way.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 30, 2026

🦋 Changeset detected

Latest commit: be1b897

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@storybook/mcp Patch
@storybook/addon-mcp Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 30, 2026

Deploy Preview for storybook-mcp-self-host-example canceled.

Name Link
🔨 Latest commit be1b897
🔍 Latest deploy log https://app.netlify.com/projects/storybook-mcp-self-host-example/deploys/69f37426f430e90007f6bdda

@keidy9 keidy9 marked this pull request as ready for review April 30, 2026 06:02
@keidy9
Copy link
Copy Markdown
Author

keidy9 commented Apr 30, 2026

Hi @JReinhold, would you mind reviewing please?

@JReinhold JReinhold added the enhancement New feature or request label Apr 30, 2026
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 30, 2026

npm i https://pkg.pr.new/storybookjs/mcp/@storybook/addon-mcp@222
npm i https://pkg.pr.new/storybookjs/mcp/@storybook/mcp@222

commit: a56859f

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes @storybook/mcp’s react-docgen-typescript (RDT) prop type serialization so string-literal unions referenced via named aliases (e.g. variant?: ButtonVariant) render expanded union members instead of only the alias name, aligning MCP output with what Storybook Controls already derives from __docgenInfo.

Changes:

  • Add serializeRdtType to expand enum-named RDT types using type.value when present, with fallback to prior raw/name behavior.
  • Update and extend unit tests to cover inline unions, aliased unions (regression), and the degraded “no value array” fallback case.
  • Add a changeset for the user-facing patch release.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
packages/mcp/src/utils/parse-react-docgen.ts Introduces serializeRdtType and routes RDT parsing through it to expand aliased enum/union members.
packages/mcp/src/utils/parse-react-docgen.test.ts Renames the existing enum test and adds regression + fallback coverage for aliased unions and missing type.value.
.changeset/fix-rdt-aliased-enum-values.md Declares a patch release and documents the behavior change for consumers.

Comment thread packages/mcp/src/utils/parse-react-docgen.test.ts Outdated
keidy9 and others added 3 commits April 30, 2026 03:09
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
RDT's PropItemType declares value?: any, so { name: 'enum', raw: 'ButtonVariant' }
satisfies the type natively. Per Copilot review.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@keidy9
Copy link
Copy Markdown
Author

keidy9 commented May 1, 2026

Hi @kasperpeulen, could you review please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants