@cobwds/mcp-server 1.19.3 → 1.23.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 (36) hide show
  1. package/README.md +6 -15
  2. package/data/cem/custom-elements.json +10084 -6696
  3. package/data/frameworks.json +14 -0
  4. package/data/guides/form-validation.md +1 -1
  5. package/data/guides/frameworks/angular.md +184 -26
  6. package/data/guides/frameworks/react-additions.md +69 -0
  7. package/data/guides/frameworks/react.md +209 -27
  8. package/data/guides/frameworks/vue.md +356 -0
  9. package/data/tokens/tokens.css +45 -56
  10. package/data/tokens/tokens.json +39 -78
  11. package/dist/index.js +0 -0
  12. package/dist/lib/cem-parser.d.ts +12 -0
  13. package/dist/lib/cem-parser.d.ts.map +1 -1
  14. package/dist/lib/framework-snippets.d.ts +36 -0
  15. package/dist/lib/framework-snippets.d.ts.map +1 -0
  16. package/dist/lib/framework-snippets.js +55 -0
  17. package/dist/lib/framework-usage.d.ts +20 -0
  18. package/dist/lib/framework-usage.d.ts.map +1 -0
  19. package/dist/lib/framework-usage.js +50 -0
  20. package/dist/lib/frameworks-data.d.ts +19 -0
  21. package/dist/lib/frameworks-data.d.ts.map +1 -0
  22. package/dist/lib/frameworks-data.js +40 -0
  23. package/dist/resources/frameworks.d.ts +15 -0
  24. package/dist/resources/frameworks.d.ts.map +1 -0
  25. package/dist/resources/frameworks.js +104 -0
  26. package/dist/resources/guides.d.ts.map +1 -1
  27. package/dist/resources/guides.js +12 -1
  28. package/dist/resources/index.d.ts.map +1 -1
  29. package/dist/resources/index.js +2 -0
  30. package/dist/tools/component-tools.d.ts.map +1 -1
  31. package/dist/tools/component-tools.js +20 -5
  32. package/dist/tools/guide-tools.js +1 -1
  33. package/dist/tools/utility-tools.d.ts +48 -0
  34. package/dist/tools/utility-tools.d.ts.map +1 -1
  35. package/dist/tools/utility-tools.js +236 -71
  36. package/package.json +6 -4
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Framework Resources
3
+ *
4
+ * MCP resources for COBWDS framework packages (@cobwds/react, @cobwds/vue,
5
+ * @cobwds/angular).
6
+ *
7
+ * Resources:
8
+ * - cobwds://frameworks - Index of framework packages with version and guide URI
9
+ * - cobwds://frameworks/react - @cobwds/react guide (synced from its README)
10
+ * - cobwds://frameworks/vue - @cobwds/vue guide (synced from its README)
11
+ * - cobwds://frameworks/angular - @cobwds/angular guide (synced from its README)
12
+ */
13
+ import { readFileSync } from "node:fs";
14
+ import { join, dirname } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+ import { getFrameworksIndex } from "../lib/frameworks-data.js";
17
+ const __filename = fileURLToPath(import.meta.url);
18
+ const __dirname = dirname(__filename);
19
+ const GUIDES_DIR = join(__dirname, "../../data/guides/frameworks");
20
+ function loadFrameworkGuide(framework) {
21
+ try {
22
+ return readFileSync(join(GUIDES_DIR, `${framework}.md`), "utf-8");
23
+ }
24
+ catch {
25
+ return `Framework guide not found: ${framework}. Run "npm run sync:guides -w @cobwds/mcp-server".`;
26
+ }
27
+ }
28
+ export function registerFrameworkResources(server) {
29
+ // cobwds://frameworks - Index of framework packages
30
+ server.resource("frameworks", "cobwds://frameworks", {
31
+ description: "Index of COBWDS framework packages (@cobwds/react, @cobwds/vue, @cobwds/angular) with their published version and guide resource URI",
32
+ mimeType: "application/json",
33
+ }, async () => {
34
+ const index = getFrameworksIndex();
35
+ const list = [
36
+ {
37
+ id: "react",
38
+ packageName: index.react.packageName,
39
+ version: index.react.version,
40
+ guideUri: "cobwds://frameworks/react",
41
+ },
42
+ {
43
+ id: "vue",
44
+ packageName: index.vue.packageName,
45
+ version: index.vue.version,
46
+ guideUri: "cobwds://frameworks/vue",
47
+ },
48
+ {
49
+ id: "angular",
50
+ packageName: index.angular.packageName,
51
+ version: index.angular.version,
52
+ guideUri: "cobwds://frameworks/angular",
53
+ },
54
+ ];
55
+ return {
56
+ contents: [
57
+ {
58
+ uri: "cobwds://frameworks",
59
+ mimeType: "application/json",
60
+ text: JSON.stringify(list, null, 2),
61
+ },
62
+ ],
63
+ };
64
+ });
65
+ // cobwds://frameworks/react - @cobwds/react guide
66
+ server.resource("frameworks-react", "cobwds://frameworks/react", {
67
+ description: "@cobwds/react install, usage, forms, SSR, and troubleshooting guide",
68
+ mimeType: "text/markdown",
69
+ }, async () => ({
70
+ contents: [
71
+ {
72
+ uri: "cobwds://frameworks/react",
73
+ mimeType: "text/markdown",
74
+ text: loadFrameworkGuide("react"),
75
+ },
76
+ ],
77
+ }));
78
+ // cobwds://frameworks/vue - @cobwds/vue guide
79
+ server.resource("frameworks-vue", "cobwds://frameworks/vue", {
80
+ description: "@cobwds/vue install, usage, v-model forms, SSR, and troubleshooting guide",
81
+ mimeType: "text/markdown",
82
+ }, async () => ({
83
+ contents: [
84
+ {
85
+ uri: "cobwds://frameworks/vue",
86
+ mimeType: "text/markdown",
87
+ text: loadFrameworkGuide("vue"),
88
+ },
89
+ ],
90
+ }));
91
+ // cobwds://frameworks/angular - @cobwds/angular guide
92
+ server.resource("frameworks-angular", "cobwds://frameworks/angular", {
93
+ description: "@cobwds/angular install, usage, forms, SSR, and troubleshooting guide",
94
+ mimeType: "text/markdown",
95
+ }, async () => ({
96
+ contents: [
97
+ {
98
+ uri: "cobwds://frameworks/angular",
99
+ mimeType: "text/markdown",
100
+ text: loadFrameworkGuide("angular"),
101
+ },
102
+ ],
103
+ }));
104
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"guides.d.ts","sourceRoot":"","sources":["../../src/resources/guides.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyE9D"}
1
+ {"version":3,"file":"guides.d.ts","sourceRoot":"","sources":["../../src/resources/guides.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoF9D"}
@@ -56,7 +56,18 @@ Then use them in HTML:
56
56
 
57
57
  ## Framework Integration
58
58
 
59
- For framework-specific setup, use the \`get_guide\` tool with \`topic: "framework"\` and a \`framework\` parameter (angular, react, dotnet, drupal, or vanilla).
59
+ For framework-specific setup, use the \`get_guide\` tool with a \`topic\` and a \`framework\` parameter (angular, react, vue, dotnet, drupal, or vanilla).
60
+
61
+ React, Vue, and Angular are first-class packages, not wrapper snippets:
62
+ \`@cobwds/react\` (\`npm install @cobwds/react\`), \`@cobwds/vue\`
63
+ (\`npm install @cobwds/vue\`), and \`@cobwds/angular\`
64
+ (\`npm install @cobwds/angular @cobwds/components\`) generate typed
65
+ components, props, and events directly from this design system's
66
+ manifest. See the \`cobwds://frameworks\` resource for their current
67
+ published versions, \`cobwds://frameworks/react\`, \`cobwds://frameworks/vue\`, and
68
+ \`cobwds://frameworks/angular\` for their full guides, and pass
69
+ \`framework: "react"\` or \`"angular"\` to \`get_component\` for
70
+ per-component import lines and framework-specific code examples.
60
71
 
61
72
  ## Resources
62
73
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAIzD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAKzD"}
@@ -6,8 +6,10 @@
6
6
  import { registerComponentResources } from "./components.js";
7
7
  import { registerTokenResources } from "./tokens.js";
8
8
  import { registerGuideResources } from "./guides.js";
9
+ import { registerFrameworkResources } from "./frameworks.js";
9
10
  export function registerResources(server) {
10
11
  registerComponentResources(server);
11
12
  registerTokenResources(server);
12
13
  registerGuideResources(server);
14
+ registerFrameworkResources(server);
13
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"component-tools.d.ts","sourceRoot":"","sources":["../../src/tools/component-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+G9D"}
1
+ {"version":3,"file":"component-tools.d.ts","sourceRoot":"","sources":["../../src/tools/component-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAYzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2I9D"}
@@ -10,6 +10,8 @@
10
10
  import { z } from "zod";
11
11
  import { getComponent, getAllComponents } from "../lib/cem-parser.js";
12
12
  import { searchComponents } from "../lib/search.js";
13
+ import { buildExampleSnippets, } from "../lib/framework-snippets.js";
14
+ import { buildAngularUsageNotes, buildReactUsageNotes, } from "../lib/framework-usage.js";
13
15
  export function registerComponentTools(server) {
14
16
  // find_components - Search or list all components
15
17
  server.tool("find_components", "Search for COBWDS components by name or description. Omit query to list all components.", {
@@ -51,15 +53,19 @@ export function registerComponentTools(server) {
51
53
  };
52
54
  });
53
55
  // get_component - Full documentation for a specific component
54
- server.tool("get_component", "Get full documentation for a specific COBWDS component including properties, events, slots, and CSS custom properties", {
56
+ server.tool("get_component", "Get full documentation for a specific COBWDS component including properties, events, slots, and CSS custom properties. Set framework to 'react' or 'angular' to get that framework's import line, event-prop naming, and forms guidance alongside HTML/React/Angular code examples.", {
55
57
  tagName: z
56
58
  .string()
57
59
  .describe("The tag name of the component (e.g., 'cob-button')"),
58
60
  includeExamples: z
59
61
  .boolean()
60
62
  .default(false)
61
- .describe("Include HTML code examples from component JSDoc. Set to true when you need usage patterns."),
62
- }, async ({ tagName, includeExamples }) => {
63
+ .describe("Include code examples from component JSDoc. Set to true when you need usage patterns. Each example carries html, react, and angular snippets."),
64
+ framework: z
65
+ .enum(["html", "react", "angular"])
66
+ .default("html")
67
+ .describe("Which framework to optimize the response for. 'html' (default) returns plain custom-element usage. 'react' and 'angular' add framework-specific usage notes (import line, event-prop naming, forms binding) and, for a form-control component, transform that framework's example snippets into its idiomatic controlled/reactive-forms pattern."),
68
+ }, async ({ tagName, includeExamples, framework }) => {
63
69
  const component = getComponent(tagName);
64
70
  if (!component) {
65
71
  return {
@@ -76,16 +82,25 @@ export function registerComponentTools(server) {
76
82
  // Attributes contains the HTML API, members duplicates this plus private methods
77
83
  const {
78
84
  // members: _members,
79
- examples, ...componentWithoutMembers } = component;
85
+ examples, formControl, ...componentWithoutMembers } = component;
86
+ const usage = {};
87
+ if (framework === "react") {
88
+ usage.react = buildReactUsageNotes(tagName, component.name, formControl);
89
+ }
90
+ else if (framework === "angular") {
91
+ usage.angular = buildAngularUsageNotes(tagName, component.name, formControl);
92
+ }
80
93
  return {
81
94
  content: [
82
95
  {
83
96
  type: "text",
84
97
  text: JSON.stringify({
85
98
  ...componentWithoutMembers,
99
+ formControl,
86
100
  examples: includeExamples && examples && examples.length > 0
87
- ? examples
101
+ ? buildExampleSnippets(examples, framework, formControl)
88
102
  : undefined,
103
+ usage: Object.keys(usage).length > 0 ? usage : undefined,
89
104
  resourceUri: `cobwds://component/${tagName}`,
90
105
  }, null, 2),
