From d75281cb678af186595c2a2d52b3cd6e08766432 Mon Sep 17 00:00:00 2001 From: chinawch007 Date: Tue, 25 Aug 2026 03:17:39 +0800 Subject: [PATCH] feat(storybook): expose component docs to agents via official MCP addon (#3527) Self-host the Storybook MCP endpoint at http://localhost:6006/mcp with only the docs toolset enabled: - install @storybook/addon-mcp in apps/desktop and register it in .storybook/main.ts with dev/test toolsets off (test needs @storybook/addon-vitest and stays a follow-up per the issue) - register the endpoint for agent clients in a new root .mcp.json ("type": "http" client convention; $schema omitted since no official schema covers this client config format) - add AGENTS.md guidance to query the MCP before writing UI code in packages/ui or apps/desktop, preferring existing components Verified: storybook boots unchanged, tools/list exposes exactly the three docs tools, and list-all-documentation / get-documentation / get-documentation-for-story return real story docs over the endpoint. Generated-by: ZCode --- .mcp.json | 8 ++ AGENTS.md | 50 +++++++++ apps/desktop/.storybook/main.ts | 15 +++ apps/desktop/package.json | 1 + package-lock.json | 173 ++++++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+) create mode 100644 .mcp.json create mode 100644 AGENTS.md diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000000..51cb758767 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "storybook": { + "type": "http", + "url": "http://localhost:6006/mcp" + } + } +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..a2f6683641 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,50 @@ + + +# AGENTS.md + +Guidance for AI coding agents working in this repository. + +## Frontend work: query the Storybook MCP before writing UI code + +UI code lives in `packages/ui` (shared components) and `apps/desktop` (desktop +app). Before writing or modifying UI code, discover what already exists through +the Storybook MCP server instead of reading component sources to guess props +and usage: + +1. Start Storybook on demand (dev-only server; nothing auto-starts it): + + ``` + npm --workspace @maka/desktop run storybook -- --no-open + ``` + +2. Connect to the MCP endpoint at `http://localhost:6006/mcp` (registered for + agents in the root `.mcp.json`). The endpoint only responds while Storybook + is running; if it is unreachable, start it as above. + +3. Query, then write: + + - `list-all-documentation` — every documented story/component + - `get-documentation-for-story` — props and usage for one story + - `get-documentation` — docs entry for a component + +Prefer composing existing `packages/ui` components. Introduce a new component +only when nothing existing fits, and give it a story so it becomes discoverable +through the same interface. Avoid adding third-party UI dependencies without a +clear need. diff --git a/apps/desktop/.storybook/main.ts b/apps/desktop/.storybook/main.ts index 8aa012a7dd..4c4816d79c 100644 --- a/apps/desktop/.storybook/main.ts +++ b/apps/desktop/.storybook/main.ts @@ -35,6 +35,21 @@ const config: StorybookConfig = { '../../../packages/ui/stories/**/*.stories.@(ts|tsx)', resolve(REPO_ROOT, 'apps/desktop/stories/**/*.stories.@(ts|tsx)'), ], + addons: [ + { + name: '@storybook/addon-mcp', + options: { + // Issue #3527: agents get a queryable component-docs interface. + // Docs toolset only; dev/test toolsets are deliberate follow-ups + // (test additionally needs @storybook/addon-vitest). + toolsets: { + dev: false, + test: false, + docs: true, + }, + }, + }, + ], framework: { name: '@storybook/react-vite', options: {}, diff --git a/apps/desktop/package.json b/apps/desktop/package.json index b08ce8ef13..35c817f085 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -66,6 +66,7 @@ "@maka/ui": "0.1.0", "@modelcontextprotocol/sdk": "^1.26.0", "@playwright/test": "^1.62.1", + "@storybook/addon-mcp": "^0.7.0", "@storybook/react-vite": "^10.5.10", "@types/react": "^19.2.18", "@types/react-dom": "^19.2.4", diff --git a/package-lock.json b/package-lock.json index 963aae16b8..2e1ca656d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,6 +66,7 @@ "@maka/ui": "0.1.0", "@modelcontextprotocol/sdk": "^1.26.0", "@playwright/test": "^1.62.1", + "@storybook/addon-mcp": "^0.7.0", "@storybook/react-vite": "^10.5.10", "@types/react": "^19.2.18", "@types/react-dom": "^19.2.4", @@ -3711,6 +3712,30 @@ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "license": "MIT" }, + "node_modules/@storybook/addon-mcp": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-mcp/-/addon-mcp-0.7.0.tgz", + "integrity": "sha512-f/IWGRMzWynBg5kDJ3DYvvnafuSX88kykGNFzzLOlkLVpfxEZoAmQF6AS47tw25GuH6EFIqSo6ZDBLHLVyZ/IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/mcp": "0.8.0", + "@tmcp/adapter-valibot": "^0.1.5", + "@tmcp/transport-http": "^0.8.5", + "picoquery": "^2.5.0", + "tmcp": "^1.19.4", + "valibot": "1.2.0" + }, + "peerDependencies": { + "@storybook/addon-vitest": "^0.0.0-0 || ^9.1.16 || ^10.0.0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 || ^10.4.0-0 || ^10.5.0-0", + "storybook": "^0.0.0-0 || ^9.1.16 || ^10.0.0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 || ^10.4.0-0 || ^10.5.0-0" + }, + "peerDependenciesMeta": { + "@storybook/addon-vitest": { + "optional": true + } + } + }, "node_modules/@storybook/builder-vite": { "version": "10.5.10", "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-10.5.10.tgz", @@ -3782,6 +3807,19 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/@storybook/mcp": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@storybook/mcp/-/mcp-0.8.0.tgz", + "integrity": "sha512-G+XDgoWGrE98moXqKSee8fQyMQxoIWxRAbPG8r/HQ95pKodratevDqNyOgW+t6ZigM6AAVN1WHiFc5MI+hc8sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tmcp/adapter-valibot": "^0.1.5", + "@tmcp/transport-http": "^0.8.5", + "tmcp": "^1.19.4", + "valibot": "1.2.0" + } + }, "node_modules/@storybook/react": { "version": "10.5.10", "resolved": "https://registry.npmjs.org/@storybook/react/-/react-10.5.10.tgz", @@ -3964,6 +4002,77 @@ "@testing-library/dom": ">=7.21.4" } }, + "node_modules/@tmcp/adapter-valibot": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@tmcp/adapter-valibot/-/adapter-valibot-0.1.6.tgz", + "integrity": "sha512-drirZeNinhYLiRSMksN+m//u0ImFxtGRk1Vp425Xp/7CbBXFQdjAG+f7grssyHAukbVTGzmWsMMP6ejrGVErUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@valibot/to-json-schema": "^1.3.0", + "valibot": "^1.1.0" + }, + "peerDependencies": { + "tmcp": "^1.17.0", + "valibot": "^1.1.0" + } + }, + "node_modules/@tmcp/adapter-valibot/node_modules/@valibot/to-json-schema": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@valibot/to-json-schema/-/to-json-schema-1.7.1.tgz", + "integrity": "sha512-3qkmU6KXWh8GIThEAW3kuRHPQBMjWkKy+Ppz3WkUucx53DTpOa6siMn4xDGSOhlVyMrDaJTCTMLYPZVAIk1P0A==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "valibot": "^1.4.0" + } + }, + "node_modules/@tmcp/adapter-valibot/node_modules/valibot": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.4.2.tgz", + "integrity": "sha512-gjdCvJ6d3RyHAneqxMYMW9QMCwYMb3jpOO0IyHZV1bnRHFBHrX3VkIILt5XYR0WhwHiH7Mty8ovuPZ/O3gamrg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@tmcp/session-manager": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@tmcp/session-manager/-/session-manager-0.2.2.tgz", + "integrity": "sha512-UrCRpTsxh5XnMbplspvftEYboiZWgAiXqqAUbyFTHoHMJ0LoNDy8bQd0+7qtxtT4S5Qsnv650gvs/Nbec5NTCQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "tmcp": "^1.16.3" + } + }, + "node_modules/@tmcp/transport-http": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/@tmcp/transport-http/-/transport-http-0.8.6.tgz", + "integrity": "sha512-iLcxu+tEMbkVHbhFfyXQhxfPDDTfm+F0kEw8Xg/a1rm29s4cBg1vwcpbtk02XTxsdDh8RJ1AZkQwF9WDGeb/IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tmcp/session-manager": "^0.2.2", + "esm-env": "^1.2.2" + }, + "peerDependencies": { + "@tmcp/auth": "^0.3.3 || ^0.4.0", + "tmcp": "^1.18.0" + }, + "peerDependenciesMeta": { + "@tmcp/auth": { + "optional": true + } + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", @@ -7613,6 +7722,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/esm-env": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", + "dev": true, + "license": "MIT" + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -8999,6 +9115,13 @@ "dev": true, "license": "MIT" }, + "node_modules/json-rpc-2.0": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/json-rpc-2.0/-/json-rpc-2.0-1.7.1.tgz", + "integrity": "sha512-JqZjhjAanbpkXIzFE7u8mE/iFblawwlXtONaCvRqI+pyABVz7B4M1EUNpyVW+dZjqgQ2L5HFmZCmOCgUKm00hg==", + "dev": true, + "license": "MIT" + }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", @@ -11071,6 +11194,13 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/picoquery": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/picoquery/-/picoquery-2.5.0.tgz", + "integrity": "sha512-j1kgOFxtaCyoFCkpoYG2Oj3OdGakadO7HZ7o5CqyRazlmBekKhbDoUnNnXASE07xSY4nDImWZkrZv7toSxMi/g==", + "dev": true, + "license": "MIT" + }, "node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -12481,6 +12611,13 @@ "license": "BSD-3-Clause", "optional": true }, + "node_modules/sqids": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/sqids/-/sqids-0.3.0.tgz", + "integrity": "sha512-lOQK1ucVg+W6n3FhRwwSeUijxe93b51Bfz5PMRMihVf1iVkl82ePQG7V5vwrhzB11v0NtsR25PSZRGiSomJaJw==", + "dev": true, + "license": "MIT" + }, "node_modules/stat-mode": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", @@ -13174,6 +13311,20 @@ "node": ">=14.0.0" } }, + "node_modules/tmcp": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/tmcp/-/tmcp-1.20.0.tgz", + "integrity": "sha512-dcDximKQBGqLP/aEAVA26HcWRHhKipstg1w0fbDDJ0HcFZ6lolLU1YYmStYEn/73f534i7WrDNcjRfRYdV9CoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "json-rpc-2.0": "^1.7.1", + "sqids": "^0.3.0", + "uri-template-matcher": "^1.1.1", + "valibot": "^1.1.0" + } + }, "node_modules/tmp": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", @@ -13485,6 +13636,13 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-template-matcher": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/uri-template-matcher/-/uri-template-matcher-1.1.2.tgz", + "integrity": "sha512-uZc1h12jdO3m/R77SfTEOuo6VbMhgWznaawKpBjRGSJb7i91x5PgI37NQJtG+Cerxkk0yr1pylBY2qG1kQ+aEQ==", + "dev": true, + "license": "ISC" + }, "node_modules/use-sync-external-store": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", @@ -13522,6 +13680,21 @@ "uuid": "dist-node/bin/uuid" } }, + "node_modules/valibot": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.2.0.tgz", + "integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",