@amedia/brick-mcp 0.0.1-LLM-DOCS → 0.0.1-NEW-PATH-1

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.
Files changed (65) hide show
  1. package/README.md +241 -98
  2. package/dist/data/components/brick-actions.json +6 -0
  3. package/dist/data/components/brick-alt-teaser.json +10 -0
  4. package/dist/data/components/brick-avatar.json +11 -0
  5. package/dist/data/components/brick-button.json +12 -0
  6. package/dist/data/components/brick-card.json +10 -0
  7. package/dist/data/components/brick-carousel.json +11 -0
  8. package/dist/data/components/brick-classnames.json +10 -0
  9. package/dist/data/components/brick-countdown.json +7 -0
  10. package/dist/data/components/brick-dialog.json +11 -0
  11. package/dist/data/components/brick-fonts.json +10 -0
  12. package/dist/data/components/brick-helloworld.json +7 -0
  13. package/dist/data/components/brick-icon.json +10 -0
  14. package/dist/data/components/brick-icons.json +11 -0
  15. package/dist/data/components/brick-illustrations.json +7 -0
  16. package/dist/data/components/brick-image.json +10 -0
  17. package/dist/data/components/brick-input.json +12 -0
  18. package/{data → dist/data}/components/brick-mcp.json +1 -1
  19. package/dist/data/components/brick-nifs.json +7 -0
  20. package/{data → dist/data}/components/brick-pill.json +1 -1
  21. package/{data → dist/data}/components/brick-player.json +1 -1
  22. package/dist/data/components/brick-published.json +7 -0
  23. package/{data → dist/data}/components/brick-share.json +1 -1
  24. package/{data → dist/data}/components/brick-stepper.json +1 -1
  25. package/{data → dist/data}/components/brick-tab.json +1 -1
  26. package/{data → dist/data}/components/brick-tabs.json +1 -1
  27. package/{data → dist/data}/components/brick-tag.json +1 -1
  28. package/{data → dist/data}/components/brick-teaser-player.json +1 -1
  29. package/{data → dist/data}/components/brick-teaser-reels.json +1 -1
  30. package/{data → dist/data}/components/brick-teaser.json +1 -1
  31. package/{data → dist/data}/components/brick-textarea.json +1 -1
  32. package/{data → dist/data}/components/brick-toast.json +1 -1
  33. package/{data → dist/data}/components/brick-toggle.json +1 -1
  34. package/{data → dist/data}/components/brick-tokens.json +1 -1
  35. package/{data → dist/data}/components/brick-tooltip.json +1 -1
  36. package/{data → dist/data}/components-metadata.json +29 -29
  37. package/dist/data/components.json +321 -0
  38. package/dist/http.js +311 -0
  39. package/dist/http.js.map +7 -0
  40. package/dist/index.js +52 -81
  41. package/dist/index.js.map +4 -4
  42. package/package.json +3 -6
  43. package/scripts/generate-data.js +37 -40
  44. package/data/components/brick-actions.md +0 -59
  45. package/data/components/brick-alt-teaser.md +0 -253
  46. package/data/components/brick-avatar.md +0 -265
  47. package/data/components/brick-button.md +0 -364
  48. package/data/components/brick-card.md +0 -329
  49. package/data/components/brick-carousel.md +0 -330
  50. package/data/components/brick-classnames.md +0 -150
  51. package/data/components/brick-countdown.md +0 -179
  52. package/data/components/brick-dialog.md +0 -418
  53. package/data/components/brick-fonts.md +0 -335
  54. package/data/components/brick-helloworld.md +0 -202
  55. package/data/components/brick-icon.md +0 -271
  56. package/data/components/brick-icons.md +0 -430
  57. package/data/components/brick-illustrations.md +0 -552
  58. package/data/components/brick-image.md +0 -335
  59. package/data/components/brick-input.md +0 -521
  60. package/data/components/brick-nifs.md +0 -163
  61. package/data/components/brick-published.json +0 -7
  62. package/data/tokens-documentation.json +0 -7
  63. /package/{data → dist/data}/components/brick-template.json +0 -0
  64. /package/{data → dist/data}/components/brick-themes.json +0 -0
  65. /package/{data → dist/data}/tokens.json +0 -0