91
106
  },
@@ -56,7 +56,7 @@ export function registerGuideTools(server) {
56
56
  ])
57
57
  .describe("The guide topic to retrieve"),
58
58
  framework: z
59
- .enum(["angular", "react", "dotnet", "drupal", "vanilla"])
59
+ .enum(["angular", "react", "vue", "dotnet", "drupal", "vanilla"])
60
60
  .optional()
61
61
  .describe("When provided, returns framework-specific setup guide instead of the topic guide. Use with topic 'installation' to get framework install instructions."),
62
62
  }, async ({ topic, framework }) => {
@@ -2,7 +2,55 @@
2
2
  * Utility Tools
3
3
  *
4
4
  * MCP tools for COBWDS utility classes.
5
+ *
6
+ * The class lists this tool returns are RENDERED from the scale constants
7
+ * below. Those constants mirror the Sass sources that actually generate the
8
+ * stylesheet:
9
+ *
10
+ * - packages/styles/src/utilities/_config.scss ($spacing, $opacity-values,
11
+ * $zindex-values, $display-values,
12
+ * $breakpoints, $flex-columns)
13
+ * - packages/styles/src/utilities/_layout-grid.scss ($responsive-gap-suffixes)
14
+ * - packages/styles/src/core/typography.scss ($body-sizes, $ui-sizes,
15
+ * $ui-underline-styles, $display-sizes)
16
+ *
17
+ * Do not hand-write a class name into the markdown. Add it to a scale and let
18
+ * the renderer emit it, so a name can never appear here without a scale entry
19
+ * behind it.
20
+ *
21
+ * `npm run verify:utility-docs` compiles the stylesheet and asserts that every
22
+ * class this tool names exists in it. Run it after touching any scale.
5
23
  */
6
24
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
25
+ declare const UTILITY_DOCS: {
26
+ grid: string;
27
+ flex: string;
28
+ spacing: string;
29
+ display: string;
30
+ opacity: string;
31
+ zindex: string;
32
+ typography: string;
33
+ responsive: string;
34
+ componentSpacing: string;
35
+ };
36
+ /**
37
+ * Classes the reference deliberately names in order to say they do NOT exist.
38
+ *
39
+ * These are the names people reach for out of habit from other frameworks.
40
+ * Saying so explicitly is more useful than silence, but it means the docs
41
+ * mention class names the stylesheet does not define, which would otherwise
42
+ * trip the verifier.
43
+ *
44
+ * `verify-utility-docs.mjs` asserts each of these is genuinely absent, so if
45
+ * COBWDS ever adds one, the stale warning fails the check instead of quietly
46
+ * misinforming people.
47
+ */
48
+ declare const KNOWN_ABSENT: readonly string[];
49
+ /**
50
+ * Exported so `src/scripts/verify-utility-docs.mjs` can assert that every class
51
+ * named in this reference exists in the compiled stylesheet — and that every
52
+ * class named in KNOWN_ABSENT still does not.
53
+ */
54
+ export { UTILITY_DOCS, KNOWN_ABSENT };
7
55
  export declare function registerUtilityTools(server: McpServer): void;
8
56
  //# sourceMappingURL=utility-tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utility-tools.d.ts","sourceRoot":"","sources":["../../src/tools/utility-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmPzE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8D5D"}
1
+ {"version":3,"file":"utility-tools.d.ts","sourceRoot":"","sources":["../../src/tools/utility-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiLzE,QAAA,MAAM,YAAY;;;;;;;;;;CAyOjB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,YAAY,EAAE,SAAS,MAAM,EAUlC,CAAC;AAEF;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AAEtC,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8D5D"}
@@ -2,8 +2,150 @@
2
2
  * Utility Tools
3
3
  *
4
4
  * MCP tools for COBWDS utility classes.
5
+ *
6
+ * The class lists this tool returns are RENDERED from the scale constants
7
+ * below. Those constants mirror the Sass sources that actually generate the
8
+ * stylesheet:
9
+ *
10
+ * - packages/styles/src/utilities/_config.scss ($spacing, $opacity-values,
11
+ * $zindex-values, $display-values,
12
+ * $breakpoints, $flex-columns)
13
+ * - packages/styles/src/utilities/_layout-grid.scss ($responsive-gap-suffixes)
14
+ * - packages/styles/src/core/typography.scss ($body-sizes, $ui-sizes,
15
+ * $ui-underline-styles, $display-sizes)
16
+ *
17
+ * Do not hand-write a class name into the markdown. Add it to a scale and let
18
+ * the renderer emit it, so a name can never appear here without a scale entry
19
+ * behind it.
20
+ *
21
+ * `npm run verify:utility-docs` compiles the stylesheet and asserts that every
22
+ * class this tool names exists in it. Run it after touching any scale.
5
23
  */
6
24
  import { z } from "zod";
25
+ /**
26
+ * `$spacing` in _config.scss. The utilities emit literal pixel values, not
27
+ * `var(--cob-space-*)` references, so the rendered docs quote pixels.
28
+ *
29
+ * There is deliberately no `0` key: `cob-margin-0` and `cob-padding-0` are
30
+ * not generated.
31
+ */
32
+ const SPACING = [
33
+ ["1px", "1px"],
34
+ ["2px", "2px"],
35
+ ["50", "4px", "0.25rem"],
36
+ ["100", "8px", "0.5rem"],
37
+ ["150", "12px", "0.75rem"],
38
+ ["200", "16px", "1rem"],
39
+ ["250", "20px", "1.25rem"],
40
+ ["300", "24px", "1.5rem"],
41
+ ["400", "32px", "2rem"],
42
+ ["500", "40px", "2.5rem"],
43
+ ["600", "48px", "3rem"],
44
+ ["700", "56px", "3.5rem"],
45
+ ["800", "64px", "4rem"],
46
+ ["1200", "96px", "6rem"],
47
+ ];
48
+ /** `$responsive-gap-suffixes` in _layout-grid.scss. */
49
+ const RESPONSIVE_GAP_KEYS = [
50
+ "400",
51
+ "500",
52
+ "600",
53
+ "700",
54
+ "800",
55
+ "1200",
56
+ ];
57
+ /** `$opacity-values` in _config.scss. */
58
+ const OPACITY = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
59
+ /** `$zindex-values` in _config.scss. */
60
+ const ZINDEX = [
61
+ ["0", "0"],
62
+ ["100", "100"],
63
+ ["200", "200"],
64
+ ["300", "300"],
65
+ ["400", "400"],
66
+ ["500", "500"],
67
+ ["auto", "auto"],
68
+ ["bottom", "-100"],
69
+ ["top", "99999"],
70
+ ];
71
+ /** `$display-values` in _config.scss. */
72
+ const DISPLAY = [
73
+ "none",
74
+ "block",
75
+ "inline",
76
+ "inline-block",
77
+ "flex",
78
+ "inline-flex",
79
+ "table",
80
+ "table-cell",
81
+ "table-row",
82
+ ];
83
+ /** `$breakpoints` in _config.scss. */
84
+ const BREAKPOINTS = [
85
+ ["mobile-lg", "30em", "480px"],
86
+ ["tablet", "40em", "640px"],
87
+ ["desktop", "64em", "1024px"],
88
+ ["widescreen", "87.5em", "1400px"],
89
+ ];
90
+ /** Typography scales in core/typography.scss. */
91
+ const HEADING_LEVELS = [1, 2, 3, 4, 5, 6];
92
+ const BODY_SIZES = ["xs", "sm", "md"];
93
+ const UI_SIZES = ["xs", "sm", "md", "lg", "xl"];
94
+ const DISPLAY_SIZES = ["sm", "md", "lg", "xl"];
95
+ /** `$ui-underline-styles` — only these size/weight pairs are generated. */
96
+ const UI_UNDERLINE = [
97
+ ["sm", "semibold"],
98
+ ["md", "semibold"],
99
+ ["md", "regular"],
100
+ ["lg", "semibold"],
101
+ ];
102
+ const FLEX_ALIGN = [
103
+ "start",
104
+ "center",
105
+ "end",
106
+ "baseline",
107
+ "stretch",
108
+ ];
109
+ const FLEX_JUSTIFY = [
110
+ "start",
111
+ "center",
112
+ "end",
113
+ "space-between",
114
+ "space-around",
115
+ "space-evenly",
116
+ ];
117
+ /* ------------------------------------------------------------------ *
118
+ * Renderers
119
+ * ------------------------------------------------------------------ */
120
+ const spacingKeys = SPACING.map(([key]) => key);
121
+ const bullets = (lines) => lines.join("\n");
122
+ const inlineList = (items) => items.map((i) => `\`${i}\``).join(", ");
123
+ const spacingValueRows = bullets(SPACING.map(([key, px, rem]) => `- \`${key}\` - ${px}${rem ? ` (${rem})` : ""}`));
124
+ const gapValueRows = bullets(SPACING.map(([key, px, rem]) => {
125
+ const size = `${px}${rem ? ` (${rem})` : ""}`;
126
+ // Gaps in the responsive set are capped at 2rem below 64em. For 400 the
127
+ // cap equals the full value, so only note it where it actually differs.
128
+ const capped = RESPONSIVE_GAP_KEYS.includes(key) && Number.parseInt(px, 10) > 32;
129
+ return capped
130
+ ? `- \`cob-grid-gap-${key}\` - ${size} at 64em and up, capped at 32px (2rem) below that`
131
+ : `- \`cob-grid-gap-${key}\` - ${size}`;
132
+ }));
133
+ const opacityRows = bullets(OPACITY.map((v) => {
134
+ const label = v === 0
135
+ ? "Fully transparent"
136
+ : v === 100
137
+ ? "Fully opaque"
138
+ : `${v}% opaque`;
139
+ return `- \`cob-opacity-${v}\` - opacity: ${v / 100} (${label})`;
140
+ }));
141
+ const zindexRows = bullets(ZINDEX.map(([name, value]) => `- \`cob-z-${name}\` - z-index: ${value}`));
142
+ const displayRows = bullets(DISPLAY.map((v) => `- \`cob-display-${v}\` - display: ${v}`));
143
+ const breakpointRows = bullets(BREAKPOINTS.map(([name, em, px]) => `- \`cob-${name}:\` - ${em} (${px}) and up`));
144
+ const headingRows = bullets(HEADING_LEVELS.map((n) => `- \`cob-font-h${n}\` - Heading level ${n} type style`));
145
+ const underlineRows = bullets(UI_UNDERLINE.flatMap(([size, weight]) => [
146
+ `- \`cob-font-ui-${size}-${weight}-underline\` - UI ${size} ${weight}, 7% underline`,
147
+ `- \`cob-font-ui-${size}-${weight}-underline-strong\` - UI ${size} ${weight}, 14% underline`,
148
+ ]));
7
149
  const UTILITY_DOCS = {
8
150
  grid: `## Grid System
9
151
 
@@ -26,20 +168,11 @@ COBWDS provides a 12-column responsive grid system.
26
168
  - \`cob-grid-col-fill\` - Column fills remaining space
27
169
 
28
170
  ### Gap Classes
29
- - \`cob-grid-gap-0\` - No gap
30
- - \`cob-grid-gap-2px\` - 2px gap
31
- - \`cob-grid-gap-50\` - 4px gap (0.25rem)
32
- - \`cob-grid-gap-100\` - 8px gap (0.5rem)
33
- - \`cob-grid-gap-150\` - 12px gap (0.75rem)
34
- - \`cob-grid-gap-200\` - 16px gap (1rem)
35
- - \`cob-grid-gap-250\` - 20px gap (1.25rem)
36
- - \`cob-grid-gap-300\` - 24px gap (1.5rem)
37
- - \`cob-grid-gap-400\` - 32px gap (2rem)
38
- - \`cob-grid-gap-500\` - 40px gap (2.5rem)
39
- - \`cob-grid-gap-600\` - 48px gap (3rem)
40
- - \`cob-grid-gap-700\` - 56px gap (3.5rem)
41
- - \`cob-grid-gap-800\` - 64px gap (4rem)
42
- - \`cob-grid-gap-1200\` - 96px gap (6rem)
171
+ Gap classes apply to \`cob-grid-row\`. Use \`cob-grid-gap-x-*\` or
172
+ \`cob-grid-gap-y-*\` for a single axis. There is no \`cob-grid-gap-0\`; omit
173
+ the gap class instead.
174
+
175
+ ${gapValueRows}
43
176
 
44
177
  ### Offset Classes
45
178
  - \`cob-grid-offset-[1-12]\` - Offset column by 1-12 columns
@@ -61,6 +194,7 @@ COBWDS provides a 12-column responsive grid system.
61
194
 
62
195
  ### Display
63
196
  - \`cob-display-flex\` - Sets display: flex
197
+ - \`cob-display-inline-flex\` - Sets display: inline-flex
64
198
 
65
199
  ### Direction
66
200
  - \`cob-flex-row\` - Row direction (default)
@@ -71,21 +205,26 @@ COBWDS provides a 12-column responsive grid system.
71
205
  - \`cob-flex-no-wrap\` - Prevent wrapping
72
206
 
73
207
  ### Alignment (Cross Axis)
74
- - \`cob-flex-align-start\` - Align items to start
75
- - \`cob-flex-align-center\` - Align items to center
76
- - \`cob-flex-align-end\` - Align items to end
77
- - \`cob-flex-align-stretch\` - Stretch items to fill
208
+ ${bullets(FLEX_ALIGN.map((v) => `- \`cob-flex-align-${v}\` - align-items: ${v}`))}
209
+
210
+ ### Self Alignment
211
+ ${bullets(FLEX_ALIGN.map((v) => `- \`cob-flex-align-self-${v}\` - align-self: ${v}`))}
78
212
 
