mozaic-mcp-server 2.1.1 → 2.3.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.
Files changed (55) hide show
  1. package/README.md +15 -7
  2. package/SKILLS.md +75 -5
  3. package/bin/install-skills.js +2 -0
  4. package/data/mozaic.db +0 -0
  5. package/dist/__tests__/tools.integration.test.js +85 -0
  6. package/dist/__tests__/tools.integration.test.js.map +1 -1
  7. package/dist/index.js +115 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/parsers/freemarker-parser.d.ts +25 -0
  10. package/dist/parsers/freemarker-parser.d.ts.map +1 -0
  11. package/dist/parsers/freemarker-parser.js +299 -0
  12. package/dist/parsers/freemarker-parser.js.map +1 -0
  13. package/dist/parsers/web-components-parser.d.ts +3 -0
  14. package/dist/parsers/web-components-parser.d.ts.map +1 -0
  15. package/dist/parsers/web-components-parser.js +503 -0
  16. package/dist/parsers/web-components-parser.js.map +1 -0
  17. package/dist/tools/generate-freemarker.d.ts +32 -0
  18. package/dist/tools/generate-freemarker.d.ts.map +1 -0
  19. package/dist/tools/generate-freemarker.js +146 -0
  20. package/dist/tools/generate-freemarker.js.map +1 -0
  21. package/dist/tools/generate-webcomponent.d.ts +38 -0
  22. package/dist/tools/generate-webcomponent.d.ts.map +1 -0
  23. package/dist/tools/generate-webcomponent.js +83 -0
  24. package/dist/tools/generate-webcomponent.js.map +1 -0
  25. package/dist/tools/get-component-info.d.ts +1 -1
  26. package/dist/tools/get-component-info.d.ts.map +1 -1
  27. package/dist/tools/get-component-info.js +9 -1
  28. package/dist/tools/get-component-info.js.map +1 -1
  29. package/dist/tools/get-freemarker-info.d.ts +27 -0
  30. package/dist/tools/get-freemarker-info.d.ts.map +1 -0
  31. package/dist/tools/get-freemarker-info.js +161 -0
  32. package/dist/tools/get-freemarker-info.js.map +1 -0
  33. package/dist/tools/get-webcomponent-info.d.ts +52 -0
  34. package/dist/tools/get-webcomponent-info.d.ts.map +1 -0
  35. package/dist/tools/get-webcomponent-info.js +170 -0
  36. package/dist/tools/get-webcomponent-info.js.map +1 -0
  37. package/dist/tools/list-freemarker.d.ts +23 -0
  38. package/dist/tools/list-freemarker.d.ts.map +1 -0
  39. package/dist/tools/list-freemarker.js +97 -0
  40. package/dist/tools/list-freemarker.js.map +1 -0
  41. package/dist/tools/list-webcomponents.d.ts +32 -0
  42. package/dist/tools/list-webcomponents.d.ts.map +1 -0
  43. package/dist/tools/list-webcomponents.js +110 -0
  44. package/dist/tools/list-webcomponents.js.map +1 -0
  45. package/package.json +1 -1
  46. package/skills/mozaic-freemarker-builder/scripts/generate-component.sh +27 -0
  47. package/skills/mozaic-freemarker-builder/scripts/get-component.sh +28 -0
  48. package/skills/mozaic-freemarker-builder/scripts/list-components.sh +13 -0
  49. package/skills/mozaic-freemarker-builder/scripts/search-components.sh +14 -0
  50. package/skills/mozaic-freemarker-builder/skill.md +145 -0
  51. package/skills/mozaic-webcomponents-builder/scripts/generate-component.sh +67 -0
  52. package/skills/mozaic-webcomponents-builder/scripts/get-component.sh +105 -0
  53. package/skills/mozaic-webcomponents-builder/scripts/list-components.sh +42 -0
  54. package/skills/mozaic-webcomponents-builder/scripts/search-components.sh +34 -0
  55. package/skills/mozaic-webcomponents-builder/skill.md +292 -0