package/dist/http.js ADDED
@@ -0,0 +1,311 @@
1
+ #!/usr/bin/env node
2
+ // src/http.ts
3
+ import cors from "@fastify/cors";
4
+ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
5
+ import Fastify from "fastify";
6
+
7
+ // src/server.ts
8
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
+ import { z } from "zod";
10
+
11
+ // src/extractors/packageScanner.ts
12
+ import { readFile } from "node:fs/promises";
13
+ import { dirname, join } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+ var __filename = fileURLToPath(import.meta.url);
16
+ var __dirname = dirname(__filename);
17
+ function getDataPath() {
18
+ return join(__dirname, "data");
19
+ }
20
+ async function scanAllPackages() {
21
+ try {
22
+ const metadataPath = join(getDataPath(), "components-metadata.json");
23
+ const content = await readFile(metadataPath, "utf-8");
24
+ const metadata = JSON.parse(content);
25
+ return metadata;
26
+ } catch (error) {
27
+ console.error("Error loading component metadata:", error);
28
+ return [];
29
+ }
30
+ }
31
+ async function loadComponentData(componentName) {
32
+ try {
33
+ const componentPath = join(
34
+ getDataPath(),
35
+ "components",
36
+ `${componentName}.json`
37
+ );
38
+ const content = await readFile(componentPath, "utf-8");
39
+ const component = JSON.parse(content);
40
+ return component;
41
+ } catch (error) {
42
+ console.error(`Error loading component data for ${componentName}:`, error);
43
+ return void 0;
44
+ }
45
+ }
46
+ function filterComponents(components, filter) {
47
+ if (!filter) {
48
+ return components;
49
+ }
50
+ const filterLower = filter.toLowerCase();
51
+ return components.filter((component) => {
52
+ if (component.name.toLowerCase().includes(filterLower)) {
53
+ return true;
54
+ }
55
+ if (component.category?.toLowerCase().includes(filterLower)) {
56
+ return true;
57
+ }
58
+ if (component.tags?.some((tag) => tag.toLowerCase().includes(filterLower))) {
59
+ return true;
60
+ }
61
+ return false;
62
+ });
63
+ }
64
+
65
+ // src/tools/getComponentDocs.ts
66
+ function getStorybookLink(componentName) {
67
+ return `https://master--60060c41f82e040021133482.chromatic.com/?path=/docs/bricks-${componentName}`;
68
+ }
69
+ function extractExamples(component) {
70
+ const examples = {
71
+ webComponent: `<${component.selector}></${component.selector}>`,
72
+ storybook: getStorybookLink(component.name)
73
+ };
74
+ if (component.mdx) {
75
+ const codeBlockRegex = /```(?:html|javascript|typescript)\n([\s\S]*?)```/;
76
+ const match = component.mdx.match(codeBlockRegex);
77
+ if (match) {
78
+ examples.webComponent = match[1].trim();
79
+ }
80
+ }
81
+ return examples;
82
+ }
83
+ async function getComponentDoc(component) {
84
+ const examples = extractExamples(component);
85
+ return {
86
+ name: component.name,
87
+ version: component.version,
88
+ selector: component.selector,
89
+ description: component.llm || component.mdx,
90
+ examples,
91
+ cdnPath: `https://assets.acdn.no/pkg/@amedia/${component.name}/${component.version}/${component.name}.js`
92
+ };
93
+ }
94
+ async function getComponentDocs(input) {
95
+ const componentDataPromises = input.components.map(
96
+ (componentName) => loadComponentData(componentName)
97
+ );
98
+ const componentsData = await Promise.all(componentDataPromises);
99
+ const validComponents = componentsData.filter(
100
+ (comp) => comp !== void 0
101
+ );
102
+ const docs = await Promise.all(
103
+ validComponents.map((comp) => getComponentDoc(comp))
104
+ );
105
+ return { docs };
106
+ }
107
+
108
+ // src/tools/getDesignTokens.ts
109
+ import { readFile as readFile2 } from "node:fs/promises";
110
+ import { dirname as dirname2, join as join2 } from "node:path";
111
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
112
+ var __filename2 = fileURLToPath2(import.meta.url);
113
+ var __dirname2 = dirname2(__filename2);
114
+ function getTokensDataPath() {
115
+ const dataPath = join2(__dirname2, "..", "data", "tokens.json");
116
+ return dataPath;
117
+ }
118
+ async function loadAllTokens() {
119
+ try {
120
+ const dataPath = getTokensDataPath();
121
+ const content = await readFile2(dataPath, "utf-8");
122
+ return JSON.parse(content);
123
+ } catch (error) {
124
+ console.error("Error loading tokens data:", error);
125
+ return [];
126
+ }
127
+ }
128
+ async function getDesignTokens(input) {
129
+ const allTokens = await loadAllTokens();
130
+ let filteredTokens = allTokens;
131
+ if (input.theme) {
132
+ filteredTokens = filteredTokens.filter(
133
+ (token) => token.theme === input.theme
134
+ );
135
+ }
136
+ if (input.category) {
137
+ filteredTokens = filteredTokens.filter((token) => {
138
+ if (input.category === "colors" && token.type === "color") {
139
+ return true;
140
+ }
141
+ if (input.category === "spacing" && (token.type === "spacing" || token.name.includes("spacing"))) {
142
+ return true;
143
+ }
144
+ if (input.category === "typography" && (token.type === "fontFamily" || token.type === "fontSize" || token.type === "fontWeight" || token.name.includes("font"))) {
145
+ return true;
146
+ }
147
+ if (input.category === "shadows" && (token.type === "boxShadow" || token.name.includes("shadow"))) {
148
+ return true;
149
+ }
150
+ if (input.category === "borders" && (token.type === "borderRadius" || token.type === "borderWidth" || token.name.includes("border"))) {
151
+ return true;
152
+ }
153
+ return false;
154
+ });
155
+ }
156
+ return { tokens: filteredTokens };
157
+ }
158
+
159
+ // src/tools/listComponents.ts
160
+ async function listComponents(input) {
161
+ const allComponents = await scanAllPackages();
162
+ const components = filterComponents(allComponents, input.filter);
163
+ return {
164
+ components
165
+ };
166
+ }
167
+
168
+ // src/server.ts
169
+ function createServer() {
170
+ const server = new McpServer({
171
+ name: "brick-design-system",
172
+ version: "1.0.0"
173
+ });
174
+ server.registerTool(
175
+ "list-components",
176
+ {
177
+ title: "List Brick Components",
178
+ description: "List all available Brick components with metadata. Optionally filter by category, tag, or name.",
179
+ inputSchema: {
180
+ filter: z.string().optional().describe("Optional filter by category, tag, or name")
181
+ }
182
+ },
183
+ async ({ filter }) => {
184
+ const result = await listComponents({ filter });
185
+ return {
186
+ content: [
187
+ {
188
+ type: "text",
189
+ text: JSON.stringify(result, null, 2)
190
+ }
191
+ ]
192
+ };
193
+ }
194
+ );
195
+ server.registerTool(
196
+ "get-component-docs",
197
+ {
198
+ title: "Get Component Documentation",
199
+ description: "Retrieve detailed documentation for specific Brick component(s) including props, events, examples, and accessibility information.",
200
+ inputSchema: {
201
+ components: z.array(z.string()).describe(
202
+ 'Array of component names (e.g., ["brick-button", "brick-modal"])'
203
+ )
204
+ }
205
+ },
206
+ async ({ components }) => {
207
+ const result = await getComponentDocs({ components });
208
+ return {
209
+ content: [
210
+ {
211
+ type: "text",
212
+ text: JSON.stringify(result, null, 2)
213
+ }
214
+ ]
215
+ };
216
+ }
217
+ );
218
+ server.registerTool(
219
+ "get-design-tokens",
220
+ {
221
+ title: "Get Design Tokens",
222
+ description: "Access design tokens from brick-tokens. Optionally filter by category (colors, spacing, typography, shadows, borders) or theme.",
223
+ inputSchema: {
224
+ category: z.enum(["colors", "spacing", "typography", "shadows", "borders"]).optional().describe("Filter tokens by category"),
225
+ theme: z.string().optional().describe('Filter tokens by theme (e.g., "bergen", "alfa")')
226
+ }
227
+ },
228
+ async ({ category, theme }) => {
229
+ const result = await getDesignTokens({ category, theme });
230
+ return {
231
+ content: [
232
+ {
233
+ type: "text",
234
+ text: JSON.stringify(result, null, 2)
235
+ }
236
+ ]
237
+ };
238
+ }
239
+ );
240
+ return server;
241
+ }
242
+
243
+ // src/http.ts
244
+ var PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : 3e3;
245
+ var HOST = process.env.HOST || "0.0.0.0";
246
+ var fastify = Fastify({
247
+ logger: true
248
+ });
249
+ var activeTransports = /* @__PURE__ */ new Map();
250
+ var activeMcpServers = /* @__PURE__ */ new Map();
251
+ var isProduction = process.env.NODE_ENV === "production";
252
+ var allowedOrigin = process.env.CORS_ORIGIN;
253
+ var corsOptions;
254
+ if (isProduction) {
255
+ if (!allowedOrigin) {
256
+ console.warn(
257
+ "[SECURITY WARNING] CORS_ORIGIN is not set in production. Refusing to start with insecure CORS configuration."
258
+ );
259
+ process.exit(1);
260
+ }
261
+ corsOptions = {
262
+ origin: allowedOrigin,
263
+ credentials: true
264
+ };
265
+ } else {
266
+ corsOptions = {
267
+ origin: true,
268
+ credentials: true
269
+ };
270
+ }
271
+ await fastify.register(cors, corsOptions);
272
+ fastify.get("/health", async () => {
273
+ return { status: "ok" };
274
+ });
275
+ fastify.get("/sse", async (_request, reply) => {
276
+ reply.hijack();
277
+ const mcpServer = createServer();
278
+ const transport = new SSEServerTransport("/message", reply.raw);
279
+ await mcpServer.connect(transport);
280
+ const sessionId = transport.sessionId;
281
+ activeTransports.set(sessionId, transport);
282
+ activeMcpServers.set(sessionId, mcpServer);
283
+ reply.raw.on("close", async () => {
284
+ activeTransports.delete(sessionId);
285
+ const server = activeMcpServers.get(sessionId);
286
+ if (server) {
287
+ await server.close();
288
+ activeMcpServers.delete(sessionId);
289
+ }
290
+ });
291
+ });
292
+ fastify.post("/message", async (request, reply) => {
293
+ reply.hijack();
294
+ const { sessionId } = request.query;
295
+ const transport = activeTransports.get(sessionId);
296
+ if (!transport) {
297
+ reply.raw.writeHead(404, { "Content-Type": "application/json" });
298
+ reply.raw.end(JSON.stringify({ error: "Session not found" }));
299
+ return;
300
+ }
301
+ await transport.handlePostMessage(request.raw, reply.raw, request.body);
302
+ });
303
+ try {
304
+ await fastify.listen({ port: PORT, host: HOST });
305
+ console.log(`Brick MCP HTTP server listening on http://${HOST}:${PORT}`);
306
+ console.log(`SSE endpoint: http://${HOST}:${PORT}/sse`);
307
+ } catch (err) {
308
+ fastify.log.error(err);
309
+ process.exit(1);
310
+ }
311
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/http.ts", "../src/server.ts", "../src/extractors/packageScanner.ts", "../src/tools/getComponentDocs.ts", "../src/tools/getDesignTokens.ts", "../src/tools/listComponents.ts"],
4
+ "sourcesContent": ["/**\n * HTTP server entry point using Fastify and SSE transport\n */\n\nimport cors from '@fastify/cors';\nimport { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';\nimport Fastify from 'fastify';\n\nimport { createServer } from './server.ts';\n\nconst PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : 3000;\nconst HOST = process.env.HOST || '0.0.0.0';\n\nconst fastify = Fastify({\n logger: true,\n});\n\n// Store active transports and servers by sessionId\nconst activeTransports = new Map<string, SSEServerTransport>();\nconst activeMcpServers = new Map<string, ReturnType<typeof createServer>>();\n\n// Enable CORS with environment-based origin restriction\nconst isProduction = process.env.NODE_ENV === 'production';\nconst allowedOrigin = process.env.CORS_ORIGIN;\n\nlet corsOptions;\nif (isProduction) {\n if (!allowedOrigin) {\n console.warn(\n '[SECURITY WARNING] CORS_ORIGIN is not set in production. Refusing to start with insecure CORS configuration.'\n );\n process.exit(1);\n }\n corsOptions = {\n origin: allowedOrigin,\n credentials: true,\n };\n} else {\n corsOptions = {\n origin: true,\n credentials: true,\n };\n}\n\nawait fastify.register(cors, corsOptions);\n\n// Health check endpoint\nfastify.get('/health', async () => {\n return { status: 'ok' };\n});\n\n// SSE endpoint for MCP communication\nfastify.get('/sse', async (_request, reply) => {\n // Prevent Fastify from automatically sending a response\n reply.hijack();\n\n // Create a new MCP server instance for this connection\n const mcpServer = createServer();\n\n // Create SSE transport (this will handle headers internally)\n const transport = new SSEServerTransport('/message', reply.raw);\n\n // Handle the SSE connection (this calls transport.start() which writes headers)\n await mcpServer.connect(transport);\n\n // Store the transport and server by sessionId for POST message handling\n // The sessionId is available after the transport starts via the public getter\n const sessionId = transport.sessionId;\n activeTransports.set(sessionId, transport);\n activeMcpServers.set(sessionId, mcpServer);\n\n // Clean up when the connection closes\n reply.raw.on('close', async () => {\n activeTransports.delete(sessionId);\n const server = activeMcpServers.get(sessionId);\n if (server) {\n await server.close();\n activeMcpServers.delete(sessionId);\n }\n });\n});\n\n// POST endpoint for messages\nfastify.post<{\n Querystring: { sessionId: string };\n}>('/message', async (request, reply) => {\n // Prevent Fastify from automatically sending a response\n reply.hijack();\n\n // Extract sessionId from query parameters (now properly typed)\n const { sessionId } = request.query;\n\n // Find the transport for this session\n const transport = activeTransports.get(sessionId);\n\n if (!transport) {\n reply.raw.writeHead(404, { 'Content-Type': 'application/json' });\n reply.raw.end(JSON.stringify({ error: 'Session not found' }));\n return;\n }\n\n // Let the transport handle the POST message\n await transport.handlePostMessage(request.raw, reply.raw, request.body);\n});\n\n// Start the server\ntry {\n await fastify.listen({ port: PORT, host: HOST });\n console.log(`Brick MCP HTTP server listening on http://${HOST}:${PORT}`);\n console.log(`SSE endpoint: http://${HOST}:${PORT}/sse`);\n} catch (err) {\n fastify.log.error(err);\n process.exit(1);\n}\n", "/**\n * MCP server setup and registration\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\nimport { getComponentDocs } from './tools/getComponentDocs.ts';\nimport { getDesignTokens } from './tools/getDesignTokens.ts';\nimport { listComponents } from './tools/listComponents.ts';\n\n/**\n * Create and configure the MCP server\n */\nexport function createServer(): McpServer {\n // Create an MCP server\n const server = new McpServer({\n name: 'brick-design-system',\n version: '1.0.0',\n });\n\n // Register list-components tool\n server.registerTool(\n 'list-components',\n {\n title: 'List Brick Components',\n description:\n 'List all available Brick components with metadata. Optionally filter by category, tag, or name.',\n inputSchema: {\n filter: z\n .string()\n .optional()\n .describe('Optional filter by category, tag, or name'),\n },\n },\n async ({ filter }) => {\n const result = await listComponents({ filter });\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n );\n\n // Register get-component-docs tool\n server.registerTool(\n 'get-component-docs',\n {\n title: 'Get Component Documentation',\n description:\n 'Retrieve detailed documentation for specific Brick component(s) including props, events, examples, and accessibility information.',\n inputSchema: {\n components: z\n .array(z.string())\n .describe(\n 'Array of component names (e.g., [\"brick-button\", \"brick-modal\"])'\n ),\n },\n },\n async ({ components }) => {\n const result = await getComponentDocs({ components });\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n );\n\n // Register get-design-tokens tool\n server.registerTool(\n 'get-design-tokens',\n {\n title: 'Get Design Tokens',\n description:\n 'Access design tokens from brick-tokens. Optionally filter by category (colors, spacing, typography, shadows, borders) or theme.',\n inputSchema: {\n category: z\n .enum(['colors', 'spacing', 'typography', 'shadows', 'borders'])\n .optional()\n .describe('Filter tokens by category'),\n theme: z\n .string()\n .optional()\n .describe('Filter tokens by theme (e.g., \"bergen\", \"alfa\")'),\n },\n },\n async ({ category, theme }) => {\n const result = await getDesignTokens({ category, theme });\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n );\n\n return server;\n}\n", "/**\n * Package scanner for discovering Brick components\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { type BrickComponent, type BrickComponentMetadata } from '../types.ts';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Get the path to the bundled components data directory\n */\nfunction getDataPath(): string {\n // When bundled by esbuild, __dirname will be 'dist'\n // So we look for 'data' adjacent to __dirname (dist/data)\n return join(__dirname, 'data');\n}\n\n/**\n * Load all component metadata (lightweight, for listing)\n */\nexport async function scanAllPackages(): Promise<BrickComponentMetadata[]> {\n try {\n const metadataPath = join(getDataPath(), 'components-metadata.json');\n const content = await readFile(metadataPath, 'utf-8');\n const metadata: BrickComponentMetadata[] = JSON.parse(content);\n return metadata;\n } catch (error) {\n console.error('Error loading component metadata:', error);\n return [];\n }\n}\n\n/**\n * Load full component data for a specific component\n */\nexport async function loadComponentData(\n componentName: string\n): Promise<BrickComponent | undefined> {\n try {\n const componentPath = join(\n getDataPath(),\n 'components',\n `${componentName}.json`\n );\n const content = await readFile(componentPath, 'utf-8');\n const component: BrickComponent = JSON.parse(content);\n return component;\n } catch (error) {\n console.error(`Error loading component data for ${componentName}:`, error);\n return undefined;\n }\n}\n\n/**\n * Filter components by category or tag\n */\nexport function filterComponents(\n components: BrickComponentMetadata[],\n filter?: string\n): BrickComponentMetadata[] {\n if (!filter) {\n return components;\n }\n\n const filterLower = filter.toLowerCase();\n\n return components.filter((component) => {\n // Match against name\n if (component.name.toLowerCase().includes(filterLower)) {\n return true;\n }\n\n // Match against category\n if (component.category?.toLowerCase().includes(filterLower)) {\n return true;\n }\n\n // Match against tags\n if (\n component.tags?.some((tag) => tag.toLowerCase().includes(filterLower))\n ) {\n return true;\n }\n\n return false;\n });\n}\n", "/**\n * Get Component Docs tool implementation\n */\n\nimport { loadComponentData } from '../extractors/packageScanner.ts';\nimport type { BrickComponent, ComponentDocs } from '../types.ts';\n\nexport interface GetComponentDocsInput {\n components: string[]; // e.g., [\"brick-button\", \"brick-modal\"]\n}\n\nexport interface GetComponentDocsOutput {\n docs: ComponentDocs[];\n}\n\n/**\n * Extract Storybook link from package\n */\nfunction getStorybookLink(componentName: string): string {\n return `https://master--60060c41f82e040021133482.chromatic.com/?path=/docs/bricks-${componentName}`;\n}\n\n/**\n * Extract examples from component data\n */\nfunction extractExamples(component: BrickComponent) {\n const examples: ComponentDocs['examples'] = {\n webComponent: `<${component.selector}></${component.selector}>`,\n storybook: getStorybookLink(component.name),\n };\n\n if (component.mdx) {\n // Try to extract code examples from MDX\n const codeBlockRegex = /```(?:html|javascript|typescript)\\n([\\s\\S]*?)```/;\n const match = component.mdx.match(codeBlockRegex);\n if (match) {\n examples.webComponent = match[1].trim();\n }\n }\n\n return examples;\n}\n\n/**\n * Get documentation for a single component\n */\nasync function getComponentDoc(\n component: BrickComponent\n): Promise<ComponentDocs> {\n const examples = extractExamples(component);\n\n return {\n name: component.name,\n version: component.version,\n selector: component.selector,\n description: component.llm || component.mdx,\n examples,\n cdnPath: `https://assets.acdn.no/pkg/@amedia/${component.name}/${component.version}/${component.name}.js`,\n };\n}\n\n/**\n * Get detailed documentation for specific component(s)\n */\nexport async function getComponentDocs(\n input: GetComponentDocsInput\n): Promise<GetComponentDocsOutput> {\n // Load full component data for each requested component\n const componentDataPromises = input.components.map((componentName) =>\n loadComponentData(componentName)\n );\n\n const componentsData = await Promise.all(componentDataPromises);\n\n // Filter out any components that failed to load\n const validComponents = componentsData.filter(\n (comp): comp is BrickComponent => comp !== undefined\n );\n\n // Get documentation for each component\n const docs = await Promise.all(\n validComponents.map((comp) => getComponentDoc(comp))\n );\n\n return { docs };\n}\n", "/**\n * Get Design Tokens tool implementation\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface DesignToken {\n name: string;\n value: string;\n type: string;\n description?: string;\n category?: string;\n theme?: string;\n}\n\nexport interface GetDesignTokensInput {\n category?: 'colors' | 'spacing' | 'typography' | 'shadows' | 'borders';\n theme?: string;\n}\n\nexport interface GetDesignTokensOutput {\n tokens: DesignToken[];\n}\n\n/**\n * Get the path to the bundled tokens data\n */\nfunction getTokensDataPath(): string {\n // In production (dist), data is in ../data/tokens.json\n // In development (src), data is in ../../data/tokens.json\n const dataPath = join(__dirname, '..', 'data', 'tokens.json');\n return dataPath;\n}\n\n/**\n * Load all tokens from bundled JSON data\n */\nasync function loadAllTokens(): Promise<DesignToken[]> {\n try {\n const dataPath = getTokensDataPath();\n const content = await readFile(dataPath, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n console.error('Error loading tokens data:', error);\n return [];\n }\n}\n\n/**\n * Get design tokens with optional filtering\n */\nexport async function getDesignTokens(\n input: GetDesignTokensInput\n): Promise<GetDesignTokensOutput> {\n const allTokens = await loadAllTokens();\n\n let filteredTokens = allTokens;\n\n // Filter by theme if specified\n if (input.theme) {\n filteredTokens = filteredTokens.filter(\n (token) => token.theme === input.theme\n );\n }\n\n // Filter by category if specified\n if (input.category) {\n filteredTokens = filteredTokens.filter((token) => {\n // Filter based on type or name pattern\n if (input.category === 'colors' && token.type === 'color') {\n return true;\n }\n if (\n input.category === 'spacing' &&\n (token.type === 'spacing' || token.name.includes('spacing'))\n ) {\n return true;\n }\n if (\n input.category === 'typography' &&\n (token.type === 'fontFamily' ||\n token.type === 'fontSize' ||\n token.type === 'fontWeight' ||\n token.name.includes('font'))\n ) {\n return true;\n }\n if (\n input.category === 'shadows' &&\n (token.type === 'boxShadow' || token.name.includes('shadow'))\n ) {\n return true;\n }\n if (\n input.category === 'borders' &&\n (token.type === 'borderRadius' ||\n token.type === 'borderWidth' ||\n token.name.includes('border'))\n ) {\n return true;\n }\n return false;\n });\n }\n\n return { tokens: filteredTokens };\n}\n", "/**\n * List Components tool implementation\n */\n\nimport {\n filterComponents,\n scanAllPackages,\n} from '../extractors/packageScanner.ts';\nimport type { BrickComponentMetadata } from '../types.ts';\n\nexport interface ListComponentsInput {\n filter?: string;\n}\n\nexport interface ListComponentsOutput {\n components: BrickComponentMetadata[];\n}\n\n/**\n * List all available Brick components with optional filtering\n */\nexport async function listComponents(\n input: ListComponentsInput\n): Promise<ListComponentsOutput> {\n // Scan all packages in the monorepo (returns lightweight metadata)\n const allComponents = await scanAllPackages();\n\n // Apply filter if provided\n const components = filterComponents(allComponents, input.filter);\n\n return {\n components,\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["readFile", "dirname", "join", "fileURLToPath", "__filename", "__dirname"]
7
+ }
package/dist/index.js CHANGED
@@ -6,37 +6,18 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
6
6
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
7
  import { z } from "zod";