79
213
  ### Justification (Main Axis)
80
- - \`cob-flex-justify-start\` - Justify to start
81
- - \`cob-flex-justify-center\` - Justify to center
82
- - \`cob-flex-justify-end\` - Justify to end
214
+ ${bullets(FLEX_JUSTIFY.map((v) => `- \`cob-flex-justify-${v}\` - justify-content: ${v}`))}
83
215
 
84
216
  ### Flex Sizing
85
217
  - \`cob-flex-[1-12]\` - Flex grow/shrink values
86
218
  - \`cob-flex-auto\` - flex: auto (grow and shrink)
87
219
  - \`cob-flex-fill\` - Fill available space
88
220
 
221
+ ### Gaps
222
+ Available on the spacing scale: ${inlineList(spacingKeys)}
223
+
224
+ - \`cob-flex-gap-{value}\` - gap on both axes
225
+ - \`cob-flex-row-gap-{value}\` - row-gap only
226
+ - \`cob-flex-column-gap-{value}\` - column-gap only
227
+
89
228
  ### Example: Button Group
90
229
  \`\`\`html
91
230
  <div class="cob-display-flex cob-flex-justify-end cob-flex-gap-200">
@@ -111,21 +250,11 @@ Pattern: \`cob-{property}-{direction}-{value}\`
111
250
  - (none) - All sides
112
251
 
113
252
  ### Values
114
- - \`0\` - 0
115
- - \`1px\` - 1px
116
- - \`2px\` - 2px
117
- - \`50\` - var(--cob-space-50) = 0.125rem (2px)
118
- - \`100\` - var(--cob-space-100) = 0.25rem (4px)
119
- - \`150\` - var(--cob-space-150) = 0.375rem (6px)
120
- - \`200\` - var(--cob-space-200) = 0.5rem (8px)
121
- - \`250\` - var(--cob-space-250) = 0.625rem (10px)
122
- - \`300\` - var(--cob-space-300) = 0.75rem (12px)
123
- - \`400\` - var(--cob-space-400) = 1rem (16px)
124
- - \`500\` - var(--cob-space-500) = 1.25rem (20px)
125
- - \`600\` - var(--cob-space-600) = 1.5rem (24px)
126
- - \`700\` - var(--cob-space-700) = 2rem (32px)
127
- - \`800\` - var(--cob-space-800) = 2.5rem (40px)
128
- - \`1200\` - var(--cob-space-1200) = 4rem (64px)
253
+ The utilities emit literal pixel values. There is no zero and no \`auto\`
254
+ value — \`cob-margin-0\` and \`cob-padding-0\` are not generated. Omit the
255
+ class instead.
256
+
257
+ ${spacingValueRows}
129
258
 
130
259
  ### Examples
131
260
  \`\`\`html
@@ -140,11 +269,7 @@ Pattern: \`cob-{property}-{direction}-{value}\`
140
269
  \`\`\``,
