@nysds/mcp-server 1.21.0 → 1.22.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.
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Framework Resources
3
+ *
4
+ * MCP resources for NYSDS framework packages (@nysds/react, @nysds/vue,
5
+ * @nysds/angular).
6
+ *
7
+ * Resources:
8
+ * - nysds://frameworks - Index of framework packages with version and guide URI
9
+ * - nysds://frameworks/react - @nysds/react guide (synced from its README)
10
+ * - nysds://frameworks/vue - @nysds/vue guide (synced from its README)
11
+ * - nysds://frameworks/angular - @nysds/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 @nysds/mcp-server".`;
26
+ }
27
+ }
28
+ export function registerFrameworkResources(server) {
29
+ // nysds://frameworks - Index of framework packages
30
+ server.resource("frameworks", "nysds://frameworks", {
31
+ description: "Index of NYSDS framework packages (@nysds/react, @nysds/vue, @nysds/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: "nysds://frameworks/react",
41
+ },
42
+ {
43
+ id: "vue",
44
+ packageName: index.vue.packageName,
45
+ version: index.vue.version,
46
+ guideUri: "nysds://frameworks/vue",
47
+ },
48
+ {
49
+ id: "angular",
50
+ packageName: index.angular.packageName,
51
+ version: index.angular.version,
52
+ guideUri: "nysds://frameworks/angular",
53
+ },
54
+ ];
55
+ return {
56
+ contents: [
57
+ {
58
+ uri: "nysds://frameworks",
59
+ mimeType: "application/json",
60
+ text: JSON.stringify(list, null, 2),
61
+ },
62
+ ],
63
+ };
64
+ });
65
+ // nysds://frameworks/react - @nysds/react guide
66
+ server.resource("frameworks-react", "nysds://frameworks/react", {
67
+ description: "@nysds/react install, usage, forms, SSR, and troubleshooting guide",
68
+ mimeType: "text/markdown",
69
+ }, async () => ({
70
+ contents: [
71
+ {
72
+ uri: "nysds://frameworks/react",
73
+ mimeType: "text/markdown",
74
+ text: loadFrameworkGuide("react"),
75
+ },
76
+ ],
77
+ }));
78
+ // nysds://frameworks/vue - @nysds/vue guide
79
+ server.resource("frameworks-vue", "nysds://frameworks/vue", {
80
+ description: "@nysds/vue install, usage, v-model forms, SSR, and troubleshooting guide",
81
+ mimeType: "text/markdown",
82
+ }, async () => ({
83
+ contents: [
84
+ {
85
+ uri: "nysds://frameworks/vue",
86
+ mimeType: "text/markdown",
87
+ text: loadFrameworkGuide("vue"),
88
+ },
89
+ ],
90
+ }));
91
+ // nysds://frameworks/angular - @nysds/angular guide
92
+ server.resource("frameworks-angular", "nysds://frameworks/angular", {
93
+ description: "@nysds/angular install, usage, forms, SSR, and troubleshooting guide",
94
+ mimeType: "text/markdown",
95
+ }, async () => ({
96
+ contents: [
97
+ {
98
+ uri: "nysds://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
+ \`@nysds/react\` (\`npm install @nysds/react\`), \`@nysds/vue\`
63
+ (\`npm install @nysds/vue\`), and \`@nysds/angular\`
64
+ (\`npm install @nysds/angular @nysds/components\`) generate typed
65
+ components, props, and events directly from this design system's
66
+ manifest. See the \`nysds://frameworks\` resource for their current
67
+ published versions, \`nysds://frameworks/react\`, \`nysds://frameworks/vue\`, and
68
+ \`nysds://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 NYSDS 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 NYSDS component including properties, events, slots, and CSS custom properties", {
56
+ server.tool("get_component", "Get full documentation for a specific NYSDS 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., 'nys-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: `nysds://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 }) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nysds/mcp-server",
3
- "version": "1.21.0",
3
+ "version": "1.22.0",
4
4
  "description": "MCP server for the New York State Design System. Exposes components, tokens, and documentation to AI assistants.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,18 +20,20 @@
20
20
  ],
21
21
  "scripts": {
22
22
  "copy-data": "mkdir -p data/cem data/tokens && cp ../../custom-elements.json data/cem/ && cp ../tokens/src/tokens.json data/tokens/ && cp ../tokens/dist/tokens.css data/tokens/",
23
- "build": "npm run copy-data && tsc",
23
+ "sync:guides": "node scripts/sync-guides.mjs",
24
+ "build": "npm run copy-data && npm run sync:guides && tsc",
24
25
  "dev": "tsc --watch",
25
26
  "start": "node dist/index.js",
26
27
  "inspect": "npx -y @modelcontextprotocol/inspector node dist/index.js"
27
28
  },
28
29
  "dependencies": {
29
30
  "@modelcontextprotocol/sdk": "^1.26.0",
31
+ "@nysds/codegen": "^1.20.1",
30
32
  "zod": "^3.25"
31
33
  },
32
34
  "devDependencies": {
33
- "@nysds/styles": "^1.21.0",
34
- "@nysds/tokens": "^1.21.0",
35
+ "@nysds/styles": "^1.22.0",
36
+ "@nysds/tokens": "^1.22.0",
35
37
  "@types/node": "^22.0.0",
36
38
  "typescript": "^5.9.3"
37
39
  },