8
8
 
9
- // src/tools/getComponentDocs.ts
10
- import { readFile as readFile2 } from "node:fs/promises";
11
- import { join as join3 } from "node:path";
12
-
13
- // src/utils/dataPath.ts
14
- import { accessSync } from "node:fs";
9
+ // src/extractors/packageScanner.ts
10
+ import { readFile } from "node:fs/promises";
15
11
  import { dirname, join } from "node:path";
16
12
  import { fileURLToPath } from "node:url";
13
+ var __filename = fileURLToPath(import.meta.url);
14
+ var __dirname = dirname(__filename);
17
15
  function getDataPath() {
18
- const currentFilePath = fileURLToPath(import.meta.url);
19
- let dir = dirname(currentFilePath);
20
- for (let i = 0; i < 5; i++) {
21
- try {
22
- const testPath = join(dir, "package.json");
23
- accessSync(testPath);
24
- return join(dir, "data");
25
- } catch {
26
- const parent = dirname(dir);
27
- if (parent === dir) break;
28
- dir = parent;
29
- }
30
- }
31
- return join(dirname(currentFilePath), "..", "..", "data");
16
+ return join(__dirname, "data");
32
17
  }
33
-
34
- // src/extractors/packageScanner.ts
35
- import { readFile } from "node:fs/promises";
36
- import { join as join2 } from "node:path";
37
18
  async function scanAllPackages() {
38
19
  try {
39
- const metadataPath = join2(getDataPath(), "components-metadata.json");
20
+ const metadataPath = join(getDataPath(), "components-metadata.json");
40
21
  const content = await readFile(metadataPath, "utf-8");
41
22
  const metadata = JSON.parse(content);
42
23
  return metadata;
@@ -47,7 +28,7 @@ async function scanAllPackages() {
47
28
  }
48
29
  async function loadComponentData(componentName) {
49
30
  try {
50
- const componentPath = join2(
31
+ const componentPath = join(
51
32
  getDataPath(),
52
33
  "components",
53
34
  `${componentName}.json`
@@ -80,75 +61,70 @@ function filterComponents(components, filter) {
80
61
  }
81
62
 
82
63
  // src/tools/getComponentDocs.ts
83
- async function loadComponentMarkdown(componentName) {
84
- try {
85
- const markdownPath = join3(
86
- getDataPath(),
87
- "components",
88
- `${componentName}.md`
89
- );
90
- const content = await readFile2(markdownPath, "utf-8");
91
- return content;
92
- } catch (error) {
93
- console.error(`Error loading markdown for ${componentName}:`, error);
94
- return void 0;
64
+ function getStorybookLink(componentName) {
65
+ return `https://master--60060c41f82e040021133482.chromatic.com/?path=/docs/bricks-${componentName}`;
66
+ }
67
+ function extractExamples(component) {
68
+ const examples = {
69
+ webComponent: `<${component.selector}></${component.selector}>`,
70
+ storybook: getStorybookLink(component.name)
71
+ };
72
+ if (component.mdx) {
73
+ const codeBlockRegex = /```(?:html|javascript|typescript)\n([\s\S]*?)```/;
74
+ const match = component.mdx.match(codeBlockRegex);
75
+ if (match) {
76
+ examples.webComponent = match[1].trim();
77
+ }
95
78
  }
79
+ return examples;
80
+ }
81
+ async function getComponentDoc(component) {
82
+ const examples = extractExamples(component);
83
+ return {
84
+ name: component.name,
85
+ version: component.version,
86
+ selector: component.selector,
87
+ description: component.llm || component.mdx,
88
+ examples,
89
+ cdnPath: `https://assets.acdn.no/pkg/@amedia/${component.name}/${component.version}/${component.name}.js`
90
+ };
96
91
  }
97
92
  async function getComponentDocs(input) {
98
- const docsPromises = input.components.map((componentName) => {
99
- const md = loadComponentMarkdown(componentName);
100
- if (!md) {
101
- const json = loadComponentData(componentName);
102
- return json ? JSON.stringify(json) : void 0;
103
- }
104
- return md;
105
- });
106
- const docsResults = await Promise.all(docsPromises);
107
- const docs = docsResults.filter((doc) => doc !== void 0);
93
+ const componentDataPromises = input.components.map(
94
+ (componentName) => loadComponentData(componentName)
95
+ );
96
+ const componentsData = await Promise.all(componentDataPromises);
97
+ const validComponents = componentsData.filter(
98
+ (comp) => comp !== void 0
99
+ );
100
+ const docs = await Promise.all(
101
+ validComponents.map((comp) => getComponentDoc(comp))
102
+ );
108
103
  return { docs };
109
104
  }
110
105
 
111
106
  // src/tools/getDesignTokens.ts
112
- import { readFile as readFile3 } from "node:fs/promises";
113
- import { join as join4 } from "node:path";
107
+ import { readFile as readFile2 } from "node:fs/promises";
108
+ import { dirname as dirname2, join as join2 } from "node:path";
109
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
110
+ var __filename2 = fileURLToPath2(import.meta.url);
111
+ var __dirname2 = dirname2(__filename2);
114
112
  function getTokensDataPath() {
115
- return join4(getDataPath(), "tokens.json");
116
- }
117
- function getDocumentationDataPath() {
118
- return join4(getDataPath(), "tokens-documentation.json");
113
+ const dataPath = join2(__dirname2, "..", "data", "tokens.json");
114
+ return dataPath;
119
115
  }
120
116
  async function loadAllTokens() {
121
117
  try {
122
118
  const dataPath = getTokensDataPath();
123
- const content = await readFile3(dataPath, "utf-8");
119
+ const content = await readFile2(dataPath, "utf-8");
124
120
  return JSON.parse(content);
125
121
  } catch (error) {
126
122
  console.error("Error loading tokens data:", error);
127
123
  return [];
128
124
  }
129
125
  }
130
- async function loadDocumentation() {
131
- try {
132
- const dataPath = getDocumentationDataPath();
133
- const content = await readFile3(dataPath, "utf-8");
134
- return JSON.parse(content);
135
- } catch (error) {
136
- console.error("Error loading documentation data:", error);
137
- return {};
138
- }
139
- }
140
- function getAvailableThemes(tokens) {
141
- const themes = /* @__PURE__ */ new Set();
142
- for (const token of tokens) {
143
- if (token.theme) {
144
- themes.add(token.theme);
145
- }
146
- }
147
- return Array.from(themes).sort();
148
- }
149
126
  async function getDesignTokens(input) {
150
127
  const allTokens = await loadAllTokens();
151
- const documentation = await loadDocumentation();
152
128
  let filteredTokens = allTokens;
153
129
  if (input.theme) {
154
130
  filteredTokens = filteredTokens.filter(
@@ -175,12 +151,7 @@ async function getDesignTokens(input) {
175
151
  return false;
176
152
  });
177
153
  }
178
- const themes = getAvailableThemes(allTokens);
179
- return {
180
- tokens: filteredTokens,
181
- themes,
182
- documentation
183
- };
154
+ return { tokens: filteredTokens };
184
155
  }
185
156
 
186
157
  // src/tools/listComponents.ts
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.ts", "../src/server.ts", "../src/tools/getComponentDocs.ts", "../src/utils/dataPath.ts", "../src/extractors/packageScanner.ts", "../src/tools/getDesignTokens.ts", "../src/tools/listComponents.ts"],
4
- "sourcesContent": ["/**\n * Main MCP server entry point\n */\n\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\n\nimport { createServer } from './server.ts';\n\n// Create and start the server\nconst server = createServer();\n\n// Start receiving messages on stdin and sending messages on stdout\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n", "/**\n * MCP server setup and registration\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\nimport { getComponentDocs } from './tools/getComponentDocs.ts';\nimport { getDesignTokens } from './tools/getDesignTokens.ts';\nimport { listComponents } from './tools/listComponents.ts';\n\n/**\n * Create and configure the MCP server\n */\nexport function createServer(): McpServer {\n // Create an MCP server\n const server = new McpServer({\n name: 'brick-design-system',\n version: '1.0.0',\n });\n\n // Register list-components tool\n server.registerTool(\n 'list-components',\n {\n title: 'List Brick Components',\n description:\n 'List all available Brick components with metadata. Optionally filter by category, tag, or name.',\n inputSchema: {\n filter: z\n .string()\n .optional()\n .describe('Optional filter by category, tag, or name'),\n },\n },\n async ({ filter }) => {\n const result = await listComponents({ filter });\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n );\n\n // Register get-component-docs tool\n server.registerTool(\n 'get-component-docs',\n {\n title: 'Get Component Documentation',\n description:\n 'Retrieve detailed documentation for specific Brick component(s) including props, events, examples, and accessibility information.',\n inputSchema: {\n components: z\n .array(z.string())\n .describe(\n 'Array of component names (e.g., [\"brick-button\", \"brick-modal\"])'\n ),\n },\n },\n async ({ components }) => {\n const result = await getComponentDocs({ components });\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n );\n\n // Register get-design-tokens tool\n server.registerTool(\n 'get-design-tokens',\n {\n title: 'Get Design Tokens',\n description:\n 'Access design tokens from brick-tokens. Optionally filter by category (colors, spacing, typography, shadows, borders) or theme.',\n inputSchema: {\n category: z\n .enum(['colors', 'spacing', 'typography', 'shadows', 'borders'])\n .optional()\n .describe('Filter tokens by category'),\n theme: z\n .string()\n .optional()\n .describe('Filter tokens by theme (e.g., \"bergen\", \"alfa\")'),\n },\n },\n async ({ category, theme }) => {\n const result = await getDesignTokens({ category, theme });\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n );\n\n return server;\n}\n", "/**\n * Get Component Docs tool implementation\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport { getDataPath } from '../utils/dataPath.ts';\nimport { loadComponentData } from '../extractors/packageScanner.ts';\n\nexport interface GetComponentDocsInput {\n components: string[]; // e.g., [\"brick-button\", \"brick-modal\"]\n}\n\nexport interface GetComponentDocsOutput {\n docs: string[];\n}\n\n/**\n * Load markdown documentation for a component\n */\nasync function loadComponentMarkdown(\n componentName: string\n): Promise<string | undefined> {\n try {\n const markdownPath = join(\n getDataPath(),\n 'components',\n `${componentName}.md`\n );\n const content = await readFile(markdownPath, 'utf-8');\n return content;\n } catch (error) {\n console.error(`Error loading markdown for ${componentName}:`, error);\n return undefined;\n }\n}\n\n/**\n * Get detailed documentation for specific component(s)\n */\nexport async function getComponentDocs(\n input: GetComponentDocsInput\n): Promise<GetComponentDocsOutput> {\n // Load markdown documentation for each requested component\n const docsPromises = input.components.map((componentName) => {\n const md = loadComponentMarkdown(componentName);\n if (!md) {\n const json = loadComponentData(componentName);\n return json ? JSON.stringify(json) : undefined;\n }\n return md;\n });\n\n const docsResults = await Promise.all(docsPromises);\n\n // Filter out any components that failed to load\n const docs = docsResults.filter((doc): doc is string => doc !== undefined);\n\n return { docs };\n}\n", "/**\n * Utility for finding the data directory path\n * Works both in development (from src/) and production (from dist/)\n */\n\nimport { accessSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Get the path to the data directory at package root\n * Walks up the directory tree to find package.json, then returns the data directory\n */\nexport function getDataPath(): string {\n const currentFilePath = fileURLToPath(import.meta.url);\n let dir = dirname(currentFilePath);\n\n // Walk up the directory tree to find package root (where package.json exists)\n for (let i = 0; i < 5; i++) {\n try {\n const testPath = join(dir, 'package.json');\n accessSync(testPath);\n return join(dir, 'data');\n } catch {\n // Go up one level\n const parent = dirname(dir);\n if (parent === dir) break; // Reached filesystem root\n dir = parent;\n }\n }\n\n return join(dirname(currentFilePath), '..', '..', 'data');\n}\n", "/**\n * Package scanner for discovering Brick components\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport { type BrickComponent, type BrickComponentMetadata } from '../types.ts';\nimport { getDataPath } from '../utils/dataPath.ts';\n\n/**\n * Load all component metadata (lightweight, for listing)\n */\nexport async function scanAllPackages(): Promise<BrickComponentMetadata[]> {\n try {\n const metadataPath = join(getDataPath(), 'components-metadata.json');\n const content = await readFile(metadataPath, 'utf-8');\n const metadata: BrickComponentMetadata[] = JSON.parse(content);\n return metadata;\n } catch (error) {\n console.error('Error loading component metadata:', error);\n return [];\n }\n}\n\n/**\n * Load full component data for a specific component\n */\nexport async function loadComponentData(\n componentName: string\n): Promise<BrickComponent | undefined> {\n try {\n const componentPath = join(\n getDataPath(),\n 'components',\n `${componentName}.json`\n );\n const content = await readFile(componentPath, 'utf-8');\n const component: BrickComponent = JSON.parse(content);\n return component;\n } catch (error) {\n console.error(`Error loading component data for ${componentName}:`, error);\n return undefined;\n }\n}\n\n/**\n * Filter components by category or tag\n */\nexport function filterComponents(\n components: BrickComponentMetadata[],\n filter?: string\n): BrickComponentMetadata[] {\n if (!filter) {\n return components;\n }\n\n const filterLower = filter.toLowerCase();\n\n return components.filter((component) => {\n // Match against name\n if (component.name.toLowerCase().includes(filterLower)) {\n return true;\n }\n\n // Match against category\n if (component.category?.toLowerCase().includes(filterLower)) {\n return true;\n }\n\n // Match against tags\n if (\n component.tags?.some((tag) => tag.toLowerCase().includes(filterLower))\n ) {\n return true;\n }\n\n return false;\n });\n}\n", "/**\n * Get Design Tokens tool implementation\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport { getDataPath } from '../utils/dataPath.ts';\n\nexport interface DesignToken {\n name: string;\n value: string;\n type: string;\n description?: string;\n category?: string;\n theme?: string;\n}\n\nexport interface GetDesignTokensInput {\n category?: 'colors' | 'spacing' | 'typography' | 'shadows' | 'borders';\n theme?: string;\n}\n\nexport interface TokensDocumentation {\n anOverview?: string;\n formats?: string;\n naming?: string;\n themes?: string;\n usage?: string;\n}\n\nexport interface GetDesignTokensOutput {\n tokens: DesignToken[];\n themes: string[];\n documentation: TokensDocumentation;\n}\n\n/**\n * Get the path to the bundled tokens data\n */\nfunction getTokensDataPath(): string {\n return join(getDataPath(), 'tokens.json');\n}\n\n/**\n * Get the path to the bundled documentation data\n */\nfunction getDocumentationDataPath(): string {\n return join(getDataPath(), 'tokens-documentation.json');\n}\n\n/**\n * Load all tokens from bundled JSON data\n */\nasync function loadAllTokens(): Promise<DesignToken[]> {\n try {\n const dataPath = getTokensDataPath();\n const content = await readFile(dataPath, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n console.error('Error loading tokens data:', error);\n return [];\n }\n}\n\n/**\n * Load documentation from bundled JSON data\n */\nasync function loadDocumentation(): Promise<TokensDocumentation> {\n try {\n const dataPath = getDocumentationDataPath();\n const content = await readFile(dataPath, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n console.error('Error loading documentation data:', error);\n return {};\n }\n}\n\n/**\n * Get unique themes from tokens\n */\nfunction getAvailableThemes(tokens: DesignToken[]): string[] {\n const themes = new Set<string>();\n for (const token of tokens) {\n if (token.theme) {\n themes.add(token.theme);\n }\n }\n return Array.from(themes).sort();\n}\n\n/**\n * Get design tokens with optional filtering\n */\nexport async function getDesignTokens(\n input: GetDesignTokensInput\n): Promise<GetDesignTokensOutput> {\n const allTokens = await loadAllTokens();\n const documentation = await loadDocumentation();\n\n let filteredTokens = allTokens;\n\n // Filter by theme if specified\n if (input.theme) {\n filteredTokens = filteredTokens.filter(\n (token) => token.theme === input.theme\n );\n }\n\n // Filter by category if specified\n if (input.category) {\n filteredTokens = filteredTokens.filter((token) => {\n // Filter based on type or name pattern\n if (input.category === 'colors' && token.type === 'color') {\n return true;\n }\n if (\n input.category === 'spacing' &&\n (token.type === 'spacing' || token.name.includes('spacing'))\n ) {\n return true;\n }\n if (\n input.category === 'typography' &&\n (token.type === 'fontFamily' ||\n token.type === 'fontSize' ||\n token.type === 'fontWeight' ||\n token.name.includes('font'))\n ) {\n return true;\n }\n if (\n input.category === 'shadows' &&\n (token.type === 'boxShadow' || token.name.includes('shadow'))\n ) {\n return true;\n }\n if (\n input.category === 'borders' &&\n (token.type === 'borderRadius' ||\n token.type === 'borderWidth' ||\n token.name.includes('border'))\n ) {\n return true;\n }\n return false;\n });\n }\n\n const themes = getAvailableThemes(allTokens);\n\n return {\n tokens: filteredTokens,\n themes,\n documentation,\n };\n}\n", "/**\n * List Components tool implementation\n */\n\nimport {\n filterComponents,\n scanAllPackages,\n} from '../extractors/packageScanner.ts';\nimport type { BrickComponentMetadata } from '../types.ts';\n\nexport interface ListComponentsInput {\n filter?: string;\n}\n\nexport interface ListComponentsOutput {\n components: BrickComponentMetadata[];\n}\n\n/**\n * List all available Brick components with optional filtering\n */\nexport async function listComponents(\n input: ListComponentsInput\n): Promise<ListComponentsOutput> {\n // Scan all packages in the monorepo (returns lightweight metadata)\n const allComponents = await scanAllPackages();\n\n // Apply filter if provided\n const components = filterComponents(allComponents, input.filter);\n\n return {\n components,\n };\n}\n"],
5
- "mappings": "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",
6
- "names": ["readFile", "join", "join", "join", "join", "readFile", "readFile", "join", "join", "readFile", "server"]
3
+ "sources": ["../src/index.ts", "../src/server.ts", "../src/extractors/packageScanner.ts", "../src/tools/getComponentDocs.ts", "../src/tools/getDesignTokens.ts", "../src/tools/listComponents.ts"],
4
+ "sourcesContent": ["/**\n * Main MCP server entry point\n */\n\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\n\nimport { createServer } from './server.ts';\n\n// Create and start the server\nconst server = createServer();\n\n// Start receiving messages on stdin and sending messages on stdout\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n", "/**\n * MCP server setup and registration\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\nimport { getComponentDocs } from './tools/getComponentDocs.ts';\nimport { getDesignTokens } from './tools/getDesignTokens.ts';\nimport { listComponents } from './tools/listComponents.ts';\n\n/**\n * Create and configure the MCP server\n */\nexport function createServer(): McpServer {\n // Create an MCP server\n const server = new McpServer({\n name: 'brick-design-system',\n version: '1.0.0',\n });\n\n // Register list-components tool\n server.registerTool(\n 'list-components',\n {\n title: 'List Brick Components',\n description:\n 'List all available Brick components with metadata. Optionally filter by category, tag, or name.',\n inputSchema: {\n filter: z\n .string()\n .optional()\n .describe('Optional filter by category, tag, or name'),\n },\n },\n async ({ filter }) => {\n const result = await listComponents({ filter });\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n );\n\n // Register get-component-docs tool\n server.registerTool(\n 'get-component-docs',\n {\n title: 'Get Component Documentation',\n description:\n 'Retrieve detailed documentation for specific Brick component(s) including props, events, examples, and accessibility information.',\n inputSchema: {\n components: z\n .array(z.string())\n .describe(\n 'Array of component names (e.g., [\"brick-button\", \"brick-modal\"])'\n ),\n },\n },\n async ({ components }) => {\n const result = await getComponentDocs({ components });\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n );\n\n // Register get-design-tokens tool\n server.registerTool(\n 'get-design-tokens',\n {\n title: 'Get Design Tokens',\n description:\n 'Access design tokens from brick-tokens. Optionally filter by category (colors, spacing, typography, shadows, borders) or theme.',\n inputSchema: {\n category: z\n .enum(['colors', 'spacing', 'typography', 'shadows', 'borders'])\n .optional()\n .describe('Filter tokens by category'),\n theme: z\n .string()\n .optional()\n .describe('Filter tokens by theme (e.g., \"bergen\", \"alfa\")'),\n },\n },\n async ({ category, theme }) => {\n const result = await getDesignTokens({ category, theme });\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n );\n\n return server;\n}\n", "/**\n * Package scanner for discovering Brick components\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { type BrickComponent, type BrickComponentMetadata } from '../types.ts';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Get the path to the bundled components data directory\n */\nfunction getDataPath(): string {\n // When bundled by esbuild, __dirname will be 'dist'\n // So we look for 'data' adjacent to __dirname (dist/data)\n return join(__dirname, 'data');\n}\n\n/**\n * Load all component metadata (lightweight, for listing)\n */\nexport async function scanAllPackages(): Promise<BrickComponentMetadata[]> {\n try {\n const metadataPath = join(getDataPath(), 'components-metadata.json');\n const content = await readFile(metadataPath, 'utf-8');\n const metadata: BrickComponentMetadata[] = JSON.parse(content);\n return metadata;\n } catch (error) {\n console.error('Error loading component metadata:', error);\n return [];\n }\n}\n\n/**\n * Load full component data for a specific component\n */\nexport async function loadComponentData(\n componentName: string\n): Promise<BrickComponent | undefined> {\n try {\n const componentPath = join(\n getDataPath(),\n 'components',\n `${componentName}.json`\n );\n const content = await readFile(componentPath, 'utf-8');\n const component: BrickComponent = JSON.parse(content);\n return component;\n } catch (error) {\n console.error(`Error loading component data for ${componentName}:`, error);\n return undefined;\n }\n}\n\n/**\n * Filter components by category or tag\n */\nexport function filterComponents(\n components: BrickComponentMetadata[],\n filter?: string\n): BrickComponentMetadata[] {\n if (!filter) {\n return components;\n }\n\n const filterLower = filter.toLowerCase();\n\n return components.filter((component) => {\n // Match against name\n if (component.name.toLowerCase().includes(filterLower)) {\n return true;\n }\n\n // Match against category\n if (component.category?.toLowerCase().includes(filterLower)) {\n return true;\n }\n\n // Match against tags\n if (\n component.tags?.some((tag) => tag.toLowerCase().includes(filterLower))\n ) {\n return true;\n }\n\n return false;\n });\n}\n", "/**\n * Get Component Docs tool implementation\n */\n\nimport { loadComponentData } from '../extractors/packageScanner.ts';\nimport type { BrickComponent, ComponentDocs } from '../types.ts';\n\nexport interface GetComponentDocsInput {\n components: string[]; // e.g., [\"brick-button\", \"brick-modal\"]\n}\n\nexport interface GetComponentDocsOutput {\n docs: ComponentDocs[];\n}\n\n/**\n * Extract Storybook link from package\n */\nfunction getStorybookLink(componentName: string): string {\n return `https://master--60060c41f82e040021133482.chromatic.com/?path=/docs/bricks-${componentName}`;\n}\n\n/**\n * Extract examples from component data\n */\nfunction extractExamples(component: BrickComponent) {\n const examples: ComponentDocs['examples'] = {\n webComponent: `<${component.selector}></${component.selector}>`,\n storybook: getStorybookLink(component.name),\n };\n\n if (component.mdx) {\n // Try to extract code examples from MDX\n const codeBlockRegex = /```(?:html|javascript|typescript)\\n([\\s\\S]*?)```/;\n const match = component.mdx.match(codeBlockRegex);\n if (match) {\n examples.webComponent = match[1].trim();\n }\n }\n\n return examples;\n}\n\n/**\n * Get documentation for a single component\n */\nasync function getComponentDoc(\n component: BrickComponent\n): Promise<ComponentDocs> {\n const examples = extractExamples(component);\n\n return {\n name: component.name,\n version: component.version,\n selector: component.selector,\n description: component.llm || component.mdx,\n examples,\n cdnPath: `https://assets.acdn.no/pkg/@amedia/${component.name}/${component.version}/${component.name}.js`,\n };\n}\n\n/**\n * Get detailed documentation for specific component(s)\n */\nexport async function getComponentDocs(\n input: GetComponentDocsInput\n): Promise<GetComponentDocsOutput> {\n // Load full component data for each requested component\n const componentDataPromises = input.components.map((componentName) =>\n loadComponentData(componentName)\n );\n\n const componentsData = await Promise.all(componentDataPromises);\n\n // Filter out any components that failed to load\n const validComponents = componentsData.filter(\n (comp): comp is BrickComponent => comp !== undefined\n );\n\n // Get documentation for each component\n const docs = await Promise.all(\n validComponents.map((comp) => getComponentDoc(comp))\n );\n\n return { docs };\n}\n", "/**\n * Get Design Tokens tool implementation\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface DesignToken {\n name: string;\n value: string;\n type: string;\n description?: string;\n category?: string;\n theme?: string;\n}\n\nexport interface GetDesignTokensInput {\n category?: 'colors' | 'spacing' | 'typography' | 'shadows' | 'borders';\n theme?: string;\n}\n\nexport interface GetDesignTokensOutput {\n tokens: DesignToken[];\n}\n\n/**\n * Get the path to the bundled tokens data\n */\nfunction getTokensDataPath(): string {\n // In production (dist), data is in ../data/tokens.json\n // In development (src), data is in ../../data/tokens.json\n const dataPath = join(__dirname, '..', 'data', 'tokens.json');\n return dataPath;\n}\n\n/**\n * Load all tokens from bundled JSON data\n */\nasync function loadAllTokens(): Promise<DesignToken[]> {\n try {\n const dataPath = getTokensDataPath();\n const content = await readFile(dataPath, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n console.error('Error loading tokens data:', error);\n return [];\n }\n}\n\n/**\n * Get design tokens with optional filtering\n */\nexport async function getDesignTokens(\n input: GetDesignTokensInput\n): Promise<GetDesignTokensOutput> {\n const allTokens = await loadAllTokens();\n\n let filteredTokens = allTokens;\n\n // Filter by theme if specified\n if (input.theme) {\n filteredTokens = filteredTokens.filter(\n (token) => token.theme === input.theme\n );\n }\n\n // Filter by category if specified\n if (input.category) {\n filteredTokens = filteredTokens.filter((token) => {\n // Filter based on type or name pattern\n if (input.category === 'colors' && token.type === 'color') {\n return true;\n }\n if (\n input.category === 'spacing' &&\n (token.type === 'spacing' || token.name.includes('spacing'))\n ) {\n return true;\n }\n if (\n input.category === 'typography' &&\n (token.type === 'fontFamily' ||\n token.type === 'fontSize' ||\n token.type === 'fontWeight' ||\n token.name.includes('font'))\n ) {\n return true;\n }\n if (\n input.category === 'shadows' &&\n (token.type === 'boxShadow' || token.name.includes('shadow'))\n ) {\n return true;\n }\n if (\n input.category === 'borders' &&\n (token.type === 'borderRadius' ||\n token.type === 'borderWidth' ||\n token.name.includes('border'))\n ) {\n return true;\n }\n return false;\n });\n }\n\n return { tokens: filteredTokens };\n}\n", "/**\n * List Components tool implementation\n */\n\nimport {\n filterComponents,\n scanAllPackages,\n} from '../extractors/packageScanner.ts';\nimport type { BrickComponentMetadata } from '../types.ts';\n\nexport interface ListComponentsInput {\n filter?: string;\n}\n\nexport interface ListComponentsOutput {\n components: BrickComponentMetadata[];\n}\n\n/**\n * List all available Brick components with optional filtering\n */\nexport async function listComponents(\n input: ListComponentsInput\n): Promise<ListComponentsOutput> {\n // Scan all packages in the monorepo (returns lightweight metadata)\n const allComponents = await scanAllPackages();\n\n // Apply filter if provided\n const components = filterComponents(allComponents, input.filter);\n\n return {\n components,\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["readFile", "dirname", "join", "fileURLToPath", "__filename", "__dirname", "server"]
7
7
  }