141
270
  display: `## Display Utilities
142
271
 
143
- - \`cob-display-none\` - Hide element
144
- - \`cob-display-block\` - Block display
145
- - \`cob-display-inline\` - Inline display
146
- - \`cob-display-inline-block\` - Inline-block display
147
- - \`cob-display-flex\` - Flex display
272
+ ${displayRows}
148
273
 
149
274
  ### Example: Hide on Mobile
150
275
  \`\`\`html
@@ -154,46 +279,57 @@ Pattern: \`cob-{property}-{direction}-{value}\`
154
279
  \`\`\``,
155
280
  opacity: `## Opacity Utilities
156
281
 
157
- - \`cob-opacity-0\` - Fully transparent
158
- - \`cob-opacity-25\` - 25% opacity
159
- - \`cob-opacity-50\` - 50% opacity
160
- - \`cob-opacity-75\` - 75% opacity
161
- - \`cob-opacity-100\` - Fully opaque`,
282
+ The scale steps by 10 — there is no \`cob-opacity-25\` or \`cob-opacity-75\`.
283
+
284
+ ${opacityRows}`,
162
285
  zindex: `## Z-Index Utilities
163
286
 
164
- - \`cob-z-0\` - z-index: 0
165
- - \`cob-z-10\` - z-index: 10
166
- - \`cob-z-20\` - z-index: 20
167
- - \`cob-z-30\` - z-index: 30
168
- - \`cob-z-40\` - z-index: 40
169
- - \`cob-z-50\` - z-index: 50
170
- - \`cob-z-auto\` - z-index: auto`,
287
+ The scale steps by 100, not by 10. \`cob-z-10\` through \`cob-z-50\` do not
288
+ exist — the comparable values are \`cob-z-100\` through \`cob-z-500\`.
289
+
290
+ ${zindexRows}`,
171
291
  typography: `## Typography Utilities
172
292
 
173
- ### Text Alignment
174
- - \`cob-text-left\` - Left align text
175
- - \`cob-text-center\` - Center align text
176
- - \`cob-text-right\` - Right align text
177
-
178
- ### Font Weight
179
- - \`cob-font-normal\` - Normal weight
180
- - \`cob-font-medium\` - Medium weight
181
- - \`cob-font-semibold\` - Semibold weight
182
- - \`cob-font-bold\` - Bold weight
183
-
184
- ### Text Transform
185
- - \`cob-text-uppercase\` - Uppercase text
186
- - \`cob-text-lowercase\` - Lowercase text
187
- - \`cob-text-capitalize\` - Capitalize text`,
293
+ COBWDS ships a role-based type scale, not atomic text modifiers. Each class
294
+ sets font-family, size, and line-height together, matching the text styles in
295
+ the COBWDS Foundations Figma file.
296
+
297
+ There are NO text-alignment, text-transform, or font-weight utilities
298
+ (no \`cob-text-center\`, no \`cob-font-bold\`). Use CSS for those.
299
+
300
+ ### Headings
301
+ ${headingRows}
302
+
303
+ ### Body
304
+ ${bullets(BODY_SIZES.map((s) => `- \`cob-font-body-${s}\` - Body text, ${s}`))}
305
+
306
+ ### UI
307
+ ${bullets(UI_SIZES.map((s) => `- \`cob-font-ui-${s}\` - UI text, ${s}`))}
308
+
309
+ ### UI Underline
310
+ ${underlineRows}
311
+
312
+ ### Display
313
+ ${bullets(DISPLAY_SIZES.map((s) => `- \`cob-font-display-${s}\` - Display text, ${s}`))}
314
+
315
+ ### Agency
316
+ - \`cob-font-agency\` - Agency / application title
317
+
318
+ ### Font family hooks
319
+ These are attribute selectors, not standalone classes. They set only
320
+ font-family on any element whose class list contains the substring, so pair
321
+ them with a size class:
322
+
323
+ - \`[class*="cob-font-mono-"]\` - monospace family
324
+ - \`[class*="cob-font-sans-"]\` - sans-serif family
325
+ - \`[class*="cob-font-serif-"]\` - serif family`,
188
326
  responsive: `## Responsive Breakpoints
189
327
 
190
328
  COBWDS utility classes support responsive prefixes.
191
329
 
192
330
  ### Breakpoints
193
331
  - (no prefix) - All screen sizes (mobile-first)
194
- - \`cob-mobile-lg:\` - 30em (480px) and up
195
- - \`cob-tablet:\` - 40em (640px) and up
196
- - \`cob-desktop:\` - 64em (1024px) and up
332
+ ${breakpointRows}
197
333
 
198
334
  ### Pattern
199
335
  \`cob-{breakpoint}:cob-{class}\`
@@ -236,6 +372,35 @@ When adding spacing around COBWDS components, use utility classes rather than wr
236
372
  <cob-button label="Submit"></cob-button>
237
373
  \`\`\``,
