@primer/mcp 0.3.4 → 0.4.0-rc.5c4b3e004

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-CaSuVJt0.js';
1
+ export { s as server } from './server-CkSoZOVD.js';
2
2
  import '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import 'cheerio';
4
4
  import 'zod';
@@ -40,36 +40,63 @@ const components = Object.entries(componentsMetadata.components).map(([id, compo
40
40
  function listComponents() {
41
41
  return components;
42
42
  }
43
+ // Scenario patterns are listed first so name resolution favours them over UI patterns.
43
44
  const patterns = [{
45
+ id: 'copy',
46
+ name: 'Copy',
47
+ category: 'scenario'
48
+ }, {
49
+ id: 'delete',
50
+ name: 'Delete',
51
+ category: 'scenario'
52
+ }, {
53
+ id: 'filter',
54
+ name: 'Filter',
55
+ category: 'scenario'
56
+ }, {
57
+ id: 'search',
58
+ name: 'Search',
59
+ category: 'scenario'
60
+ }, {
44
61
  id: 'data-visualization',
45
- name: 'Data Visualization'
62
+ name: 'Data Visualization',
63
+ category: 'ui'
46
64
  }, {
47
65
  id: 'degraded-experiences',
48
- name: 'Degraded Experiences'
66
+ name: 'Degraded Experiences',
67
+ category: 'ui'
49
68
  }, {
50
69
  id: 'empty-states',
51
- name: 'Empty States'
70
+ name: 'Empty States',
71
+ category: 'ui'
52
72
  }, {
53
73
  id: 'feature-onboarding',
54
- name: 'Feature Onboarding'
74
+ name: 'Feature Onboarding',
75
+ category: 'ui'
55
76
  }, {
56
77
  id: 'forms',
57
- name: 'Forms'
78
+ name: 'Forms',
79
+ category: 'ui'
58
80
  }, {
59
81
  id: 'loading',
60
- name: 'Loading'
82
+ name: 'Loading',
83
+ category: 'ui'
61
84
  }, {
62
85
  id: 'navigation',
63
- name: 'Navigation'
86
+ name: 'Navigation',
87
+ category: 'ui'
64
88
  }, {
65
89
  id: 'notification-messaging',
66
- name: 'Notification message'
90
+ name: 'Notification message',
91
+ category: 'ui'
67
92
  }, {
68
93
  id: 'progressive-disclosure',
69
- name: 'Progressive disclosure'
94
+ name: 'Progressive disclosure',
95
+ category: 'ui'
70
96
  }, {
71
97
  id: 'saving',
72
- name: 'Saving'
98
+ name: 'Saving',
99
+ category: 'ui'
73
100
  }];
74
101
  function listPatterns() {
75
102
  return patterns;
@@ -736,7 +763,7 @@ function runStylelint(css) {
736
763
  });
737
764
  }
738
765
 
739
- var version = "0.3.4";
766
+ var version = "0.4.0";
740
767
  var packageJson = {
741
768
  version: version};
742
769
 
@@ -1037,25 +1064,31 @@ ${text}`
1037
1064
  // Patterns
1038
1065
  // -----------------------------------------------------------------------------
1039
1066
  server.registerTool('list_patterns', {
1040
- description: 'List all of the patterns available from Primer React',
1067
+ description: 'List all of the patterns available from Primer React. Scenario patterns describe specific user tasks (copy, delete, filter, search). Prefer a scenario pattern when one fits the task, and fall back to the more generic UI patterns otherwise.',
1041
1068
  annotations: {
1042
1069
  readOnlyHint: true
1043
1070
  }
1044
1071
  }, async () => {
1045
- const patterns = listPatterns().map(pattern => {
1046
- return `- ${pattern.name}`;
1047
- });
1072
+ const all = listPatterns();
1073
+ const scenario = all.filter(pattern => pattern.category === 'scenario').map(pattern => `- ${pattern.name}`);
1074
+ const ui = all.filter(pattern => pattern.category === 'ui').map(pattern => `- ${pattern.name}`);
1048
1075
  return {
1049
1076
  content: [{
1050
1077
  type: 'text',
1051
- text: `The following patterns are available in the @primer/react in TypeScript projects:
1078
+ text: `The following patterns are available from \`@primer/react\` for use in TypeScript projects. Scenario patterns describe specific user tasks. Prefer a scenario pattern when one fits the task, and fall back to the UI patterns otherwise.
1052
1079
 
1053
- ${patterns.join('\n')}`
1080
+ ## Scenario patterns
1081
+
1082
+ ${scenario.join('\n')}
1083
+
1084
+ ## UI patterns
1085
+
1086
+ ${ui.join('\n')}`
1054
1087
  }]
1055
1088
  };
1056
1089
  });
1057
1090
  server.registerTool('get_pattern', {
1058
- description: 'Get a specific pattern by name',
1091
+ description: 'Get a specific pattern by name. Scenario patterns describe specific user tasks (copy, delete, filter, search). Prefer a scenario pattern when one fits the task, and fall back to the more generic UI patterns otherwise.',
1059
1092
  inputSchema: {
1060
1093
  name: z.string().describe('The name of the pattern to retrieve')
1061
1094
  },
@@ -1066,9 +1099,8 @@ server.registerTool('get_pattern', {
1066
1099
  name
1067
1100
  }) => {
1068
1101
  const patterns = listPatterns();
1069
- const match = patterns.find(pattern => {
1070
- return pattern.name === name;
1071
- });
1102
+ // Resolve scenario patterns first so a name clash favours the scenario pattern.
1103
+ const match = patterns.find(pattern => pattern.category === 'scenario' && pattern.name === name) ?? patterns.find(pattern => pattern.name === name);
1072
1104
  if (!match) {
1073
1105
  return {
1074
1106
  content: [{
@@ -1077,7 +1109,8 @@ server.registerTool('get_pattern', {
1077
1109
  }]
1078
1110
  };
1079
1111
  }
1080
- const url = new URL(`/product/ui-patterns/${match.id}`, 'https://primer.style');
1112
+ const basePath = match.category === 'scenario' ? 'scenario-patterns' : 'ui-patterns';
1113
+ const url = new URL(`/product/${basePath}/${match.id}`, 'https://primer.style');
1081
1114
  const response = await fetch(url);
1082
1115
  if (!response.ok) {
1083
1116
  throw new Error(`Failed to fetch ${url} - ${response.statusText}`);
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-CaSuVJt0.js';
2
+ import { s as server } from './server-CkSoZOVD.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.3.4",
4
+ "version": "0.4.0-rc.5c4b3e004",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "mcp": "./bin/mcp.js"
@@ -37,7 +37,7 @@
37
37
  "@modelcontextprotocol/sdk": "^1.24.0",
38
38
  "@primer/octicons": "^19.15.5",
39
39
  "@primer/primitives": "10.x || 11.x",
40
- "@primer/react": "^38.20.0",
40
+ "@primer/react": "^38.30.0",
41
41
  "cheerio": "^1.0.0",
42
42
  "turndown": "^7.2.0",
43
43
  "zod": "^4.3.5"
package/src/primer.ts CHANGED
@@ -40,48 +40,81 @@ function listComponents(): Array<Component> {
40
40
  type Pattern = {
41
41
  id: string
42
42
  name: string
43
+ // 'scenario' maps to the /product/scenario-patterns/ base path, 'ui' to /product/ui-patterns/
44
+ category: 'scenario' | 'ui'
43
45
  }
44
46
 
47
+ // Scenario patterns are listed first so name resolution favours them over UI patterns.
45
48
  const patterns: Array<Pattern> = [
49
+ {
50
+ id: 'copy',
51
+ name: 'Copy',
52
+ category: 'scenario',
53
+ },
54
+ {
55
+ id: 'delete',
56
+ name: 'Delete',
57
+ category: 'scenario',
58
+ },
59
+ {
60
+ id: 'filter',
61
+ name: 'Filter',
62
+ category: 'scenario',
63
+ },
64
+ {
65
+ id: 'search',
66
+ name: 'Search',
67
+ category: 'scenario',
68
+ },
46
69
  {
47
70
  id: 'data-visualization',
48
71
  name: 'Data Visualization',
72
+ category: 'ui',
49
73
  },
50
74
  {
51
75
  id: 'degraded-experiences',
52
76
  name: 'Degraded Experiences',
77
+ category: 'ui',
53
78
  },
54
79
  {
55
80
  id: 'empty-states',
56
81
  name: 'Empty States',
82
+ category: 'ui',
57
83
  },
58
84
  {
59
85
  id: 'feature-onboarding',
60
86
  name: 'Feature Onboarding',
87
+ category: 'ui',
61
88
  },
62
89
  {
63
90
  id: 'forms',
64
91
  name: 'Forms',
92
+ category: 'ui',
65
93
  },
66
94
  {
67
95
  id: 'loading',
68
96
  name: 'Loading',
97
+ category: 'ui',
69
98
  },
70
99
  {
71
100
  id: 'navigation',
72
101
  name: 'Navigation',
102
+ category: 'ui',
73
103
  },
74
104
  {
75
105
  id: 'notification-messaging',
76
106
  name: 'Notification message',
107
+ category: 'ui',
77
108
  },
78
109
  {
79
110
  id: 'progressive-disclosure',
80
111
  name: 'Progressive disclosure',
112
+ category: 'ui',
81
113
  },
82
114
  {
83
115
  id: 'saving',
84
116
  name: 'Saving',
117
+ category: 'ui',
85
118
  },
86
119
  ]
87
120
 
package/src/server.ts CHANGED
@@ -372,18 +372,28 @@ ${text}`,
372
372
  // -----------------------------------------------------------------------------
373
373
  server.registerTool(
374
374
  'list_patterns',
375
- {description: 'List all of the patterns available from Primer React', annotations: {readOnlyHint: true}},
375
+ {
376
+ description:
377
+ 'List all of the patterns available from Primer React. Scenario patterns describe specific user tasks (copy, delete, filter, search). Prefer a scenario pattern when one fits the task, and fall back to the more generic UI patterns otherwise.',
378
+ annotations: {readOnlyHint: true},
379
+ },
376
380
  async () => {
377
- const patterns = listPatterns().map(pattern => {
378
- return `- ${pattern.name}`
379
- })
381
+ const all = listPatterns()
382
+ const scenario = all.filter(pattern => pattern.category === 'scenario').map(pattern => `- ${pattern.name}`)
383
+ const ui = all.filter(pattern => pattern.category === 'ui').map(pattern => `- ${pattern.name}`)
380
384
  return {
381
385
  content: [
382
386
  {
383
387
  type: 'text',
384
- text: `The following patterns are available in the @primer/react in TypeScript projects:
388
+ text: `The following patterns are available from \`@primer/react\` for use in TypeScript projects. Scenario patterns describe specific user tasks. Prefer a scenario pattern when one fits the task, and fall back to the UI patterns otherwise.
385
389
 
386
- ${patterns.join('\n')}`,
390
+ ## Scenario patterns
391
+
392
+ ${scenario.join('\n')}
393
+
394
+ ## UI patterns
395
+
396
+ ${ui.join('\n')}`,
387
397
  },
388
398
  ],
389
399
  }
@@ -393,7 +403,8 @@ ${patterns.join('\n')}`,
393
403
  server.registerTool(
394
404
  'get_pattern',
395
405
  {
396
- description: 'Get a specific pattern by name',
406
+ description:
407
+ 'Get a specific pattern by name. Scenario patterns describe specific user tasks (copy, delete, filter, search). Prefer a scenario pattern when one fits the task, and fall back to the more generic UI patterns otherwise.',
397
408
  inputSchema: {
398
409
  name: z.string().describe('The name of the pattern to retrieve'),
399
410
  },
@@ -401,9 +412,10 @@ server.registerTool(
401
412
  },
402
413
  async ({name}) => {
403
414
  const patterns = listPatterns()
404
- const match = patterns.find(pattern => {
405
- return pattern.name === name
406
- })
415
+ // Resolve scenario patterns first so a name clash favours the scenario pattern.
416
+ const match =
417
+ patterns.find(pattern => pattern.category === 'scenario' && pattern.name === name) ??
418
+ patterns.find(pattern => pattern.name === name)
407
419
  if (!match) {
408
420
  return {
409
421
  content: [
@@ -415,7 +427,8 @@ server.registerTool(
415
427
  }
416
428
  }
417
429
 
418
- const url = new URL(`/product/ui-patterns/${match.id}`, 'https://primer.style')
430
+ const basePath = match.category === 'scenario' ? 'scenario-patterns' : 'ui-patterns'
431
+ const url = new URL(`/product/${basePath}/${match.id}`, 'https://primer.style')
419
432
  const response = await fetch(url)
420
433
  if (!response.ok) {
421
434
  throw new Error(`Failed to fetch ${url} - ${response.statusText}`)