@forgespace/branding-mcp 0.4.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 (244) hide show
  1. package/.env.example +3 -0
  2. package/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  3. package/.github/workflows/ci.yml +73 -0
  4. package/.github/workflows/release-automation.yml +56 -0
  5. package/.github/workflows/security-scan.yml +37 -0
  6. package/.gitleaks.toml +14 -0
  7. package/.prettierrc.json +10 -0
  8. package/CHANGELOG.md +66 -0
  9. package/CONTRIBUTING.md +203 -0
  10. package/LICENSE +21 -0
  11. package/README.md +105 -0
  12. package/data/README.md +13 -0
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +49 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/lib/branding-core/ai/brand-interpreter.d.ts +5 -0
  18. package/dist/lib/branding-core/ai/brand-interpreter.d.ts.map +1 -0
  19. package/dist/lib/branding-core/ai/brand-interpreter.js +16 -0
  20. package/dist/lib/branding-core/ai/brand-interpreter.js.map +1 -0
  21. package/dist/lib/branding-core/ai/claude-interpreter.d.ts +5 -0
  22. package/dist/lib/branding-core/ai/claude-interpreter.d.ts.map +1 -0
  23. package/dist/lib/branding-core/ai/claude-interpreter.js +55 -0
  24. package/dist/lib/branding-core/ai/claude-interpreter.js.map +1 -0
  25. package/dist/lib/branding-core/ai/intent-applier.d.ts +4 -0
  26. package/dist/lib/branding-core/ai/intent-applier.d.ts.map +1 -0
  27. package/dist/lib/branding-core/ai/intent-applier.js +29 -0
  28. package/dist/lib/branding-core/ai/intent-applier.js.map +1 -0
  29. package/dist/lib/branding-core/ai/keyword-interpreter.d.ts +4 -0
  30. package/dist/lib/branding-core/ai/keyword-interpreter.d.ts.map +1 -0
  31. package/dist/lib/branding-core/ai/keyword-interpreter.js +85 -0
  32. package/dist/lib/branding-core/ai/keyword-interpreter.js.map +1 -0
  33. package/dist/lib/branding-core/ai/prompts.d.ts +4 -0
  34. package/dist/lib/branding-core/ai/prompts.d.ts.map +1 -0
  35. package/dist/lib/branding-core/ai/prompts.js +79 -0
  36. package/dist/lib/branding-core/ai/prompts.js.map +1 -0
  37. package/dist/lib/branding-core/ai/types.d.ts +27 -0
  38. package/dist/lib/branding-core/ai/types.d.ts.map +1 -0
  39. package/dist/lib/branding-core/ai/types.js +2 -0
  40. package/dist/lib/branding-core/ai/types.js.map +1 -0
  41. package/dist/lib/branding-core/documents/html-generator.d.ts +3 -0
  42. package/dist/lib/branding-core/documents/html-generator.d.ts.map +1 -0
  43. package/dist/lib/branding-core/documents/html-generator.js +31 -0
  44. package/dist/lib/branding-core/documents/html-generator.js.map +1 -0
  45. package/dist/lib/branding-core/documents/pdf-generator.d.ts +3 -0
  46. package/dist/lib/branding-core/documents/pdf-generator.d.ts.map +1 -0
  47. package/dist/lib/branding-core/documents/pdf-generator.js +20 -0
  48. package/dist/lib/branding-core/documents/pdf-generator.js.map +1 -0
  49. package/dist/lib/branding-core/exporters/css-variables.d.ts +3 -0
  50. package/dist/lib/branding-core/exporters/css-variables.d.ts.map +1 -0
  51. package/dist/lib/branding-core/exporters/css-variables.js +62 -0
  52. package/dist/lib/branding-core/exporters/css-variables.js.map +1 -0
  53. package/dist/lib/branding-core/exporters/design-tokens.d.ts +3 -0
  54. package/dist/lib/branding-core/exporters/design-tokens.d.ts.map +1 -0
  55. package/dist/lib/branding-core/exporters/design-tokens.js +75 -0
  56. package/dist/lib/branding-core/exporters/design-tokens.js.map +1 -0
  57. package/dist/lib/branding-core/exporters/figma-tokens.d.ts +9 -0
  58. package/dist/lib/branding-core/exporters/figma-tokens.d.ts.map +1 -0
  59. package/dist/lib/branding-core/exporters/figma-tokens.js +69 -0
  60. package/dist/lib/branding-core/exporters/figma-tokens.js.map +1 -0
  61. package/dist/lib/branding-core/exporters/react-theme.d.ts +3 -0
  62. package/dist/lib/branding-core/exporters/react-theme.d.ts.map +1 -0
  63. package/dist/lib/branding-core/exporters/react-theme.js +61 -0
  64. package/dist/lib/branding-core/exporters/react-theme.js.map +1 -0
  65. package/dist/lib/branding-core/exporters/sass-variables.d.ts +3 -0
  66. package/dist/lib/branding-core/exporters/sass-variables.d.ts.map +1 -0
  67. package/dist/lib/branding-core/exporters/sass-variables.js +65 -0
  68. package/dist/lib/branding-core/exporters/sass-variables.js.map +1 -0
  69. package/dist/lib/branding-core/exporters/tailwind-preset.d.ts +3 -0
  70. package/dist/lib/branding-core/exporters/tailwind-preset.d.ts.map +1 -0
  71. package/dist/lib/branding-core/exporters/tailwind-preset.js +55 -0
  72. package/dist/lib/branding-core/exporters/tailwind-preset.js.map +1 -0
  73. package/dist/lib/branding-core/generators/border-system.d.ts +3 -0
  74. package/dist/lib/branding-core/generators/border-system.d.ts.map +1 -0
  75. package/dist/lib/branding-core/generators/border-system.js +37 -0
  76. package/dist/lib/branding-core/generators/border-system.js.map +1 -0
  77. package/dist/lib/branding-core/generators/color-palette.d.ts +7 -0
  78. package/dist/lib/branding-core/generators/color-palette.d.ts.map +1 -0
  79. package/dist/lib/branding-core/generators/color-palette.js +117 -0
  80. package/dist/lib/branding-core/generators/color-palette.js.map +1 -0
  81. package/dist/lib/branding-core/generators/favicon-generator.d.ts +3 -0
  82. package/dist/lib/branding-core/generators/favicon-generator.d.ts.map +1 -0
  83. package/dist/lib/branding-core/generators/favicon-generator.js +23 -0
  84. package/dist/lib/branding-core/generators/favicon-generator.js.map +1 -0
  85. package/dist/lib/branding-core/generators/gradient-system.d.ts +3 -0
  86. package/dist/lib/branding-core/generators/gradient-system.d.ts.map +1 -0
  87. package/dist/lib/branding-core/generators/gradient-system.js +74 -0
  88. package/dist/lib/branding-core/generators/gradient-system.js.map +1 -0
  89. package/dist/lib/branding-core/generators/logo-generator.d.ts +4 -0
  90. package/dist/lib/branding-core/generators/logo-generator.d.ts.map +1 -0
  91. package/dist/lib/branding-core/generators/logo-generator.js +130 -0
  92. package/dist/lib/branding-core/generators/logo-generator.js.map +1 -0
  93. package/dist/lib/branding-core/generators/motion-system.d.ts +3 -0
  94. package/dist/lib/branding-core/generators/motion-system.d.ts.map +1 -0
  95. package/dist/lib/branding-core/generators/motion-system.js +91 -0
  96. package/dist/lib/branding-core/generators/motion-system.js.map +1 -0
  97. package/dist/lib/branding-core/generators/og-image-generator.d.ts +3 -0
  98. package/dist/lib/branding-core/generators/og-image-generator.d.ts.map +1 -0
  99. package/dist/lib/branding-core/generators/og-image-generator.js +72 -0
  100. package/dist/lib/branding-core/generators/og-image-generator.js.map +1 -0
  101. package/dist/lib/branding-core/generators/shadow-system.d.ts +3 -0
  102. package/dist/lib/branding-core/generators/shadow-system.d.ts.map +1 -0
  103. package/dist/lib/branding-core/generators/shadow-system.js +44 -0
  104. package/dist/lib/branding-core/generators/shadow-system.js.map +1 -0
  105. package/dist/lib/branding-core/generators/spacing-scale.d.ts +3 -0
  106. package/dist/lib/branding-core/generators/spacing-scale.d.ts.map +1 -0
  107. package/dist/lib/branding-core/generators/spacing-scale.js +27 -0
  108. package/dist/lib/branding-core/generators/spacing-scale.js.map +1 -0
  109. package/dist/lib/branding-core/generators/typography-system.d.ts +3 -0
  110. package/dist/lib/branding-core/generators/typography-system.d.ts.map +1 -0
  111. package/dist/lib/branding-core/generators/typography-system.js +121 -0
  112. package/dist/lib/branding-core/generators/typography-system.js.map +1 -0
  113. package/dist/lib/branding-core/index.d.ts +24 -0
  114. package/dist/lib/branding-core/index.d.ts.map +1 -0
  115. package/dist/lib/branding-core/index.js +22 -0
  116. package/dist/lib/branding-core/index.js.map +1 -0
  117. package/dist/lib/branding-core/validators/brand-consistency.d.ts +3 -0
  118. package/dist/lib/branding-core/validators/brand-consistency.d.ts.map +1 -0
  119. package/dist/lib/branding-core/validators/brand-consistency.js +70 -0
  120. package/dist/lib/branding-core/validators/brand-consistency.js.map +1 -0
  121. package/dist/lib/branding-core/validators/contrast-checker.d.ts +3 -0
  122. package/dist/lib/branding-core/validators/contrast-checker.d.ts.map +1 -0
  123. package/dist/lib/branding-core/validators/contrast-checker.js +33 -0
  124. package/dist/lib/branding-core/validators/contrast-checker.js.map +1 -0
  125. package/dist/lib/branding-core/validators/token-schema.d.ts +10 -0
  126. package/dist/lib/branding-core/validators/token-schema.d.ts.map +1 -0
  127. package/dist/lib/branding-core/validators/token-schema.js +43 -0
  128. package/dist/lib/branding-core/validators/token-schema.js.map +1 -0
  129. package/dist/lib/config.d.ts +7 -0
  130. package/dist/lib/config.d.ts.map +1 -0
  131. package/dist/lib/config.js +8 -0
  132. package/dist/lib/config.js.map +1 -0
  133. package/dist/lib/logger.d.ts +3 -0
  134. package/dist/lib/logger.d.ts.map +1 -0
  135. package/dist/lib/logger.js +10 -0
  136. package/dist/lib/logger.js.map +1 -0
  137. package/dist/lib/types.d.ts +208 -0
  138. package/dist/lib/types.d.ts.map +1 -0
  139. package/dist/lib/types.js +2 -0
  140. package/dist/lib/types.js.map +1 -0
  141. package/dist/resources/brand-knowledge.d.ts +3 -0
  142. package/dist/resources/brand-knowledge.d.ts.map +1 -0
  143. package/dist/resources/brand-knowledge.js +53 -0
  144. package/dist/resources/brand-knowledge.js.map +1 -0
  145. package/dist/resources/brand-templates.d.ts +3 -0
  146. package/dist/resources/brand-templates.d.ts.map +1 -0
  147. package/dist/resources/brand-templates.js +68 -0
  148. package/dist/resources/brand-templates.js.map +1 -0
  149. package/dist/tools/create-brand-guidelines.d.ts +3 -0
  150. package/dist/tools/create-brand-guidelines.d.ts.map +1 -0
  151. package/dist/tools/create-brand-guidelines.js +85 -0
  152. package/dist/tools/create-brand-guidelines.js.map +1 -0
  153. package/dist/tools/export-design-tokens.d.ts +3 -0
  154. package/dist/tools/export-design-tokens.d.ts.map +1 -0
  155. package/dist/tools/export-design-tokens.js +37 -0
  156. package/dist/tools/export-design-tokens.js.map +1 -0
  157. package/dist/tools/generate-brand-assets.d.ts +3 -0
  158. package/dist/tools/generate-brand-assets.d.ts.map +1 -0
  159. package/dist/tools/generate-brand-assets.js +37 -0
  160. package/dist/tools/generate-brand-assets.js.map +1 -0
  161. package/dist/tools/generate-brand-identity.d.ts +3 -0
  162. package/dist/tools/generate-brand-identity.d.ts.map +1 -0
  163. package/dist/tools/generate-brand-identity.js +73 -0
  164. package/dist/tools/generate-brand-identity.js.map +1 -0
  165. package/dist/tools/generate-color-palette.d.ts +3 -0
  166. package/dist/tools/generate-color-palette.d.ts.map +1 -0
  167. package/dist/tools/generate-color-palette.js +33 -0
  168. package/dist/tools/generate-color-palette.js.map +1 -0
  169. package/dist/tools/generate-typography-system.d.ts +3 -0
  170. package/dist/tools/generate-typography-system.d.ts.map +1 -0
  171. package/dist/tools/generate-typography-system.js +28 -0
  172. package/dist/tools/generate-typography-system.js.map +1 -0
  173. package/dist/tools/refine-brand-element.d.ts +3 -0
  174. package/dist/tools/refine-brand-element.d.ts.map +1 -0
  175. package/dist/tools/refine-brand-element.js +41 -0
  176. package/dist/tools/refine-brand-element.js.map +1 -0
  177. package/dist/tools/validate-brand-consistency.d.ts +3 -0
  178. package/dist/tools/validate-brand-consistency.d.ts.map +1 -0
  179. package/dist/tools/validate-brand-consistency.js +25 -0
  180. package/dist/tools/validate-brand-consistency.js.map +1 -0
  181. package/docs/API.md +110 -0
  182. package/docs/DATA_SOURCES.md +69 -0
  183. package/docs/INTEGRATION.md +58 -0
  184. package/eslint.config.js +52 -0
  185. package/jest.config.js +40 -0
  186. package/package.json +78 -0
  187. package/src/__tests__/integration/brand-generation.test.ts +84 -0
  188. package/src/__tests__/integration/mcp-server.test.ts +18 -0
  189. package/src/__tests__/unit/ai-interpreter.test.ts +172 -0
  190. package/src/__tests__/unit/border-system.test.ts +77 -0
  191. package/src/__tests__/unit/color-palette.test.ts +161 -0
  192. package/src/__tests__/unit/contrast-checker.test.ts +124 -0
  193. package/src/__tests__/unit/design-tokens.test.ts +184 -0
  194. package/src/__tests__/unit/favicon-generator.test.ts +80 -0
  195. package/src/__tests__/unit/gradient-system.test.ts +122 -0
  196. package/src/__tests__/unit/logo-generator.test.ts +146 -0
  197. package/src/__tests__/unit/motion-system.test.ts +91 -0
  198. package/src/__tests__/unit/og-image-generator.test.ts +115 -0
  199. package/src/__tests__/unit/shadow-system.test.ts +63 -0
  200. package/src/__tests__/unit/spacing-scale.test.ts +60 -0
  201. package/src/__tests__/unit/typography-system.test.ts +71 -0
  202. package/src/index.ts +59 -0
  203. package/src/lib/branding-core/ai/brand-interpreter.ts +30 -0
  204. package/src/lib/branding-core/ai/claude-interpreter.ts +76 -0
  205. package/src/lib/branding-core/ai/intent-applier.ts +59 -0
  206. package/src/lib/branding-core/ai/keyword-interpreter.ts +95 -0
  207. package/src/lib/branding-core/ai/prompts.ts +93 -0
  208. package/src/lib/branding-core/ai/types.ts +36 -0
  209. package/src/lib/branding-core/documents/html-generator.ts +32 -0
  210. package/src/lib/branding-core/documents/pdf-generator.ts +21 -0
  211. package/src/lib/branding-core/exporters/css-variables.ts +71 -0
  212. package/src/lib/branding-core/exporters/design-tokens.ts +86 -0
  213. package/src/lib/branding-core/exporters/figma-tokens.ts +87 -0
  214. package/src/lib/branding-core/exporters/react-theme.ts +69 -0
  215. package/src/lib/branding-core/exporters/sass-variables.ts +74 -0
  216. package/src/lib/branding-core/exporters/tailwind-preset.ts +67 -0
  217. package/src/lib/branding-core/generators/border-system.ts +41 -0
  218. package/src/lib/branding-core/generators/color-palette.ts +147 -0
  219. package/src/lib/branding-core/generators/favicon-generator.ts +33 -0
  220. package/src/lib/branding-core/generators/gradient-system.ts +120 -0
  221. package/src/lib/branding-core/generators/logo-generator.ts +152 -0
  222. package/src/lib/branding-core/generators/motion-system.ts +98 -0
  223. package/src/lib/branding-core/generators/og-image-generator.ts +97 -0
  224. package/src/lib/branding-core/generators/shadow-system.ts +66 -0
  225. package/src/lib/branding-core/generators/spacing-scale.ts +29 -0
  226. package/src/lib/branding-core/generators/typography-system.ts +128 -0
  227. package/src/lib/branding-core/index.ts +28 -0
  228. package/src/lib/branding-core/validators/brand-consistency.ts +79 -0
  229. package/src/lib/branding-core/validators/contrast-checker.ts +37 -0
  230. package/src/lib/branding-core/validators/token-schema.ts +50 -0
  231. package/src/lib/config.ts +13 -0
  232. package/src/lib/logger.ts +12 -0
  233. package/src/lib/types.ts +236 -0
  234. package/src/resources/brand-knowledge.ts +60 -0
  235. package/src/resources/brand-templates.ts +70 -0
  236. package/src/tools/create-brand-guidelines.ts +94 -0
  237. package/src/tools/export-design-tokens.ts +52 -0
  238. package/src/tools/generate-brand-assets.ts +48 -0
  239. package/src/tools/generate-brand-identity.ts +115 -0
  240. package/src/tools/generate-color-palette.ts +43 -0
  241. package/src/tools/generate-typography-system.ts +42 -0
  242. package/src/tools/refine-brand-element.ts +65 -0
  243. package/src/tools/validate-brand-consistency.ts +32 -0
  244. package/tsconfig.json +21 -0