238
374
  };
375
+ /**
376
+ * Classes the reference deliberately names in order to say they do NOT exist.
377
+ *
378
+ * These are the names people reach for out of habit from other frameworks.
379
+ * Saying so explicitly is more useful than silence, but it means the docs
380
+ * mention class names the stylesheet does not define, which would otherwise
381
+ * trip the verifier.
382
+ *
383
+ * `verify-utility-docs.mjs` asserts each of these is genuinely absent, so if
384
+ * COBWDS ever adds one, the stale warning fails the check instead of quietly
385
+ * misinforming people.
386
+ */
387
+ const KNOWN_ABSENT = [
388
+ "cob-text-center",
389
+ "cob-font-bold",
390
+ "cob-z-10",
391
+ "cob-z-50",
392
+ "cob-opacity-25",
393
+ "cob-opacity-75",
394
+ "cob-margin-0",
395
+ "cob-padding-0",
396
+ "cob-grid-gap-0",
397
+ ];
398
+ /**
399
+ * Exported so `src/scripts/verify-utility-docs.mjs` can assert that every class
400
+ * named in this reference exists in the compiled stylesheet — and that every
401
+ * class named in KNOWN_ABSENT still does not.
402
+ */
403
+ export { UTILITY_DOCS, KNOWN_ABSENT };
239
404
  export function registerUtilityTools(server) {
240
405
  // get_utility_classes - Comprehensive utility class reference
241
406
  server.tool("get_utility_classes", "Get COBWDS utility class reference for layout, spacing, and styling", {