@@ -0,0 +1,170 @@
1
+ import { getComponentBySlug } from "../db/queries.js";
2
+ export function handleGetWebComponentInfo(db, input) {
3
+ const { component } = input;
4
+ // Normalize component name to slug (kebab-case)
5
+ const slug = component.toLowerCase().replace(/^mozaic-/, "");
6
+ const componentData = getComponentBySlug(db, slug);
7
+ if (!componentData) {
8
+ return {
9
+ content: [
10
+ {
11
+ type: "text",
12
+ text: `Web Component not found: ${component}. Try using the list_webcomponents tool to see available components.`,
13
+ },
14
+ ],
15
+ };
16
+ }
17
+ // Check if component supports webcomponents framework
18
+ const frameworks = componentData.frameworks || [];
19
+ if (!frameworks.includes("webcomponents")) {
20
+ return {
21
+ content: [
22
+ {
23
+ type: "text",
24
+ text: `Component "${component}" is not available as a web component. Available frameworks: ${frameworks.join(", ")}`,
25
+ },
26
+ ],
27
+ };
28
+ }
29
+ // Filter examples for webcomponents
30
+ const filteredExamples = (componentData.examples || [])
31
+ .filter((ex) => ex.framework === "webcomponents")
32
+ .map((ex) => ({
33
+ title: ex.title,
34
+ code: ex.code,
35
+ }));
36
+ // Build output
37
+ const output = {
38
+ name: componentData.name,
39
+ tagName: componentData.slug,
40
+ description: componentData.description,
41
+ attributes: (componentData.props || []).map((p) => ({
42
+ name: p.name,
43
+ type: p.type,
44
+ default: p.defaultValue,
45
+ required: p.required || false,
46
+ options: p.options,
47
+ description: p.description,
48
+ })),
49
+ slots: (componentData.slots || []).map((s) => ({
50
+ name: s.name,
51
+ description: s.description,
52
+ })),
53
+ events: (componentData.events || []).map((e) => ({
54
+ name: e.name,
55
+ payload: e.payload,
56
+ description: e.description,
57
+ })),
58
+ cssProperties: componentData.cssClasses || [],
59
+ examples: filteredExamples,
60
+ };
61
+ // Add basic example if none found
62
+ if (output.examples.length === 0) {
63
+ const basicExample = generateBasicWebComponentExample(output.tagName);
64
+ output.examples.push({ title: "Basic Usage", code: basicExample });
65
+ }
66
+ // Add formatted output with helpful information
67
+ let text = `# ${output.name} (${output.tagName})\n\n`;
68
+ if (output.description) {
69
+ text += `${output.description}\n\n`;
70
+ }
71
+ // Attributes section
72
+ if (output.attributes.length > 0) {
73
+ text += `## Attributes\n\n`;
74
+ for (const attr of output.attributes) {
75
+ text += `- **${attr.name}**`;
76
+ if (attr.type)
77
+ text += ` (${attr.type})`;
78
+ if (attr.required)
79
+ text += ` *required*`;
80
+ if (attr.default)
81
+ text += ` - default: \`${attr.default}\``;
82
+ if (attr.description)
83
+ text += `\n ${attr.description}`;
84
+ if (attr.options && attr.options.length > 0) {
85
+ text += `\n Options: ${attr.options.map((o) => `\`${o}\``).join(", ")}`;
86
+ }
87
+ text += `\n`;
88
+ }
89
+ text += `\n`;
90
+ }
91
+ // Slots section
92
+ if (output.slots.length > 0) {
93
+ text += `## Slots\n\n`;
94
+ for (const slot of output.slots) {
95
+ text += `- **${slot.name}**`;
96
+ if (slot.description)
97
+ text += ` - ${slot.description}`;
98
+ text += `\n`;
99
+ }
100
+ text += `\n`;
101
+ }
102
+ // Events section
103
+ if (output.events.length > 0) {
104
+ text += `## Events\n\n`;
105
+ for (const event of output.events) {
106
+ text += `- **${event.name}**`;
107
+ if (event.payload)
108
+ text += ` (payload: ${event.payload})`;
109
+ if (event.description)
110
+ text += `\n ${event.description}`;
111
+ text += `\n`;
112
+ }
113
+ text += `\n`;
114
+ }
115
+ // CSS Properties section
116
+ if (output.cssProperties.length > 0) {
117
+ text += `## CSS Custom Properties\n\n`;
118
+ for (const prop of output.cssProperties) {
119
+ text += `- \`${prop}\`\n`;
120
+ }
121
+ text += `\n`;
122
+ }
123
+ // Examples section
124
+ if (output.examples.length > 0) {
125
+ text += `## Examples\n\n`;
126
+ for (const example of output.examples) {
127
+ if (example.title) {
128
+ text += `### ${example.title}\n\n`;
129
+ }
130
+ text += `\`\`\`html\n${example.code}\n\`\`\`\n\n`;
131
+ }
132
+ }
133
+ // Installation
134
+ text += `## Installation\n\n`;
135
+ text += `\`\`\`javascript\n`;
136
+ text += `import '@adeo/mozaic-web-components/${slug}.js';\n`;
137
+ text += `\`\`\`\n\n`;
138
+ // JSON output for programmatic use
139
+ text += `---\n\n`;
140
+ text += `**JSON Output:**\n\n`;
141
+ text += `\`\`\`json\n${JSON.stringify(output, null, 2)}\n\`\`\``;
142
+ return {
143
+ content: [
144
+ {
145
+ type: "text",
146
+ text,
147
+ },
148
+ ],
149
+ };
150
+ }
151
+ // Generate a basic example
152
+ function generateBasicWebComponentExample(tagName) {
153
+ return `<${tagName}>\n Content\n</${tagName}>`;
154
+ }
155
+ // Tool definition for MCP
156
+ export const getWebComponentInfoTool = {
157
+ name: "get_webcomponent_info",
158
+ description: "Get detailed information about a Mozaic Web Component including attributes, slots, events, CSS custom properties, and usage examples.",
159
+ inputSchema: {
160
+ type: "object",
161
+ properties: {
162
+ component: {
163
+ type: "string",
164
+ description: "Web component name (e.g., 'button', 'card', 'mozaic-button'). Will be converted to tag name.",
165
+ },
166
+ },
167
+ required: ["component"],
168
+ },
169
+ };
170
+ //# sourceMappingURL=get-webcomponent-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-webcomponent-info.js","sourceRoot":"","sources":["../../src/tools/get-webcomponent-info.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import Database from "better-sqlite3";
2
+ import { z } from "zod";
3
+ /**
4
+ * List Freemarker components by category
5
+ *
6
+ * Returns a list of all Freemarker macro components, optionally filtered by category.
7
+ */
8
+ declare const _ListFreemarkerInputSchema: z.ZodObject<{
9
+ category: z.ZodDefault<z.ZodOptional<z.ZodEnum<["all", "action", "form", "feedback", "navigation", "layout", "data-display", "other"]>>>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ category: "all" | "form" | "navigation" | "feedback" | "layout" | "data-display" | "action" | "other";
12
+ }, {
13
+ category?: "all" | "form" | "navigation" | "feedback" | "layout" | "data-display" | "action" | "other" | undefined;
14
+ }>;
15
+ export type ListFreemarkerInput = z.infer<typeof _ListFreemarkerInputSchema>;
16
+ export declare function handleListFreemarker(db: Database.Database, input: ListFreemarkerInput): {
17
+ content: Array<{
18
+ type: "text";
19
+ text: string;
20
+ }>;
21
+ };
22
+ export {};
23
+ //# sourceMappingURL=list-freemarker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-freemarker.d.ts","sourceRoot":"","sources":["../../src/tools/list-freemarker.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AAEH,QAAA,MAAM,0BAA0B;;;;;;EAM9B,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE7E,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,mBAAmB,GACzB;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAqGpD"}
@@ -0,0 +1,97 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * List Freemarker components by category
4
+ *
5
+ * Returns a list of all Freemarker macro components, optionally filtered by category.
6
+ */
7
+ const _ListFreemarkerInputSchema = z.object({
8
+ category: z
9
+ .enum(["all", "action", "form", "feedback", "navigation", "layout", "data-display", "other"])
10
+ .optional()
11
+ .default("all")
12
+ .describe("Filter by category (default: all)"),
13
+ });
14
+ export function handleListFreemarker(db, input) {
15
+ const category = input.category || "all";
16
+ let query = `
17
+ SELECT name, slug, category, description
18
+ FROM components
19
+ WHERE frameworks LIKE '%freemarker%'
20
+ `;
21
+ const params = [];
22
+ if (category !== "all") {
23
+ query += ` AND category = ?`;
24
+ params.push(category);
25
+ }
26
+ query += ` ORDER BY category ASC, name ASC`;
27
+ const components = db.prepare(query).all(...params);
28
+ if (components.length === 0) {
29
+ return {
30
+ content: [
31
+ {
32
+ type: "text",
33
+ text: `No Freemarker components found${category !== "all" ? ` in category "${category}"` : ""}.`,
34
+ },
35
+ ],
36
+ };
37
+ }
38
+ // Group components by category
39
+ const groupedComponents = new Map();
40
+ components.forEach((component) => {
41
+ const cat = component.category;
42
+ if (!groupedComponents.has(cat)) {
43
+ groupedComponents.set(cat, []);
44
+ }
45
+ const group = groupedComponents.get(cat);
46
+ if (group) {
47
+ group.push(component);
48
+ }
49
+ });
50
+ // Build output
51
+ let output = `# Freemarker Components\n\n`;
52
+ output += `Found ${components.length} components`;
53
+ if (category !== "all") {
54
+ output += ` in category "${category}"`;
55
+ }
56
+ output += `\n\n`;
57
+ // List by category
58
+ const categories = Array.from(groupedComponents.keys()).sort();
59
+ categories.forEach((cat) => {
60
+ const comps = groupedComponents.get(cat);
61
+ if (!comps)
62
+ return;
63
+ output += `## ${cat.charAt(0).toUpperCase() + cat.slice(1)} (${comps.length})\n\n`;
64
+ comps.forEach((comp) => {
65
+ output += `### ${comp.name}\n`;
66
+ output += `- **Slug:** \`${comp.slug}\`\n`;
67
+ if (comp.description) {
68
+ output += `- **Description:** ${comp.description}\n`;
69
+ }
70
+ const macroName = comp.slug.replace(/-/g, "");
71
+ output += `- **Usage:** \`<#import "mozaic/${macroName}.ftl" as ${macroName}>\`\n`;
72
+ output += `\n`;
73
+ });
74
+ });
75
+ // Summary by category
76
+ output += `---\n\n`;
77
+ output += `## Summary by Category\n\n`;
78
+ categories.forEach((cat) => {
79
+ const group = groupedComponents.get(cat);
80
+ if (group) {
81
+ output += `- **${cat}**: ${group.length} components\n`;
82
+ }
83
+ });
84
+ output += `\n`;
85
+ output += `## Next Steps\n\n`;
86
+ output += `Use \`get_freemarker_info\` to view detailed information about a specific component.\n`;
87
+ output += `Use \`generate_freemarker\` to generate ready-to-use code for a component.\n`;
88
+ return {
89
+ content: [
90
+ {
91
+ type: "text",
92
+ text: output,
93
+ },
94
+ ],
95
+ };
96
+ }
97
+ //# sourceMappingURL=list-freemarker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-freemarker.js","sourceRoot":"","sources":["../../src/tools/list-freemarker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type Database from "better-sqlite3";
2
+ export interface ListWebComponentsInput {
3
+ category?: "form" | "navigation" | "feedback" | "layout" | "data-display" | "action" | "all";
4
+ }
5
+ export interface WebComponentListItem {
6
+ name: string;
7
+ tagName: string;
8
+ category: string;
9
+ description?: string;
10
+ }
11
+ export declare function handleListWebComponents(db: Database.Database, input: ListWebComponentsInput): {
12
+ content: Array<{
13
+ type: "text";
14
+ text: string;
15
+ }>;
16
+ };
17
+ export declare const listWebComponentsTool: {
18
+ name: string;
19
+ description: string;
20
+ inputSchema: {
21
+ type: "object";
22
+ properties: {
23
+ category: {
24
+ type: string;
25
+ enum: string[];
26
+ default: string;
27
+ description: string;
28
+ };
29
+ };
30
+ };
31
+ };
32
+ //# sourceMappingURL=list-webcomponents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-webcomponents.d.ts","sourceRoot":"","sources":["../../src/tools/list-webcomponents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,UAAU,GAAG,QAAQ,GAAG,cAAc,GAAG,QAAQ,GAAG,KAAK,CAAC;CAC9F;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,sBAAsB,GAC5B;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAgHpD;AAGD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;CAejC,CAAC"}
@@ -0,0 +1,110 @@
1
+ export function handleListWebComponents(db, input) {
2
+ const { category = "all" } = input;
3
+ // Query components with webcomponents framework
4
+ let query = `
5
+ SELECT name, slug, category, description, frameworks
6
+ FROM components
7
+ WHERE frameworks LIKE '%webcomponents%'
8
+ `;
9
+ const params = [];
10
+ if (category && category !== "all") {
11
+ query += ` AND category = ?`;
12
+ params.push(category);
13
+ }
14
+ query += ` ORDER BY category, name`;
15
+ const rows = db.prepare(query).all(...params);
16
+ if (rows.length === 0) {
17
+ return {
18
+ content: [
19
+ {
20
+ type: "text",
21
+ text: category === "all"
22
+ ? "No web components found in the database."
23
+ : `No web components found in category: ${category}`,
24
+ },
25
+ ],
26
+ };
27
+ }
28
+ // Group by category for better readability
29
+ const grouped = {};
30
+ for (const row of rows) {
31
+ const cat = row.category || "other";
32
+ if (!grouped[cat]) {
33
+ grouped[cat] = [];
34
+ }
35
+ grouped[cat].push({
36
+ name: row.name,
37
+ tagName: row.slug,
38
+ category: cat,
39
+ description: row.description,
40
+ });
41
+ }
42
+ // Format output
43
+ let text = `# Mozaic Web Components\n\n`;
44
+ text += `Total: ${rows.length} component${rows.length !== 1 ? "s" : ""}\n\n`;
45
+ if (category === "all") {
46
+ text += `## Categories\n\n`;
47
+ for (const [cat, components] of Object.entries(grouped)) {
48
+ text += `### ${cat.charAt(0).toUpperCase() + cat.slice(1)} (${components.length})\n\n`;
49
+ for (const comp of components) {
50
+ text += `- **${comp.name}** (\`<${comp.tagName}>\`)`;
51
+ if (comp.description) {
52
+ text += `\n ${comp.description}`;
53
+ }
54
+ text += `\n`;
55
+ }
56
+ text += `\n`;
57
+ }
58
+ }
59
+ else {
60
+ text += `## ${category.charAt(0).toUpperCase() + category.slice(1)} Components\n\n`;
61
+ for (const comp of rows) {
62
+ text += `- **${comp.name}** (\`<${comp.slug}>\`)`;
63
+ if (comp.description) {
64
+ text += `\n ${comp.description}`;
65
+ }
66
+ text += `\n`;
67
+ }
68
+ }
69
+ // JSON output
70
+ const jsonOutput = {
71
+ total: rows.length,
72
+ categories: Object.keys(grouped),
73
+ components: category === "all"
74
+ ? grouped
75
+ : rows.map((r) => ({
76
+ name: r.name,
77
+ tagName: r.slug,
78
+ category: r.category,
79
+ description: r.description,
80
+ })),
81
+ };
82
+ text += `\n---\n\n`;
83
+ text += `**JSON Output:**\n\n`;
84
+ text += `\`\`\`json\n${JSON.stringify(jsonOutput, null, 2)}\n\`\`\``;
85
+ return {
86
+ content: [
87
+ {
88
+ type: "text",
89
+ text,
90
+ },
91
+ ],
92
+ };
93
+ }
94
+ // Tool definition for MCP
95
+ export const listWebComponentsTool = {
96
+ name: "list_webcomponents",
97
+ description: "List available Mozaic Web Components by category. Returns custom element tag names and descriptions.",
98
+ inputSchema: {
99
+ type: "object",
100
+ properties: {
101
+ category: {
102
+ type: "string",
103
+ enum: ["form", "navigation", "feedback", "layout", "data-display", "action", "all"],
104
+ default: "all",
105
+ description: "Filter web components by category",
106
+ },
107
+ },
108
+ },
109
+ };
110
+ //# sourceMappingURL=list-webcomponents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-webcomponents.js","sourceRoot":"","sources":["../../src/tools/list-webcomponents.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,uBAAuB,CACrC,EAAqB,EACrB,KAA6B;IAE7B,MAAM,EAAE,QAAQ,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC;IAEnC,gDAAgD;IAChD,IAAI,KAAK,GAAG;;;;GAIX,CAAC;IAEF,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,QAAQ,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;QACnC,KAAK,IAAI,mBAAmB,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,IAAI,0BAA0B,CAAC;IAEpC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAM1C,CAAC;IAEH,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EACF,QAAQ,KAAK,KAAK;wBAChB,CAAC,CAAC,0CAA0C;wBAC5C,CAAC,CAAC,wCAAwC,QAAQ,EAAE;iBACzD;aACF;SACF,CAAC;IACJ,CAAC;IAED,2CAA2C;IAC3C,MAAM,OAAO,GAA2C,EAAE,CAAC;IAE3D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,IAAI,OAAO,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACpB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YAChB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,OAAO,EAAE,GAAG,CAAC,IAAI;YACjB,QAAQ,EAAE,GAAG;YACb,WAAW,EAAE,GAAG,CAAC,WAAW;SAC7B,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB;IAChB,IAAI,IAAI,GAAG,6BAA6B,CAAC;IACzC,IAAI,IAAI,UAAU,IAAI,CAAC,MAAM,aAAa,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IAE7E,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;QACvB,IAAI,IAAI,mBAAmB,CAAC;QAC5B,KAAK,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACxD,IAAI,IAAI,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,MAAM,OAAO,CAAC;YACvF,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;gBAC9B,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,OAAO,MAAM,CAAC;gBACrD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;oBACrB,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;gBACpC,CAAC;gBACD,IAAI,IAAI,IAAI,CAAC;YACf,CAAC;YACD,IAAI,IAAI,IAAI,CAAC;QACf,CAAC;IACH,CAAC;SAAM,CAAC;QACN,IAAI,IAAI,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC;QACpF,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,IAAI,MAAM,CAAC;YAClD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;YACpC,CAAC;YACD,IAAI,IAAI,IAAI,CAAC;QACf,CAAC;IACH,CAAC;IAED,cAAc;IACd,MAAM,UAAU,GAAG;QACjB,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;QAChC,UAAU,EACR,QAAQ,KAAK,KAAK;YAChB,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACf,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,OAAO,EAAE,CAAC,CAAC,IAAI;gBACf,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,WAAW,EAAE,CAAC,CAAC,WAAW;aAC3B,CAAC,CAAC;KACV,CAAC;IAEF,IAAI,IAAI,WAAW,CAAC;IACpB,IAAI,IAAI,sBAAsB,CAAC;IAC/B,IAAI,IAAI,eAAe,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC;IAErE,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI;aACL;SACF;KACF,CAAC;AACJ,CAAC;AAED,0BAA0B;AAC1B,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,sGAAsG;IACxG,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,KAAK,CAAC;gBACnF,OAAO,EAAE,KAAK;gBACd,WAAW,EAAE,mCAAmC;aACjD;SACF;KACF;CACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mozaic-mcp-server",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "Self-contained Claude Code skills for Mozaic Design System by ADEO",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,27 @@
1
+ #!/bin/bash
2
+ # Generate Freemarker macro usage code
3
+ COMPONENT="${1:?Component name required}"
4
+ CONFIG="${2:-{}}"
5
+ CONTENT="${3:-Content goes here}"
6
+ DB_PATH="${MOZAIC_DB_PATH:-${HOME}/.claude/mozaic.db}"
7
+
8
+ # Get component info
9
+ COMP_DATA=$(sqlite3 "$DB_PATH" "SELECT slug FROM components WHERE frameworks LIKE '%freemarker%' AND (LOWER(slug) LIKE LOWER('%$COMPONENT%') OR LOWER(name) LIKE LOWER('%$COMPONENT%')) LIMIT 1;")
10
+
11
+ if [ -z "$COMP_DATA" ]; then
12
+ echo "Component '$COMPONENT' not found"
13
+ exit 1
14
+ fi
15
+
16
+ MACRO_NAME=$(echo "$COMP_DATA" | tr '-' '')
17
+
18
+ # Generate code
19
+ cat <<EOF
20
+ <#import "mozaic/${MACRO_NAME}.ftl" as ${MACRO_NAME}>
21
+
22
+ <#assign config = ${CONFIG}>
23
+
24
+ <@${MACRO_NAME}.${MACRO_NAME} config=config>
25
+ ${CONTENT}
26
+ </@${MACRO_NAME}.${MACRO_NAME}>
27
+ EOF
@@ -0,0 +1,28 @@
1
+ #!/bin/bash
2
+ # Get detailed Freemarker component information
3
+ COMPONENT="${1:?Component name required}"
4
+ DB_PATH="${MOZAIC_DB_PATH:-${HOME}/.claude/mozaic.db}"
5
+
6
+ sqlite3 "$DB_PATH" <<EOF
7
+ .mode json
8
+ SELECT
9
+ c.name,
10
+ c.slug,
11
+ c.category,
12
+ c.description,
13
+ json_group_array(
14
+ json_object(
15
+ 'name', p.name,
16
+ 'type', p.type,
17
+ 'required', p.required,
18
+ 'default', p.default_value,
19
+ 'description', p.description
20
+ )
21
+ ) as props
22
+ FROM components c
23
+ LEFT JOIN component_props p ON p.component_id = c.id
24
+ WHERE c.frameworks LIKE '%freemarker%'
25
+ AND (LOWER(c.slug) LIKE LOWER('%$COMPONENT%') OR LOWER(c.name) LIKE LOWER('%$COMPONENT%'))
26
+ GROUP BY c.id
27
+ LIMIT 1;
28
+ EOF
@@ -0,0 +1,13 @@
1
+ #!/bin/bash
2
+ # List Freemarker components by category
3
+ CATEGORY="${1:-all}"
4
+ DB_PATH="${MOZAIC_DB_PATH:-${HOME}/.claude/mozaic.db}"
5
+
6
+ sqlite3 "$DB_PATH" <<EOF
7
+ .mode json
8
+ SELECT name, slug, category, description
9
+ FROM components
10
+ WHERE frameworks LIKE '%freemarker%'
11
+ ${CATEGORY:+AND category = '$CATEGORY'}
12
+ ORDER BY category, name;
13
+ EOF
@@ -0,0 +1,14 @@
1
+ #!/bin/bash
2
+ # Search Freemarker components by name or description
3
+ QUERY="${1:?Search query required}"
4
+ DB_PATH="${MOZAIC_DB_PATH:-${HOME}/.claude/mozaic.db}"
5
+
6
+ sqlite3 "$DB_PATH" <<EOF
7
+ .mode json
8
+ SELECT name, slug, category, description
9
+ FROM components
10
+ WHERE frameworks LIKE '%freemarker%'
11
+ AND (LOWER(name) LIKE LOWER('%$QUERY%') OR LOWER(description) LIKE LOWER('%$QUERY%'))
12
+ ORDER BY name
13
+ LIMIT 20;
14
+ EOF