@primer/mcp 0.0.5 → 0.2.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.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { s as server } from './server-Ccnupv1s.js';
1
+ export { s as server } from './server-CjO5UCV7.js';
2
2
  import '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import 'cheerio';
4
4
  import 'zod';
@@ -1 +1 @@
1
- {"version":3,"file":"primer.d.ts","sourceRoot":"","sources":["../src/primer.ts"],"names":[],"mappings":"AAGA,KAAK,SAAS,GAAG;IACf,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AA+BD,iBAAS,cAAc,IAAI,KAAK,CAAC,SAAS,CAAC,CAE1C;AAED,KAAK,OAAO,GAAG;IACb,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AA6CD,iBAAS,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,CAEtC;AAED,KAAK,IAAI,GAAG;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACvB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CACvB,CAAA;AAUD,iBAAS,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,CAEhC;AAED,OAAO,EAAC,cAAc,EAAE,YAAY,EAAE,SAAS,EAAC,CAAA"}
1
+ {"version":3,"file":"primer.d.ts","sourceRoot":"","sources":["../src/primer.ts"],"names":[],"mappings":"AAGA,KAAK,SAAS,GAAG;IACf,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AA2BD,iBAAS,cAAc,IAAI,KAAK,CAAC,SAAS,CAAC,CAE1C;AAED,KAAK,OAAO,GAAG;IACb,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AA6CD,iBAAS,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,CAEtC;AAED,KAAK,IAAI,GAAG;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACvB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CACvB,CAAA;AAUD,iBAAS,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,CAEhC;AAED,OAAO,EAAC,cAAc,EAAE,YAAY,EAAE,SAAS,EAAC,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import * as cheerio from 'cheerio';
3
- import { z } from 'zod';
3
+ import * as z from 'zod';
4
4
  import TurndownService from 'turndown';
5
5
  import componentsMetadata from '@primer/react/generated/components.json' with { type: 'json' };
6
6
  import octicons from '@primer/octicons/build/data.json' with { type: 'json' };
@@ -24,9 +24,6 @@ function idToSlug(id) {
24
24
  if (id === 'dialog_v2') {
25
25
  return 'dialog';
26
26
  }
27
- if (id.startsWith('skeleton')) {
28
- return 'skeleton-loaders';
29
- }
30
27
  return id.replaceAll('_', '-');
31
28
  }
32
29
  const components = Object.entries(componentsMetadata.components).map(([id, component]) => {
@@ -163,7 +160,7 @@ function serialize(value) {
163
160
  }).join('\n');
164
161
  }
165
162
 
166
- var version = "0.1.0-rc.1";
163
+ var version = "0.2.0";
167
164
  var packageJson = {
168
165
  version: version};
169
166
 
@@ -176,7 +173,9 @@ const turndownService = new TurndownService();
176
173
  // -----------------------------------------------------------------------------
177
174
  // Project setup
178
175
  // -----------------------------------------------------------------------------
179
- server.tool('init', 'Setup or create a project that includes Primer React', async () => {
176
+ server.registerTool('init', {
177
+ description: 'Setup or create a project that includes Primer React'
178
+ }, async () => {
180
179
  const url = new URL(`/product/getting-started/react`, 'https://primer.style');
181
180
  const response = await fetch(url);
182
181
  if (!response.ok) {
@@ -219,7 +218,9 @@ ${text}
219
218
  // -----------------------------------------------------------------------------
220
219
  // Components
221
220
  // -----------------------------------------------------------------------------
222
- server.tool('list_components', 'List all of the components available from Primer React', async () => {
221
+ server.registerTool('list_components', {
222
+ description: 'List all of the components available from Primer React'
223
+ }, async () => {
223
224
  const components = listComponents().map(component => {
224
225
  return `- ${component.name}`;
225
226
  });
@@ -234,8 +235,11 @@ You can use the \`get_component\` tool to get more information about a specific
234
235
  }]
235
236
  };
236
237
  });
237
- server.tool('get_component', 'Retrieve documentation and usage details for a specific React component from the @primer/react package by its name. This tool provides the official Primer documentation for any listed component, making it easy to inspect, reuse, or integrate components in your project.', {
238
- name: z.string().describe('The name of the component to retrieve')
238
+ server.registerTool('get_component', {
239
+ description: 'Retrieve documentation and usage details for a specific React component from the @primer/react package by its name. This tool provides the official Primer documentation for any listed component, making it easy to inspect, reuse, or integrate components in your project.',
240
+ inputSchema: {
241
+ name: z.string().describe('The name of the component to retrieve')
242
+ }
239
243
  }, async ({
240
244
  name
241
245
  }) => {
@@ -245,12 +249,26 @@ server.tool('get_component', 'Retrieve documentation and usage details for a spe
245
249
  });
246
250
  if (!match) {
247
251
  return {
248
- content: [{
249
- type: 'text',
250
- text: `There is no component named \`${name}\` in the @primer/react package. For a full list of components, use the \`list_components\` tool.`
251
- }]
252
+ isError: true,
253
+ errorMessage: `There is no component named \`${name}\` in the @primer/react package. For a full list of components, use the \`list_components\` tool.`,
254
+ content: []
252
255
  };
253
256
  }
257
+ const llmsUrl = new URL(`/product/components/${match.slug}/llms.txt`, 'https://primer.style');
258
+ const llmsResponse = await fetch(llmsUrl);
259
+ if (llmsResponse.ok) {
260
+ try {
261
+ const llmsText = await llmsResponse.text();
262
+ return {
263
+ content: [{
264
+ type: 'text',
265
+ text: llmsText
266
+ }]
267
+ };
268
+ } catch (_) {
269
+ // If there's an error fetching or processing the llms.txt, we fall back to the regular documentation
270
+ }
271
+ }
254
272
  const url = new URL(`/product/components/${match.slug}`, 'https://primer.style');
255
273
  const response = await fetch(url);
256
274
  if (!response.ok) {
@@ -278,8 +296,11 @@ ${text}`
278
296
  }]
279
297
  };
280
298
  });
281
- server.tool('get_component_examples', 'Get examples for how to use a component from Primer React', {
282
- name: z.string().describe('The name of the component to retrieve')
299
+ server.registerTool('get_component_examples', {
300
+ description: 'Get examples for how to use a component from Primer React',
301
+ inputSchema: {
302
+ name: z.string().describe('The name of the component to retrieve')
303
+ }
283
304
  }, async ({
284
305
  name
285
306
  }) => {
@@ -323,8 +344,11 @@ ${text}`
323
344
  }]
324
345
  };
325
346
  });
326
- server.tool('get_component_usage_guidelines', 'Get usage information for how to use a component from Primer', {
327
- name: z.string().describe('The name of the component to retrieve')
347
+ server.registerTool('get_component_usage_guidelines', {
348
+ description: 'Get usage information for how to use a component from Primer',
349
+ inputSchema: {
350
+ name: z.string().describe('The name of the component to retrieve')
351
+ }
328
352
  }, async ({
329
353
  name
330
354
  }) => {
@@ -376,8 +400,11 @@ ${text}`
376
400
  }]
377
401
  };
378
402
  });
379
- server.tool('get_component_accessibility_guidelines', 'Retrieve accessibility guidelines and best practices for a specific component from the @primer/react package by its name. Use this tool to get official accessibility recommendations, usage tips, and requirements to ensure your UI components are inclusive and meet accessibility standards.', {
380
- name: z.string().describe('The name of the component to retrieve')
403
+ server.registerTool('get_component_accessibility_guidelines', {
404
+ description: 'Retrieve accessibility guidelines and best practices for a specific component from the @primer/react package by its name. Use this tool to get official accessibility recommendations, usage tips, and requirements to ensure your UI components are inclusive and meet accessibility standards.',
405
+ inputSchema: {
406
+ name: z.string().describe('The name of the component to retrieve')
407
+ }
381
408
  }, async ({
382
409
  name
383
410
  }) => {
@@ -433,7 +460,9 @@ ${text}`
433
460
  // -----------------------------------------------------------------------------
434
461
  // Patterns
435
462
  // -----------------------------------------------------------------------------
436
- server.tool('list_patterns', 'List all of the patterns available from Primer React', async () => {
463
+ server.registerTool('list_patterns', {
464
+ description: 'List all of the patterns available from Primer React'
465
+ }, async () => {
437
466
  const patterns = listPatterns().map(pattern => {
438
467
  return `- ${pattern.name}`;
439
468
  });
@@ -446,8 +475,11 @@ ${patterns.join('\n')}`
446
475
  }]
447
476
  };
448
477
  });
449
- server.tool('get_pattern', 'Get a specific pattern by name', {
450
- name: z.string().describe('The name of the pattern to retrieve')
478
+ server.registerTool('get_pattern', {
479
+ description: 'Get a specific pattern by name',
480
+ inputSchema: {
481
+ name: z.string().describe('The name of the pattern to retrieve')
482
+ }
451
483
  }, async ({
452
484
  name
453
485
  }) => {
@@ -495,7 +527,9 @@ ${text}`
495
527
  // -----------------------------------------------------------------------------
496
528
  // Design Tokens
497
529
  // -----------------------------------------------------------------------------
498
- server.tool('list_tokens', 'List all of the design tokens available from Primer', async () => {
530
+ server.registerTool('list_tokens', {
531
+ description: 'List all of the design tokens available from Primer'
532
+ }, async () => {
499
533
  let text = 'Below is a list of all design tokens available from Primer. Tokens are used in CSS and CSS Modules. To refer to the CSS Custom Property for a design token, wrap it in var(--{name-of-token}). To learn how to use a specific token, use a corresponding usage tool for the category of the token. For example, if a token is a color token look for the get_color_usage tool. \n\n';
500
534
  text += serialize(tokens);
501
535
  return {
@@ -509,7 +543,9 @@ server.tool('list_tokens', 'List all of the design tokens available from Primer'
509
543
  // -----------------------------------------------------------------------------
510
544
  // Foundations
511
545
  // -----------------------------------------------------------------------------
512
- server.tool('get_color_usage', 'Get the guidelines for how to apply color to a user interface', async () => {
546
+ server.registerTool('get_color_usage', {
547
+ description: 'Get the guidelines for how to apply color to a user interface'
548
+ }, async () => {
513
549
  const url = new URL(`/product/getting-started/foundations/color-usage`, 'https://primer.style');
514
550
  const response = await fetch(url);
515
551
  if (!response.ok) {
@@ -536,7 +572,9 @@ server.tool('get_color_usage', 'Get the guidelines for how to apply color to a u
536
572
  }]
537
573
  };
538
574
  });
539
- server.tool('get_typography_usage', 'Get the guidelines for how to apply typography to a user interface', async () => {
575
+ server.registerTool('get_typography_usage', {
576
+ description: 'Get the guidelines for how to apply typography to a user interface'
577
+ }, async () => {
540
578
  const url = new URL(`/product/getting-started/foundations/typography`, 'https://primer.style');
541
579
  const response = await fetch(url);
542
580
  if (!response.ok) {
@@ -567,7 +605,9 @@ server.tool('get_typography_usage', 'Get the guidelines for how to apply typogra
567
605
  // -----------------------------------------------------------------------------
568
606
  // Icons
569
607
  // -----------------------------------------------------------------------------
570
- server.tool('list_icons', 'List all of the icons (octicons) available from Primer Octicons React', async () => {
608
+ server.registerTool('list_icons', {
609
+ description: 'List all of the icons (octicons) available from Primer Octicons React'
610
+ }, async () => {
571
611
  const icons = listIcons().map(icon => {
572
612
  const keywords = icon.keywords.map(keyword => {
573
613
  return `<keyword>${keyword}</keyword>`;
@@ -588,9 +628,12 @@ You can use the \`get_icon\` tool to get more information about a specific icon.
588
628
  }]
589
629
  };
590
630
  });
591
- server.tool('get_icon', 'Get a specific icon (octicon) by name from Primer', {
592
- name: z.string().describe('The name of the icon to retrieve'),
593
- size: z.string().optional().describe('The size of the icon to retrieve, e.g. "16"').default('16')
631
+ server.registerTool('get_icon', {
632
+ description: 'Get a specific icon (octicon) by name from Primer',
633
+ inputSchema: {
634
+ name: z.string().describe('The name of the icon to retrieve'),
635
+ size: z.string().optional().describe('The size of the icon to retrieve, e.g. "16"').default('16')
636
+ }
594
637
  }, async ({
595
638
  name,
596
639
  size
@@ -638,7 +681,9 @@ ${text}`
638
681
  // -----------------------------------------------------------------------------
639
682
  // Coding guidelines
640
683
  // -----------------------------------------------------------------------------
641
- server.tool('primer_coding_guidelines', 'Get the guidelines when writing code that uses Primer or for UI code that you are creating', async () => {
684
+ server.registerTool('primer_coding_guidelines', {
685
+ description: 'Get the guidelines when writing code that uses Primer or for UI code that you are creating'
686
+ }, async () => {
642
687
  return {
643
688
  content: [{
644
689
  type: 'text',
@@ -682,10 +727,13 @@ The following list of coding guidelines must be followed:
682
727
  *
683
728
  *
684
729
  **/
685
- server.tool('review_alt_text', 'Evaluates image alt text against accessibility best practices and context relevance.', {
686
- surroundingText: z.string().describe('Text surrounding the image, relevant to the image.'),
687
- alt: z.string().describe('The alt text of the image being evaluated'),
688
- image: z.union([z.instanceof(File).describe('The image src file being evaluated'), z.string().url().describe('The URL of the image src being evaluated'), z.string().describe('The file path of the image src being evaluated')]).describe('The image file, file path, or URL being evaluated')
730
+ server.registerTool('review_alt_text', {
731
+ description: 'Evaluates image alt text against accessibility best practices and context relevance.',
732
+ inputSchema: {
733
+ surroundingText: z.string().describe('Text surrounding the image, relevant to the image.'),
734
+ alt: z.string().describe('The alt text of the image being evaluated'),
735
+ image: z.string().describe('The image URL or file path being evaluated')
736
+ }
689
737
  }, async ({
690
738
  surroundingText,
691
739
  alt,
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAA;AASjE,QAAA,MAAM,MAAM,WAGV,CAAA;AAoqBF,OAAO,EAAC,MAAM,EAAC,CAAA"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAA;AAUjE,QAAA,MAAM,MAAM,WAGV,CAAA;AAutBF,OAAO,EAAC,MAAM,EAAC,CAAA"}
package/dist/stdio.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2
- import { s as server } from './server-Ccnupv1s.js';
2
+ import { s as server } from './server-CjO5UCV7.js';
3
3
  import '@modelcontextprotocol/sdk/server/mcp.js';
4
4
  import 'cheerio';
5
5
  import 'zod';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@primer/mcp",
3
3
  "description": "An MCP server that connects AI tools to the Primer Design System",
4
- "version": "0.0.5",
4
+ "version": "0.2.0",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "mcp": "./bin/mcp.js"
@@ -22,6 +22,10 @@
22
22
  "src",
23
23
  "README.md"
24
24
  ],
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/primer/react.git"
28
+ },
25
29
  "scripts": {
26
30
  "clean": "rimraf dist",
27
31
  "build": "rollup -c",
@@ -29,28 +33,28 @@
29
33
  "watch": "rollup -c -w"
30
34
  },
31
35
  "dependencies": {
32
- "@babel/runtime": "^7.28.4",
33
- "@modelcontextprotocol/sdk": "^1.12.0",
36
+ "@babel/runtime": "^7.28.6",
37
+ "@modelcontextprotocol/sdk": "^1.24.0",
34
38
  "@primer/octicons": "^19.15.5",
35
39
  "@primer/primitives": "10.x || 11.x",
36
- "@primer/react": "^38.0.0-rc.3",
40
+ "@primer/react": "^38.12.0",
37
41
  "cheerio": "^1.0.0",
38
42
  "turndown": "^7.2.0",
39
- "zod": "^3.23.8"
43
+ "zod": "^4.3.5"
40
44
  },
41
45
  "devDependencies": {
42
- "@babel/core": "^7.28.4",
43
- "@babel/plugin-transform-runtime": "^7.28.3",
44
- "@babel/preset-env": "^7.28.3",
45
- "@babel/preset-typescript": "^7.27.1",
46
+ "@babel/core": "^7.29.0",
47
+ "@babel/plugin-transform-runtime": "^7.29.0",
48
+ "@babel/preset-env": "^7.29.0",
49
+ "@babel/preset-typescript": "^7.28.5",
46
50
  "@modelcontextprotocol/inspector": "^0.16.6",
47
- "@rollup/plugin-babel": "^6.0.4",
48
- "@rollup/plugin-commonjs": "^28.0.6",
51
+ "@rollup/plugin-babel": "^6.1.0",
52
+ "@rollup/plugin-commonjs": "^29.0.0",
49
53
  "@rollup/plugin-json": "^6.1.0",
50
- "@rollup/plugin-node-resolve": "^16.0.1",
54
+ "@rollup/plugin-node-resolve": "^16.0.3",
51
55
  "@types/turndown": "^5.0.5",
52
56
  "rimraf": "^6.0.1",
53
- "rollup": "^4.50.1",
57
+ "rollup": "^4.56.0",
54
58
  "rollup-plugin-typescript2": "^0.36.0",
55
59
  "typescript": "^5.9.2"
56
60
  }
package/src/primer.ts CHANGED
@@ -21,10 +21,6 @@ function idToSlug(id: string): string {
21
21
  return 'dialog'
22
22
  }
23
23
 
24
- if (id.startsWith('skeleton')) {
25
- return 'skeleton-loaders'
26
- }
27
-
28
24
  return id.replaceAll('_', '-')
29
25
  }
30
26