@magnolia/mgnl-ds-mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.txt ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2026 Magnolia International Ltd.
2
+ (http://www.magnolia-cms.com). All rights reserved.
3
+
4
+
5
+ The software is dual-licensed under both the Magnolia
6
+ Network Agreement and the GNU General Public License.
7
+ You may elect to use one or the other of these licenses.
8
+
9
+ The software is distributed in the hope that it will be
10
+ useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
11
+ implied warranty of MERCHANTABILITY or FITNESS FOR A
12
+ PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
13
+ Redistribution, except as permitted by whichever of the GPL
14
+ or MNA you select, is prohibited.
15
+
16
+ 1. For the GPL license (GPL), you can redistribute and/or
17
+ modify this file under the terms of the GNU General
18
+ Public License, Version 3, as published by the Free Software
19
+ Foundation. You should have received a copy of the GNU
20
+ General Public License, Version 3 along with this program;
21
+ if not, write to the Free Software Foundation, Inc., 51
22
+ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23
+
24
+ 2. For the Magnolia Network Agreement (MNA), this file
25
+ and the accompanying materials are made available under the
26
+ terms of the MNA which accompanies this distribution, and
27
+ is available at http://www.magnolia-cms.com/mna.html
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # Magnolia DS — Storybook MCP server
2
+
3
+ An [MCP](https://modelcontextprotocol.io/) server that exposes the [Magnolia Design System Storybook](https://ds.magnolia-cloud.com) to AI agents, so they build UI with **real** components, props, and usage instead of guessing. It runs locally via `npx` — your MCP client spawns it over stdio; there’s nothing to host.
4
+
5
+ It reuses the documentation tools from [`@storybook/mcp`](https://www.npmjs.com/package/@storybook/mcp) and points them at **published** manifests (`components.json` / `docs.json`) over HTTPS. So it holds **no state**, needs **no credentials**, and can never drift from what’s live.
6
+
7
+ ## Install
8
+
9
+ Claude Code:
10
+
11
+ ```bash
12
+ claude mcp add magnolia-ds -- npx -y @magnolia/mgnl-ds-mcp-server
13
+ ```
14
+
15
+ Cursor / VS Code / other clients — add to the `mcpServers` config:
16
+
17
+ ```json
18
+ {
19
+ "mcpServers": {
20
+ "magnolia-ds": {
21
+ "command": "npx",
22
+ "args": ["-y", "@magnolia/mgnl-ds-mcp-server"]
23
+ }
24
+ }
25
+ }
26
+ ```
27
+
28
+ That’s it. `npx` fetches the latest published version on each launch, the client manages the process over stdio, and the server reads the live manifests.
29
+
30
+ ## MCP Tools
31
+
32
+ - `list-all-documentation` — list every component and docs entry (IDs + summaries).
33
+ - `get-documentation` — full docs for one component/entry (props, stories, code snippets).
34
+ - `get-documentation-for-story` — docs for a specific story variant.
35
+
36
+ Try it: ask your agent _"using the Magnolia design system, render a loading Button"_.
37
+
38
+ ## Configuration
39
+
40
+ | Setting | env | default |
41
+ | --------------------------- | ---------------- | ----------------------------------------------- |
42
+ | manifests base (URL or dir) | `MANIFESTS_PATH` | `https://ds.magnolia-cloud.com/react/manifests` |
package/bin/mcp.mjs ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+ import { readFile } from 'node:fs/promises';
3
+ import { McpServer } from 'tmcp';
4
+ import { ValibotJsonSchemaAdapter } from '@tmcp/adapter-valibot';
5
+ import { StdioTransport } from '@tmcp/transport-stdio';
6
+ import {
7
+ STORYBOOK_MCP_INSTRUCTIONS,
8
+ addListAllDocumentationTool,
9
+ addGetStoryDocumentationTool,
10
+ addGetDocumentationTool,
11
+ } from '@storybook/mcp';
12
+ import { createManifestProvider } from '../src/manifests.mjs';
13
+
14
+ const manifestsPath =
15
+ process.env.MANIFESTS_PATH ?? 'https://ds.magnolia-cloud.com/react/manifests';
16
+
17
+ const pkg = JSON.parse(
18
+ await readFile(new URL('../package.json', import.meta.url), 'utf8'),
19
+ );
20
+
21
+ // Mirrors @storybook/mcp's createStorybookMcpHandler server construction.
22
+ const server = new McpServer(
23
+ {
24
+ name: 'magnolia-ds',
25
+ version: pkg.version,
26
+ description: 'Magnolia Design System Storybook documentation',
27
+ },
28
+ {
29
+ adapter: new ValibotJsonSchemaAdapter(),
30
+ instructions: STORYBOOK_MCP_INSTRUCTIONS,
31
+ capabilities: { tools: { listChanged: true } },
32
+ },
33
+ ).withContext();
34
+
35
+ await addListAllDocumentationTool(server);
36
+ await addGetStoryDocumentationTool(server);
37
+ await addGetDocumentationTool(server);
38
+
39
+ new StdioTransport(server).listen({
40
+ manifestProvider: createManifestProvider(manifestsPath),
41
+ });
package/package.json ADDED
@@ -0,0 +1,95 @@
1
+ {
2
+ "name": "@magnolia/mgnl-ds-mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "Magnolia Design System Storybook MCP server to be run locally via npx so AI agents build UI with real components.",
5
+ "author": "Magnolia International",
6
+ "license": "See license in LICENSE.txt",
7
+ "private": false,
8
+ "type": "module",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "ssh://git@gitlab.magnolia-platform.com:9022/ds/mgnl-ds-mcp-server.git"
12
+ },
13
+ "bin": {
14
+ "mgnl-ds-mcp-server": "./bin/mcp.mjs"
15
+ },
16
+ "files": [
17
+ "bin",
18
+ "src/manifests.mjs",
19
+ "README.md",
20
+ "LICENSE.txt"
21
+ ],
22
+ "engines": {
23
+ "node": ">=22"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "scripts": {
29
+ "start": "node bin/mcp.mjs",
30
+ "lint": "eslint . && prettier --check .",
31
+ "lint:prettier": "prettier . -w",
32
+ "test": "vitest run",
33
+ "test:integration": "cross-env RUN_INTEGRATION=1 vitest run",
34
+ "release": "semantic-release"
35
+ },
36
+ "release": {
37
+ "branches": [
38
+ "main"
39
+ ],
40
+ "plugins": [
41
+ [
42
+ "@semantic-release/commit-analyzer",
43
+ {
44
+ "preset": "conventionalcommits"
45
+ }
46
+ ],
47
+ [
48
+ "@semantic-release/release-notes-generator",
49
+ {
50
+ "preset": "conventionalcommits"
51
+ }
52
+ ],
53
+ "@semantic-release/changelog",
54
+ [
55
+ "@semantic-release/npm",
56
+ {
57
+ "npmPublish": true
58
+ }
59
+ ],
60
+ [
61
+ "@semantic-release/git",
62
+ {
63
+ "assets": [
64
+ "package.json",
65
+ "CHANGELOG.md"
66
+ ]
67
+ }
68
+ ]
69
+ ],
70
+ "tagFormat": "${version}"
71
+ },
72
+ "dependencies": {
73
+ "@storybook/mcp": "^0.7.0",
74
+ "@tmcp/adapter-valibot": "^0.1.6",
75
+ "@tmcp/transport-stdio": "^0.4.3",
76
+ "tmcp": "^1.19.4"
77
+ },
78
+ "devDependencies": {
79
+ "@eslint/js": "^10.0.1",
80
+ "@semantic-release/changelog": "^6.0.3",
81
+ "@semantic-release/commit-analyzer": "^13.0.1",
82
+ "@semantic-release/git": "^10.0.1",
83
+ "@semantic-release/npm": "^13.1.5",
84
+ "@semantic-release/release-notes-generator": "^14.1.1",
85
+ "conventional-changelog-conventionalcommits": "^9.3.1",
86
+ "cross-env": "^10.1.0",
87
+ "eslint": "^10.6.0",
88
+ "eslint-config-prettier": "^10.1.8",
89
+ "eslint-plugin-prettier": "^5.5.6",
90
+ "globals": "^17.7.0",
91
+ "prettier": "^3.9.4",
92
+ "semantic-release": "^25.0.5",
93
+ "vitest": "^4.1.9"
94
+ }
95
+ }
@@ -0,0 +1,26 @@
1
+ // Manifest provider for the Magnolia DS Storybook MCP server.
2
+ //
3
+ // `@storybook/mcp` is a LIBRARY (no CLI). Its tools read the Storybook manifests (`components.json` / `docs.json`) through a `manifestProvider` we supply via the server context. This builds that provider for two sources, picked from `manifestsPath`:
4
+ // - a remote base URL (e.g. https://ds.magnolia-cloud.com/react/manifests) — the default: it `fetch`es the already-public manifests, so it needs no credentials and can never drift from what's deployed.
5
+ // - a local directory — handy for testing against `storybook-static/manifests`.
6
+ import { readFile } from 'node:fs/promises';
7
+ import { basename, resolve } from 'node:path';
8
+
9
+ export function createManifestProvider(manifestsPath) {
10
+ const base = manifestsPath.replace(/\/+$/, ''); // no trailing slash → no `//file.json`
11
+ const isRemote = base.startsWith('http://') || base.startsWith('https://');
12
+
13
+ return async (_request, path) => {
14
+ const fileName = basename(path);
15
+ if (isRemote) {
16
+ const res = await fetch(`${base}/${fileName}`);
17
+ if (!res.ok) {
18
+ throw new Error(
19
+ `Failed to fetch manifest ${base}/${fileName}: ${res.status} ${res.statusText}`,
20
+ );
21
+ }
22
+ return await res.text();
23
+ }
24
+ return await readFile(resolve(base, fileName), 'utf-8');
25
+ };
26
+ }