@primer/mcp 0.3.3 → 0.4.0-rc.2d1806208
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.d.ts +6 -0
- package/dist/index.js +2 -19
- package/dist/server-BTJ9W5jN.js +1190 -0
- package/dist/stdio.js +5 -21
- package/dist/transports/stdio.d.ts +1 -0
- package/package.json +6 -15
- package/src/primer.ts +33 -0
- package/src/server.ts +51 -16
- package/dist/server-C2QaEv-c.js +0 -1504
- package/dist/server-CGPYmiEJ.js +0 -1504
package/dist/stdio.js
CHANGED
|
@@ -1,23 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import 'cheerio';
|
|
5
|
-
import 'zod';
|
|
6
|
-
import 'turndown';
|
|
7
|
-
import '@primer/react/generated/components.json' with { type: 'json' };
|
|
8
|
-
import '@primer/octicons/build/data.json' with { type: 'json' };
|
|
9
|
-
import 'node:fs';
|
|
10
|
-
import 'node:module';
|
|
11
|
-
import 'child_process';
|
|
12
|
-
import '@primer/primitives/dist/docs/base/motion/motion.json' with { type: 'json' };
|
|
13
|
-
import '@primer/primitives/dist/docs/base/size/size.json' with { type: 'json' };
|
|
14
|
-
import '@primer/primitives/dist/docs/base/typography/typography.json' with { type: 'json' };
|
|
15
|
-
import '@primer/primitives/dist/docs/functional/size/border.json' with { type: 'json' };
|
|
16
|
-
import '@primer/primitives/dist/docs/functional/size/size-coarse.json' with { type: 'json' };
|
|
17
|
-
import '@primer/primitives/dist/docs/functional/size/size-fine.json' with { type: 'json' };
|
|
18
|
-
import '@primer/primitives/dist/docs/functional/size/size.json' with { type: 'json' };
|
|
19
|
-
import '@primer/primitives/dist/docs/functional/themes/light.json' with { type: 'json' };
|
|
20
|
-
import '@primer/primitives/dist/docs/functional/typography/typography.json' with { type: 'json' };
|
|
21
|
-
|
|
1
|
+
import { t as server } from "./server-BTJ9W5jN.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
//#region src/transports/stdio.ts
|
|
22
4
|
const transport = new StdioServerTransport();
|
|
23
5
|
await server.connect(transport);
|
|
6
|
+
//#endregion
|
|
7
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
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.
|
|
4
|
+
"version": "0.4.0-rc.2d1806208",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"mcp": "./bin/mcp.js"
|
|
@@ -28,34 +28,25 @@
|
|
|
28
28
|
},
|
|
29
29
|
"scripts": {
|
|
30
30
|
"clean": "rimraf dist",
|
|
31
|
-
"build": "
|
|
31
|
+
"build": "rolldown -c",
|
|
32
32
|
"type-check": "tsc --noEmit",
|
|
33
|
-
"watch": "
|
|
33
|
+
"watch": "rolldown -c -w"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@babel/runtime": "^7.28.6",
|
|
37
36
|
"@modelcontextprotocol/sdk": "^1.24.0",
|
|
38
37
|
"@primer/octicons": "^19.15.5",
|
|
39
38
|
"@primer/primitives": "10.x || 11.x",
|
|
40
|
-
"@primer/react": "^38.
|
|
39
|
+
"@primer/react": "^38.30.0",
|
|
41
40
|
"cheerio": "^1.0.0",
|
|
42
41
|
"turndown": "^7.2.0",
|
|
43
42
|
"zod": "^4.3.5"
|
|
44
43
|
},
|
|
45
44
|
"devDependencies": {
|
|
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",
|
|
50
45
|
"@modelcontextprotocol/inspector": "^0.16.6",
|
|
51
|
-
"@rollup/plugin-babel": "^6.1.0",
|
|
52
|
-
"@rollup/plugin-commonjs": "^29.0.0",
|
|
53
|
-
"@rollup/plugin-json": "^6.1.0",
|
|
54
|
-
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
55
46
|
"@types/turndown": "^5.0.5",
|
|
56
47
|
"rimraf": "^6.0.1",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
48
|
+
"rolldown": "^1.1.2",
|
|
49
|
+
"rolldown-plugin-dts": "^0.26.0",
|
|
59
50
|
"typescript": "^6.0.3"
|
|
60
51
|
}
|
|
61
52
|
}
|
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
|
@@ -39,6 +39,7 @@ server.registerTool(
|
|
|
39
39
|
'init',
|
|
40
40
|
{
|
|
41
41
|
description: 'Setup or create a project that includes Primer React',
|
|
42
|
+
annotations: {readOnlyHint: true},
|
|
42
43
|
},
|
|
43
44
|
async () => {
|
|
44
45
|
const url = new URL(`/product/getting-started/react`, 'https://primer.style')
|
|
@@ -92,7 +93,7 @@ ${text}
|
|
|
92
93
|
// -----------------------------------------------------------------------------
|
|
93
94
|
server.registerTool(
|
|
94
95
|
'list_components',
|
|
95
|
-
{description: 'List all of the components available from Primer React'},
|
|
96
|
+
{description: 'List all of the components available from Primer React', annotations: {readOnlyHint: true}},
|
|
96
97
|
async () => {
|
|
97
98
|
const components = listComponents().map(component => {
|
|
98
99
|
return `- ${component.name}`
|
|
@@ -120,6 +121,7 @@ server.registerTool(
|
|
|
120
121
|
inputSchema: {
|
|
121
122
|
name: z.string().describe('The name of the component to retrieve'),
|
|
122
123
|
},
|
|
124
|
+
annotations: {readOnlyHint: true},
|
|
123
125
|
},
|
|
124
126
|
async ({name}) => {
|
|
125
127
|
const components = listComponents()
|
|
@@ -166,6 +168,7 @@ server.registerTool(
|
|
|
166
168
|
inputSchema: {
|
|
167
169
|
name: z.string().describe('The name of the component to retrieve'),
|
|
168
170
|
},
|
|
171
|
+
annotations: {readOnlyHint: true},
|
|
169
172
|
},
|
|
170
173
|
async ({name}) => {
|
|
171
174
|
const components = listComponents()
|
|
@@ -226,6 +229,7 @@ server.registerTool(
|
|
|
226
229
|
inputSchema: {
|
|
227
230
|
name: z.string().describe('The name of the component to retrieve'),
|
|
228
231
|
},
|
|
232
|
+
annotations: {readOnlyHint: true},
|
|
229
233
|
},
|
|
230
234
|
async ({name}) => {
|
|
231
235
|
const components = listComponents()
|
|
@@ -298,6 +302,7 @@ server.registerTool(
|
|
|
298
302
|
inputSchema: {
|
|
299
303
|
name: z.string().describe('The name of the component to retrieve'),
|
|
300
304
|
},
|
|
305
|
+
annotations: {readOnlyHint: true},
|
|
301
306
|
},
|
|
302
307
|
async ({name}) => {
|
|
303
308
|
const components = listComponents()
|
|
@@ -367,18 +372,28 @@ ${text}`,
|
|
|
367
372
|
// -----------------------------------------------------------------------------
|
|
368
373
|
server.registerTool(
|
|
369
374
|
'list_patterns',
|
|
370
|
-
{
|
|
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
|
+
},
|
|
371
380
|
async () => {
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
})
|
|
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}`)
|
|
375
384
|
return {
|
|
376
385
|
content: [
|
|
377
386
|
{
|
|
378
387
|
type: 'text',
|
|
379
|
-
text: `The following patterns are available
|
|
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.
|
|
380
389
|
|
|
381
|
-
|
|
390
|
+
## Scenario patterns
|
|
391
|
+
|
|
392
|
+
${scenario.join('\n')}
|
|
393
|
+
|
|
394
|
+
## UI patterns
|
|
395
|
+
|
|
396
|
+
${ui.join('\n')}`,
|
|
382
397
|
},
|
|
383
398
|
],
|
|
384
399
|
}
|
|
@@ -388,16 +403,19 @@ ${patterns.join('\n')}`,
|
|
|
388
403
|
server.registerTool(
|
|
389
404
|
'get_pattern',
|
|
390
405
|
{
|
|
391
|
-
description:
|
|
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.',
|
|
392
408
|
inputSchema: {
|
|
393
409
|
name: z.string().describe('The name of the pattern to retrieve'),
|
|
394
410
|
},
|
|
411
|
+
annotations: {readOnlyHint: true},
|
|
395
412
|
},
|
|
396
413
|
async ({name}) => {
|
|
397
414
|
const patterns = listPatterns()
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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)
|
|
401
419
|
if (!match) {
|
|
402
420
|
return {
|
|
403
421
|
content: [
|
|
@@ -409,7 +427,8 @@ server.registerTool(
|
|
|
409
427
|
}
|
|
410
428
|
}
|
|
411
429
|
|
|
412
|
-
const
|
|
430
|
+
const basePath = match.category === 'scenario' ? 'scenario-patterns' : 'ui-patterns'
|
|
431
|
+
const url = new URL(`/product/${basePath}/${match.id}`, 'https://primer.style')
|
|
413
432
|
const response = await fetch(url)
|
|
414
433
|
if (!response.ok) {
|
|
415
434
|
throw new Error(`Failed to fetch ${url} - ${response.statusText}`)
|
|
@@ -469,6 +488,7 @@ server.registerTool(
|
|
|
469
488
|
.default(15)
|
|
470
489
|
.describe('Maximum results to return to stay within context limits'),
|
|
471
490
|
},
|
|
491
|
+
annotations: {readOnlyHint: true},
|
|
472
492
|
},
|
|
473
493
|
async ({query, group, limit}) => {
|
|
474
494
|
// Resolve group via aliases
|
|
@@ -566,6 +586,7 @@ server.registerTool(
|
|
|
566
586
|
inputSchema: {
|
|
567
587
|
groups: z.array(z.string()).describe('Array of group names (e.g., ["overlay", "shadow", "focus"])'),
|
|
568
588
|
},
|
|
589
|
+
annotations: {readOnlyHint: true},
|
|
569
590
|
},
|
|
570
591
|
async ({groups}) => {
|
|
571
592
|
// Normalize and resolve aliases
|
|
@@ -608,6 +629,7 @@ server.registerTool(
|
|
|
608
629
|
{
|
|
609
630
|
description:
|
|
610
631
|
'CRITICAL: CALL THIS FIRST. Provides the logic matrix and the list of valid group names. You cannot search accurately without this map.',
|
|
632
|
+
annotations: {readOnlyHint: true},
|
|
611
633
|
},
|
|
612
634
|
async () => {
|
|
613
635
|
const groups = listTokenGroups()
|
|
@@ -631,6 +653,7 @@ server.registerTool(
|
|
|
631
653
|
{
|
|
632
654
|
description:
|
|
633
655
|
'Provides "Golden Example" CSS for core patterns: Button (Interactions) and Stack (Layout). Use this to understand how to apply the Logic Matrix, Motion, and Spacing scales.',
|
|
656
|
+
annotations: {readOnlyHint: true},
|
|
634
657
|
},
|
|
635
658
|
async () => {
|
|
636
659
|
const customPatterns = getTokenUsagePatternsText()
|
|
@@ -659,6 +682,7 @@ server.registerTool(
|
|
|
659
682
|
description:
|
|
660
683
|
'REQUIRED FINAL STEP. Use this to validate your CSS. You cannot complete a task involving CSS without a successful run of this tool.',
|
|
661
684
|
inputSchema: {css: z.string()},
|
|
685
|
+
annotations: {readOnlyHint: true},
|
|
662
686
|
},
|
|
663
687
|
async ({css}) => {
|
|
664
688
|
try {
|
|
@@ -694,7 +718,7 @@ server.registerTool(
|
|
|
694
718
|
// -----------------------------------------------------------------------------
|
|
695
719
|
server.registerTool(
|
|
696
720
|
'get_color_usage',
|
|
697
|
-
{description: 'Get the guidelines for how to apply color to a user interface'},
|
|
721
|
+
{description: 'Get the guidelines for how to apply color to a user interface', annotations: {readOnlyHint: true}},
|
|
698
722
|
async () => {
|
|
699
723
|
const url = new URL(`/product/getting-started/foundations/color-usage`, 'https://primer.style')
|
|
700
724
|
const response = await fetch(url)
|
|
@@ -732,7 +756,10 @@ server.registerTool(
|
|
|
732
756
|
|
|
733
757
|
server.registerTool(
|
|
734
758
|
'get_typography_usage',
|
|
735
|
-
{
|
|
759
|
+
{
|
|
760
|
+
description: 'Get the guidelines for how to apply typography to a user interface',
|
|
761
|
+
annotations: {readOnlyHint: true},
|
|
762
|
+
},
|
|
736
763
|
async () => {
|
|
737
764
|
const url = new URL(`/product/getting-started/foundations/typography`, 'https://primer.style')
|
|
738
765
|
const response = await fetch(url)
|
|
@@ -773,7 +800,10 @@ server.registerTool(
|
|
|
773
800
|
// -----------------------------------------------------------------------------
|
|
774
801
|
server.registerTool(
|
|
775
802
|
'list_icons',
|
|
776
|
-
{
|
|
803
|
+
{
|
|
804
|
+
description: 'List all of the icons (octicons) available from Primer Octicons React',
|
|
805
|
+
annotations: {readOnlyHint: true},
|
|
806
|
+
},
|
|
777
807
|
async () => {
|
|
778
808
|
const icons = listIcons().map(icon => {
|
|
779
809
|
const keywords = icon.keywords.map(keyword => {
|
|
@@ -808,6 +838,7 @@ server.registerTool(
|
|
|
808
838
|
name: z.string().describe('The name of the icon to retrieve'),
|
|
809
839
|
size: z.string().optional().describe('The size of the icon to retrieve, e.g. "16"').default('16'),
|
|
810
840
|
},
|
|
841
|
+
annotations: {readOnlyHint: true},
|
|
811
842
|
},
|
|
812
843
|
async ({name, size}) => {
|
|
813
844
|
const icons = listIcons()
|
|
@@ -865,7 +896,10 @@ ${text}`,
|
|
|
865
896
|
// -----------------------------------------------------------------------------
|
|
866
897
|
server.registerTool(
|
|
867
898
|
'primer_coding_guidelines',
|
|
868
|
-
{
|
|
899
|
+
{
|
|
900
|
+
description: 'Get the guidelines when writing code that uses Primer or for UI code that you are creating',
|
|
901
|
+
annotations: {readOnlyHint: true},
|
|
902
|
+
},
|
|
869
903
|
async () => {
|
|
870
904
|
return {
|
|
871
905
|
content: [
|
|
@@ -922,6 +956,7 @@ server.registerTool(
|
|
|
922
956
|
alt: z.string().describe('The alt text of the image being evaluated'),
|
|
923
957
|
image: z.string().describe('The image URL or file path being evaluated'),
|
|
924
958
|
},
|
|
959
|
+
annotations: {readOnlyHint: true},
|
|
925
960
|
},
|
|
926
961
|
async ({surroundingText, alt, image}) => {
|
|
927
962
|
// Call the LLM through MCP sampling
|