@@ -0,0 +1,60 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+
3
+ const COLOR_THEORY = {
4
+ harmonies: {
5
+ complementary: 'Colors opposite on the color wheel. High contrast, vibrant.',
6
+ analogous: 'Colors adjacent on the wheel. Harmonious, low contrast.',
7
+ triadic: 'Three colors equally spaced (120 degrees). Balanced and colorful.',
8
+ 'split-complementary': 'Base + two colors adjacent to its complement. Softer contrast.',
9
+ tetradic: 'Four colors forming a rectangle. Rich palette, needs balance.',
10
+ monochromatic: 'Single hue with varied lightness/saturation. Cohesive and elegant.',
11
+ },
12
+ psychology: {
13
+ red: 'Energy, passion, urgency. Use for CTAs and alerts.',
14
+ blue: 'Trust, stability, professionalism. Common in tech and finance.',
15
+ green: 'Growth, health, nature. Used in wellness and sustainability.',
16
+ purple: 'Creativity, luxury, wisdom. Premium and creative brands.',
17
+ orange: 'Enthusiasm, confidence, warmth. Energetic and approachable.',
18
+ yellow: 'Optimism, clarity, warmth. Attention-grabbing accents.',
19
+ black: 'Sophistication, power, elegance. Luxury and editorial.',
20
+ white: 'Simplicity, cleanliness, space. Minimalist design.',
21
+ },
22
+ accessibility: {
23
+ wcagAA: 'Minimum 4.5:1 contrast ratio for normal text',
24
+ wcagAALarge: 'Minimum 3:1 for large text (18px+ or 14px+ bold)',
25
+ wcagAAA: 'Enhanced 7:1 contrast ratio for normal text',
26
+ },
27
+ };
28
+
29
+ const TYPOGRAPHY_RULES = {
30
+ scales: {
31
+ 'minor-second': { ratio: 1.067, use: 'Very tight, dense interfaces' },
32
+ 'major-second': { ratio: 1.125, use: 'Compact, functional UIs' },
33
+ 'minor-third': { ratio: 1.2, use: 'General purpose, most common' },
34
+ 'major-third': { ratio: 1.25, use: 'Marketing, editorial content' },
35
+ 'perfect-fourth': { ratio: 1.333, use: 'Bold hierarchies, headlines' },
36
+ 'golden-ratio': { ratio: 1.618, use: 'Dramatic, artistic layouts' },
37
+ },
38
+ pairingPrinciples: [
39
+ 'Contrast serif/sans-serif for heading/body distinction',
40
+ 'Limit to 2-3 fonts maximum per project',
41
+ 'Ensure x-height similarity for optical consistency',
42
+ 'Match historical period and cultural context',
43
+ ],
44
+ };
45
+
46
+ export function registerBrandKnowledge(server: McpServer): void {
47
+ server.resource('brand-knowledge', 'brand://knowledge', async () => ({
48
+ contents: [
49
+ {
50
+ uri: 'brand://knowledge',
51
+ text: JSON.stringify(
52
+ { colorTheory: COLOR_THEORY, typographyRules: TYPOGRAPHY_RULES },
53
+ null,
54
+ 2
55
+ ),
56
+ mimeType: 'application/json',
57
+ },
58
+ ],
59
+ }));
60
+ }
@@ -0,0 +1,70 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+
3
+ const TEMPLATES = [
4
+ {
5
+ id: 'tech-startup',
6
+ name: 'Tech Startup',
7
+ style: 'tech',
8
+ baseColor: '#6B4CE6',
9
+ harmony: 'complementary',
10
+ headingCategory: 'sans-serif',
11
+ bodyCategory: 'sans-serif',
12
+ },
13
+ {
14
+ id: 'luxury-brand',
15
+ name: 'Luxury Brand',
16
+ style: 'elegant',
17
+ baseColor: '#1A1A2E',
18
+ harmony: 'analogous',
19
+ headingCategory: 'serif',
20
+ bodyCategory: 'serif',
21
+ },
22
+ {
23
+ id: 'health-wellness',
24
+ name: 'Health & Wellness',
25
+ style: 'organic',
26
+ baseColor: '#2D6A4F',
27
+ harmony: 'analogous',
28
+ headingCategory: 'serif',
29
+ bodyCategory: 'sans-serif',
30
+ },
31
+ {
32
+ id: 'creative-agency',
33
+ name: 'Creative Agency',
34
+ style: 'bold',
35
+ baseColor: '#FF6B35',
36
+ harmony: 'triadic',
37
+ headingCategory: 'display',
38
+ bodyCategory: 'sans-serif',
39
+ },
40
+ {
41
+ id: 'fintech',
42
+ name: 'Fintech',
43
+ style: 'corporate',
44
+ baseColor: '#0052CC',
45
+ harmony: 'complementary',
46
+ headingCategory: 'sans-serif',
47
+ bodyCategory: 'sans-serif',
48
+ },
49
+ {
50
+ id: 'education',
51
+ name: 'Education',
52
+ style: 'playful',
53
+ baseColor: '#7C3AED',
54
+ harmony: 'split-complementary',
55
+ headingCategory: 'display',
56
+ bodyCategory: 'sans-serif',
57
+ },
58
+ ];
59
+
60
+ export function registerBrandTemplates(server: McpServer): void {
61
+ server.resource('brand-templates', 'brand://templates', async () => ({
62
+ contents: [
63
+ {
64
+ uri: 'brand://templates',
65
+ text: JSON.stringify(TEMPLATES, null, 2),
66
+ mimeType: 'application/json',
67
+ },
68
+ ],
69
+ }));
70
+ }
@@ -0,0 +1,94 @@
1
+ import { z } from 'zod';
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { brandDocFormatSchema } from '../lib/branding-core/validators/token-schema.js';
4
+ import type { BrandIdentity } from '../lib/types.js';
5
+ import { logger } from '../lib/logger.js';
6
+
7
+ function generateHtmlGuidelines(brand: BrandIdentity): string {
8
+ const { colors, typography } = brand;
9
+ return `<!DOCTYPE html>
10
+ <html lang="en">
11
+ <head>
12
+ <meta charset="UTF-8">
13
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
14
+ <title>${brand.name} - Brand Guidelines</title>
15
+ <style>
16
+ body { font-family: '${typography.bodyFont}', sans-serif; max-width: 960px; margin: 0 auto; padding: 2rem; color: #1a1a1a; }
17
+ h1, h2, h3 { font-family: '${typography.headingFont}', sans-serif; }
18
+ .swatch { display: inline-block; width: 80px; height: 80px; border-radius: 8px; margin: 4px; }
19
+ .color-label { font-size: 12px; text-align: center; margin-top: 4px; }
20
+ .section { margin: 2rem 0; padding: 1.5rem; border: 1px solid #e0e0e0; border-radius: 8px; }
21
+ </style>
22
+ </head>
23
+ <body>
24
+ <h1>${brand.name} Brand Guidelines</h1>
25
+ ${brand.tagline ? `<p><em>${brand.tagline}</em></p>` : ''}
26
+
27
+ <div class="section">
28
+ <h2>Color Palette</h2>
29
+ <div>
30
+ <div><div class="swatch" style="background:${colors.primary.hex}"></div><div class="color-label">Primary<br>${colors.primary.hex}</div></div>
31
+ <div><div class="swatch" style="background:${colors.secondary.hex}"></div><div class="color-label">Secondary<br>${colors.secondary.hex}</div></div>
32
+ <div><div class="swatch" style="background:${colors.accent.hex}"></div><div class="color-label">Accent<br>${colors.accent.hex}</div></div>
33
+ </div>
34
+ <h3>Neutrals</h3>
35
+ <div>${colors.neutral.map((n) => `<div style="display:inline-block"><div class="swatch" style="background:${n.hex}"></div><div class="color-label">${n.name}<br>${n.hex}</div></div>`).join('')}</div>
36
+ </div>
37
+
38
+ <div class="section">
39
+ <h2>Typography</h2>
40
+ <p><strong>Heading:</strong> ${typography.headingFont}</p>
41
+ <p><strong>Body:</strong> ${typography.bodyFont}</p>
42
+ <p><strong>Mono:</strong> ${typography.monoFont}</p>
43
+ <h3>Type Scale</h3>
44
+ ${typography.steps.map((s) => `<p style="font-size:${s.size};line-height:${s.lineHeight};font-weight:${s.weight}">${s.name} — ${s.size}</p>`).join('\n ')}
45
+ </div>
46
+
47
+ <div class="section">
48
+ <h2>Logo</h2>
49
+ ${brand.logo?.svg ? brand.logo.svg : '<p>Logo not generated</p>'}
50
+ </div>
51
+
52
+ <footer><p>Generated by @forgespace/branding-mcp</p></footer>
53
+ </body>
54
+ </html>`;
55
+ }
56
+
57
+ export function registerCreateBrandGuidelines(server: McpServer): void {
58
+ server.tool(
59
+ 'create_brand_guidelines',
60
+ 'Generate a brand guidelines document (HTML brand book) from a brand identity. Includes color swatches, typography samples, logo, and usage rules.',
61
+ {
62
+ brand: z.string().describe('Full BrandIdentity JSON'),
63
+ format: brandDocFormatSchema.optional().describe('Output format (html supported)'),
64
+ },
65
+ async ({ brand, format }) => {
66
+ try {
67
+ logger.info({ format }, 'Creating brand guidelines');
68
+ const brandData: BrandIdentity = JSON.parse(brand);
69
+
70
+ if (format === 'pdf') {
71
+ return {
72
+ content: [
73
+ {
74
+ type: 'text',
75
+ text: 'PDF generation requires pdfkit. Use HTML format or install optional dependencies.',
76
+ },
77
+ ],
78
+ };
79
+ }
80
+
81
+ const html = generateHtmlGuidelines(brandData);
82
+ return {
83
+ content: [{ type: 'text', text: html }],
84
+ };
85
+ } catch (error) {
86
+ const message = error instanceof Error ? error.message : String(error);
87
+ return {
88
+ content: [{ type: 'text', text: `Error creating guidelines: ${message}` }],
89
+ isError: true,
90
+ };
91
+ }
92
+ }
93
+ );
94
+ }
@@ -0,0 +1,52 @@
1
+ import { z } from 'zod';
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import {
4
+ exportDesignTokens,
5
+ exportCssVariables,
6
+ exportTailwindPreset,
7
+ exportFigmaTokens,
8
+ exportReactTheme,
9
+ exportSassVariables,
10
+ } from '../lib/branding-core/index.js';
11
+ import { exportFormatSchema } from '../lib/branding-core/validators/token-schema.js';
12
+ import type { BrandIdentity, ExportFormat } from '../lib/types.js';
13
+ import { logger } from '../lib/logger.js';
14
+
15
+ const EXPORTERS: Record<ExportFormat, (brand: BrandIdentity) => string | object> = {
16
+ json: exportDesignTokens,
17
+ css: exportCssVariables,
18
+ tailwind: exportTailwindPreset,
19
+ figma: exportFigmaTokens,
20
+ react: exportReactTheme,
21
+ sass: exportSassVariables,
22
+ };
23
+
24
+ export function registerExportDesignTokens(server: McpServer): void {
25
+ server.tool(
26
+ 'export_design_tokens',
27
+ 'Export a brand identity as design tokens in various formats: W3C JSON, CSS custom properties, Tailwind preset, Figma tokens, React theme, or Sass variables.',
28
+ {
29
+ brand: z.string().describe('Full BrandIdentity JSON (from generate_brand_identity output)'),
30
+ format: exportFormatSchema.describe('Export format'),
31
+ },
32
+ async ({ brand, format }) => {
33
+ try {
34
+ logger.info({ format }, 'Exporting design tokens');
35
+ const brandData: BrandIdentity = JSON.parse(brand);
36
+ const exporter = EXPORTERS[format];
37
+ const result = exporter(brandData);
38
+ const output = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
39
+
40
+ return {
41
+ content: [{ type: 'text', text: output }],
42
+ };
43
+ } catch (error) {
44
+ const message = error instanceof Error ? error.message : String(error);
45
+ return {
46
+ content: [{ type: 'text', text: `Error exporting tokens: ${message}` }],
47
+ isError: true,
48
+ };
49
+ }
50
+ }
51
+ );
52
+ }
@@ -0,0 +1,48 @@
1
+ import { z } from 'zod';
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { generateFavicons, generateOgImage } from '../lib/branding-core/index.js';
4
+ import type { BrandIdentity } from '../lib/types.js';
5
+ import { logger } from '../lib/logger.js';
6
+
7
+ const ogTemplateSchema = z.enum(['default', 'article', 'social']);
8
+
9
+ export function registerGenerateBrandAssets(server: McpServer): void {
10
+ server.tool(
11
+ 'generate_brand_assets',
12
+ 'Generate brand assets (favicons, OG images) from an existing brand identity JSON.',
13
+ {
14
+ brand: z
15
+ .string()
16
+ .min(1)
17
+ .describe('JSON string of BrandIdentity from generate_brand_identity'),
18
+ ogTemplate: ogTemplateSchema
19
+ .optional()
20
+ .describe('OG image template: default, article, or social'),
21
+ ogTitle: z.string().max(200).optional().describe('Custom OG image title'),
22
+ ogSubtitle: z.string().max(200).optional().describe('Custom OG image subtitle'),
23
+ },
24
+ async ({ brand: brandJson, ogTemplate, ogTitle, ogSubtitle }) => {
25
+ try {
26
+ const brand: BrandIdentity = JSON.parse(brandJson);
27
+ logger.info({ brandName: brand.name }, 'Generating brand assets');
28
+
29
+ const iconSvg = brand.logo?.variants?.icon ?? brand.logo?.svg ?? '';
30
+ const favicons = iconSvg ? generateFavicons(iconSvg, brand.colors.primary.hex) : null;
31
+
32
+ const ogImage = generateOgImage(brand, ogTemplate ?? 'default', ogTitle, ogSubtitle);
33
+
34
+ const result = { favicons, ogImage };
35
+
36
+ return {
37
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
38
+ };
39
+ } catch (error) {
40
+ const message = error instanceof Error ? error.message : String(error);
41
+ return {
42
+ content: [{ type: 'text', text: `Error generating assets: ${message}` }],
43
+ isError: true,
44
+ };
45
+ }
46
+ }
47
+ );
48
+ }
@@ -0,0 +1,115 @@
1
+ import { z } from 'zod';
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import {
4
+ generateColorPalette,
5
+ generateTypographySystem,
6
+ generateSpacingScale,
7
+ generateShadowSystem,
8
+ generateBorderSystem,
9
+ generateMotionSystem,
10
+ generateGradientSystem,
11
+ generateSvgLogo,
12
+ defaultLogoConfig,
13
+ } from '../lib/branding-core/index.js';
14
+ import {
15
+ brandStyleSchema,
16
+ colorHarmonySchema,
17
+ colorThemeSchema,
18
+ fontCategorySchema,
19
+ hexColorSchema,
20
+ typeScaleRatioSchema,
21
+ } from '../lib/branding-core/validators/token-schema.js';
22
+ import type { BrandIdentity, BrandStyle, FontCategory } from '../lib/types.js';
23
+ import { logger } from '../lib/logger.js';
24
+
25
+ const STYLE_DEFAULTS: Record<BrandStyle, { heading: FontCategory; body: FontCategory }> = {
26
+ minimal: { heading: 'sans-serif', body: 'sans-serif' },
27
+ bold: { heading: 'display', body: 'sans-serif' },
28
+ elegant: { heading: 'serif', body: 'serif' },
29
+ playful: { heading: 'display', body: 'sans-serif' },
30
+ corporate: { heading: 'sans-serif', body: 'sans-serif' },
31
+ tech: { heading: 'sans-serif', body: 'monospace' },
32
+ organic: { heading: 'serif', body: 'sans-serif' },
33
+ retro: { heading: 'display', body: 'serif' },
34
+ };
35
+
36
+ export function registerGenerateBrandIdentity(server: McpServer): void {
37
+ server.tool(
38
+ 'generate_brand_identity',
39
+ 'Generate a complete brand identity including colors, typography, spacing, and logo. Provide a brand name and style preferences to get a cohesive identity system.',
40
+ {
41
+ brandName: z.string().min(1).max(100).describe('Brand name'),
42
+ industry: z.string().min(1).max(100).describe('Industry or sector (e.g. "tech", "health")'),
43
+ style: brandStyleSchema.describe('Visual style direction'),
44
+ tagline: z.string().max(200).optional().describe('Brand tagline'),
45
+ baseColor: hexColorSchema.optional().describe('Base color preference'),
46
+ harmony: colorHarmonySchema.optional().describe('Color harmony type'),
47
+ theme: colorThemeSchema.optional().describe('Light/dark/both'),
48
+ headingCategory: fontCategorySchema.optional().describe('Heading font category'),
49
+ bodyCategory: fontCategorySchema.optional().describe('Body font category'),
50
+ scaleRatio: typeScaleRatioSchema.optional().describe('Typography scale ratio'),
51
+ },
52
+ async ({
53
+ brandName,
54
+ industry,
55
+ style,
56
+ tagline,
57
+ baseColor,
58
+ harmony,
59
+ theme,
60
+ headingCategory,
61
+ bodyCategory,
62
+ scaleRatio,
63
+ }) => {
64
+ try {
65
+ logger.info({ brandName, industry, style }, 'Generating brand identity');
66
+
67
+ const defaults = STYLE_DEFAULTS[style];
68
+ const colors = generateColorPalette(baseColor, harmony ?? 'complementary', theme);
69
+ const typography = generateTypographySystem(
70
+ headingCategory ?? defaults.heading,
71
+ bodyCategory ?? defaults.body,
72
+ scaleRatio ?? 'major-third'
73
+ );
74
+ const spacing = generateSpacingScale();
75
+ const shadows = generateShadowSystem(colors.primary.hex, theme);
76
+ const borders = generateBorderSystem(style);
77
+ const motion = generateMotionSystem(style);
78
+ const gradients = generateGradientSystem(colors, style);
79
+ const logoConfig = {
80
+ ...defaultLogoConfig(brandName, colors.primary.hex),
81
+ font: typography.headingFont,
82
+ style,
83
+ };
84
+ const logo = generateSvgLogo(logoConfig);
85
+
86
+ const identity: BrandIdentity = {
87
+ id: `brand_${Date.now().toString(36)}`,
88
+ name: brandName,
89
+ tagline,
90
+ industry,
91
+ style,
92
+ colors,
93
+ typography,
94
+ spacing,
95
+ shadows,
96
+ borders,
97
+ motion,
98
+ gradients,
99
+ logo,
100
+ createdAt: new Date().toISOString(),
101
+ };
102
+
103
+ return {
104
+ content: [{ type: 'text', text: JSON.stringify(identity, null, 2) }],
105
+ };
106
+ } catch (error) {
107
+ const message = error instanceof Error ? error.message : String(error);
108
+ return {
109
+ content: [{ type: 'text', text: `Error generating brand: ${message}` }],
110
+ isError: true,
111
+ };
112
+ }
113
+ }
114
+ );
115
+ }
@@ -0,0 +1,43 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { generateColorPalette } from '../lib/branding-core/index.js';
3
+ import {
4
+ colorHarmonySchema,
5
+ colorThemeSchema,
6
+ hexColorSchema,
7
+ } from '../lib/branding-core/validators/token-schema.js';
8
+ import { logger } from '../lib/logger.js';
9
+
10
+ export function registerGenerateColorPalette(server: McpServer): void {
11
+ server.tool(
12
+ 'generate_color_palette',
13
+ 'Generate a harmonious color palette with WCAG contrast validation. Supports complementary, analogous, triadic, split-complementary, tetradic, and monochromatic harmonies.',
14
+ {
15
+ baseColor: hexColorSchema
16
+ .optional()
17
+ .describe('Base hex color to build palette from (e.g. #6B4CE6)'),
18
+ harmony: colorHarmonySchema.optional().describe('Color harmony type'),
19
+ theme: colorThemeSchema.optional().describe('Light, dark, or both neutral scales'),
20
+ },
21
+ async ({ baseColor, harmony, theme }) => {
22
+ try {
23
+ logger.info({ baseColor, harmony, theme }, 'Generating color palette');
24
+ const palette = generateColorPalette(baseColor, harmony, theme);
25
+
26
+ return {
27
+ content: [
28
+ {
29
+ type: 'text',
30
+ text: JSON.stringify(palette, null, 2),
31
+ },
32
+ ],
33
+ };
34
+ } catch (error) {
35
+ const message = error instanceof Error ? error.message : String(error);
36
+ return {
37
+ content: [{ type: 'text', text: `Error generating palette: ${message}` }],
38
+ isError: true,
39
+ };
40
+ }
41
+ }
42
+ );
43
+ }
@@ -0,0 +1,42 @@
1
+ import { z } from 'zod';
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { generateTypographySystem } from '../lib/branding-core/index.js';
4
+ import {
5
+ fontCategorySchema,
6
+ typeScaleRatioSchema,
7
+ } from '../lib/branding-core/validators/token-schema.js';
8
+ import { logger } from '../lib/logger.js';
9
+
10
+ export function registerGenerateTypographySystem(server: McpServer): void {
11
+ server.tool(
12
+ 'generate_typography_system',
13
+ 'Generate a typography system with font pairing, modular type scale, and line heights. Uses curated font pairings for visual harmony.',
14
+ {
15
+ headingCategory: fontCategorySchema.optional().describe('Font category for headings'),
16
+ bodyCategory: fontCategorySchema.optional().describe('Font category for body text'),
17
+ scaleRatio: typeScaleRatioSchema.optional().describe('Modular scale ratio'),
18
+ baseSize: z.number().min(12).max(24).optional().describe('Base font size in pixels'),
19
+ },
20
+ async ({ headingCategory, bodyCategory, scaleRatio, baseSize }) => {
21
+ try {
22
+ logger.info({ headingCategory, bodyCategory, scaleRatio }, 'Generating typography system');
23
+ const system = generateTypographySystem(
24
+ headingCategory,
25
+ bodyCategory,
26
+ scaleRatio,
27
+ baseSize
28
+ );
29
+
30
+ return {
31
+ content: [{ type: 'text', text: JSON.stringify(system, null, 2) }],
32
+ };
33
+ } catch (error) {
34
+ const message = error instanceof Error ? error.message : String(error);
35
+ return {
36
+ content: [{ type: 'text', text: `Error generating typography: ${message}` }],
37
+ isError: true,
38
+ };
39
+ }
40
+ }
41
+ );
42
+ }
@@ -0,0 +1,65 @@
1
+ import { z } from 'zod';
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { interpretFeedback, applyIntent } from '../lib/branding-core/index.js';
4
+ import type { BrandIdentity } from '../lib/types.js';
5
+ import type { InterpreterStrategy } from '../lib/branding-core/index.js';
6
+ import { loadConfig } from '../lib/config.js';
7
+ import { logger } from '../lib/logger.js';
8
+
9
+ export function registerRefineBrandElement(server: McpServer): void {
10
+ server.tool(
11
+ 'refine_brand_element',
12
+ 'Refine a specific element of an existing brand identity using natural language feedback. Uses AI interpretation when available, keyword matching as fallback.',
13
+ {
14
+ brand: z.string().describe('Full BrandIdentity JSON'),
15
+ element: z.enum(['colors', 'typography', 'spacing']).describe('Element to refine'),
16
+ feedback: z
17
+ .string()
18
+ .describe(
19
+ 'Natural language feedback (e.g. "make it feel more premium and understated", "use serif headings with dramatic scale")'
20
+ ),
21
+ strategy: z
22
+ .enum(['keyword', 'ai', 'auto'])
23
+ .optional()
24
+ .describe(
25
+ 'Interpretation strategy: keyword (fast), ai (Claude API), auto (ai if key available)'
26
+ ),
27
+ },
28
+ async ({ brand, element, feedback, strategy }) => {
29
+ try {
30
+ logger.info({ element, feedback, strategy }, 'Refining brand element');
31
+ const brandData: BrandIdentity = JSON.parse(brand);
32
+ const config = loadConfig();
33
+
34
+ const intent = await interpretFeedback(
35
+ feedback,
36
+ element,
37
+ brandData,
38
+ (strategy as InterpreterStrategy) ?? 'auto',
39
+ { anthropicApiKey: config.anthropicApiKey }
40
+ );
41
+
42
+ const refined = applyIntent(brandData, intent);
43
+
44
+ return {
45
+ content: [
46
+ {
47
+ type: 'text',
48
+ text: JSON.stringify(
49
+ { ...refined, _interpretation: { strategy: strategy ?? 'auto', ...intent } },
50
+ null,
51
+ 2
52
+ ),
53
+ },
54
+ ],
55
+ };
56
+ } catch (error) {
57
+ const message = error instanceof Error ? error.message : String(error);
58
+ return {
59
+ content: [{ type: 'text', text: `Error refining element: ${message}` }],
60
+ isError: true,
61
+ };
62
+ }
63
+ }
64
+ );
65
+ }
@@ -0,0 +1,32 @@
1
+ import { z } from 'zod';
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { validateBrandConsistency } from '../lib/branding-core/index.js';
4
+ import type { BrandIdentity } from '../lib/types.js';
5
+ import { logger } from '../lib/logger.js';
6
+
7
+ export function registerValidateBrandConsistency(server: McpServer): void {
8
+ server.tool(
9
+ 'validate_brand_consistency',
10
+ 'Validate a brand identity for completeness, WCAG contrast compliance, and typography best practices. Returns a score (0-100) and actionable issues.',
11
+ {
12
+ brand: z.string().describe('Full BrandIdentity JSON to validate'),
13
+ },
14
+ async ({ brand }) => {
15
+ try {
16
+ logger.info('Validating brand consistency');
17
+ const brandData: BrandIdentity = JSON.parse(brand);
18
+ const result = validateBrandConsistency(brandData);
19
+
20
+ return {
21
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
22
+ };
23
+ } catch (error) {
24
+ const message = error instanceof Error ? error.message : String(error);
25
+ return {
26
+ content: [{ type: 'text', text: `Error validating brand: ${message}` }],
27
+ isError: true,
28
+ };
29
+ }
30
+ }
31
+ );
32
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022"],
5
+ "module": "NodeNext",
6
+ "moduleResolution": "NodeNext",
7
+ "strict": true,
8
+ "declaration": true,
9
+ "declarationMap": true,
10
+ "sourceMap": true,
11
+ "outDir": "./dist",
12
+ "rootDir": "./src",
13
+ "esModuleInterop": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "skipLibCheck": true,
16
+ "resolveJsonModule": true,
17
+ "isolatedModules": true
18
+ },
19
+ "include": ["src/**/*.ts"],
20
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
21
+ }