Skip to content

Commit 4e58b28

Browse files
jenny-s51cdcabrera
andauthored
feat(schemas): add component-schemas tool (#12)
Co-authored-by: CD Cabrera <[email protected]>
1 parent 0f2b54a commit 4e58b28

File tree

11 files changed

+533
-2
lines changed

11 files changed

+533
-2
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The Model Context Protocol (MCP) is an open standard that enables AI assistants
1010

1111
- **TypeScript**: Full type safety and modern JavaScript features
1212
- **PatternFly Documentation Access**: Browse, search, and retrieve PatternFly development rules
13+
- **Component Schemas**: Access JSON Schema validation for PatternFly React components
1314
- **Comprehensive Rule Coverage**: Access setup, guidelines, components, charts, chatbot, and troubleshooting documentation
1415
- **Smart Search**: Find specific rules and patterns across all documentation
1516
- **Error Handling**: Robust error handling with proper MCP error codes
@@ -194,6 +195,18 @@ npx @modelcontextprotocol/inspector-cli \
194195
]'
195196
```
196197

198+
componentSchemas (get component JSON Schema):
199+
200+
```bash
201+
npx @modelcontextprotocol/inspector-cli \
202+
--config ./mcp-config.json \
203+
--server patternfly-docs \
204+
--cli \
205+
--method tools/call \
206+
--tool-name componentSchemas \
207+
--tool-arg componentName='Button'
208+
```
209+
197210
## Environment variables
198211

199212
- DOC_MCP_FETCH_TIMEOUT_MS: Milliseconds to wait before aborting an HTTP fetch (default: 15000)

jest.setupTests.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,29 @@
11
// Shared helpers for all Jest tests
2+
3+
/**
4+
* Note: Mock @patternfly/patternfly-component-schemas/json to avoid top-level await issues in Jest
5+
* - This package uses top-level await which Jest cannot handle without transformation.
6+
* - Individual tests can override this mock if needed
7+
*/
8+
jest.mock('@patternfly/patternfly-component-schemas/json', () => ({
9+
componentNames: ['Button', 'Alert', 'Card', 'Modal', 'AlertGroup', 'Text', 'TextInput'],
10+
getComponentSchema: jest.fn().mockImplementation((name: string) => {
11+
if (name === 'Button') {
12+
return Promise.resolve({
13+
$schema: 'https://json-schema.org/draft/2020-12/schema',
14+
type: 'object',
15+
title: 'Button Props',
16+
description: 'Props for the Button component',
17+
properties: {
18+
variant: { type: 'string', enum: ['primary', 'secondary'] },
19+
size: { type: 'string', enum: ['sm', 'md', 'lg'] },
20+
children: { type: 'string', description: 'Content rendered inside the button' }
21+
},
22+
required: ['children'],
23+
additionalProperties: false
24+
});
25+
}
26+
27+
throw new Error(`Component "${name}" not found`);
28+
})
29+
}), { virtual: true });

package-lock.json

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"license": "MIT",
4949
"dependencies": {
5050
"@modelcontextprotocol/sdk": "1.19.1",
51+
"@patternfly/patternfly-component-schemas": "1.2.0",
5152
"fastest-levenshtein": "1.0.16",
5253
"zod": "3.25.76"
5354
},

src/__tests__/__snapshots__/server.test.ts.snap

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ exports[`runServer should attempt to run server, use default tools: console 1`]
227227
[
228228
"Registered tool: fetchDocs",
229229
],
230+
[
231+
"Registered tool: componentSchemas",
232+
],
230233
],
231234
"log": [
232235
[
@@ -629,6 +632,52 @@ exports[`runServer should attempt to run server, use default tools: console 1`]
629632
},
630633
[Function],
631634
],
635+
[
636+
"componentSchemas",
637+
{
638+
"description": "Get JSON Schema for a PatternFly React component. Returns prop definitions, types, and validation rules. Use this for structured component metadata, not documentation.",
639+
"inputSchema": {
640+
"componentName": ZodString {
641+
"_def": {
642+
"checks": [],
643+
"coerce": false,
644+
"description": "Name of the PatternFly component (e.g., "Button", "Table")",
645+
"typeName": "ZodString",
646+
},
647+
"and": [Function],
648+
"array": [Function],
649+
"brand": [Function],
650+
"catch": [Function],
651+
"default": [Function],
652+
"describe": [Function],
653+
"isNullable": [Function],
654+
"isOptional": [Function],
655+
"nullable": [Function],
656+
"nullish": [Function],
657+
"optional": [Function],
658+
"or": [Function],
659+
"parse": [Function],
660+
"parseAsync": [Function],
661+
"pipe": [Function],
662+
"promise": [Function],
663+
"readonly": [Function],
664+
"refine": [Function],
665+
"refinement": [Function],
666+
"safeParse": [Function],
667+
"safeParseAsync": [Function],
668+
"spa": [Function],
669+
"superRefine": [Function],
670+
"transform": [Function],
671+
"~standard": {
672+
"validate": [Function],
673+
"vendor": "zod",
674+
"version": 1,
675+
},
676+
},
677+
},
678+
},
679+
[Function],
680+
],
632681
],
633682
}
634683
`;
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2+
3+
exports[`componentSchemasTool should have a consistent return structure: structure 1`] = `
4+
[
5+
"componentSchemas",
6+
{
7+
"description": "Get JSON Schema for a PatternFly React component. Returns prop definitions, types, and validation rules. Use this for structured component metadata, not documentation.",
8+
"inputSchema": {
9+
"componentName": ZodString {
10+
"_def": {
11+
"checks": [],
12+
"coerce": false,
13+
"description": "Name of the PatternFly component (e.g., "Button", "Table")",
14+
"typeName": "ZodString",
15+
},
16+
"and": [Function],
17+
"array": [Function],
18+
"brand": [Function],
19+
"catch": [Function],
20+
"default": [Function],
21+
"describe": [Function],
22+
"isNullable": [Function],
23+
"isOptional": [Function],
24+
"nullable": [Function],
25+
"nullish": [Function],
26+
"optional": [Function],
27+
"or": [Function],
28+
"parse": [Function],
29+
"parseAsync": [Function],
30+
"pipe": [Function],
31+
"promise": [Function],
32+
"readonly": [Function],
33+
"refine": [Function],
34+
"refinement": [Function],
35+
"safeParse": [Function],
36+
"safeParseAsync": [Function],
37+
"spa": [Function],
38+
"superRefine": [Function],
39+
"transform": [Function],
40+
"~standard": {
41+
"validate": [Function],
42+
"vendor": "zod",
43+
"version": 1,
44+
},
45+
},
46+
},
47+
},
48+
[Function],
49+
]
50+
`;
51+
52+
exports[`componentSchemasTool, callback should parse parameters, default 1`] = `
53+
{
54+
"content": [
55+
{
56+
"text": "{
57+
"$schema": "https://json-schema.org/draft/2020-12/schema",
58+
"type": "object",
59+
"title": "Button Props",
60+
"description": "Props for the Button component",
61+
"properties": {
62+
"variant": {
63+
"type": "string",
64+
"enum": [
65+
"primary",
66+
"secondary"
67+
]
68+
},
69+
"size": {
70+
"type": "string",
71+
"enum": [
72+
"sm",
73+
"md",
74+
"lg"
75+
]
76+
},
77+
"children": {
78+
"type": "string",
79+
"description": "Content rendered inside the button"
80+
}
81+
},
82+
"required": [
83+
"children"
84+
],
85+
"additionalProperties": false
86+
}",
87+
"type": "text",
88+
},
89+
],
90+
}
91+
`;
92+
93+
exports[`componentSchemasTool, callback should parse parameters, with lower case componentName 1`] = `
94+
{
95+
"content": [
96+
{
97+
"text": "{
98+
"$schema": "https://json-schema.org/draft/2020-12/schema",
99+
"type": "object",
100+
"title": "Button Props",
101+
"description": "Props for the Button component",
102+
"properties": {
103+
"variant": {
104+
"type": "string",
105+
"enum": [
106+
"primary",
107+
"secondary"
108+
]
109+
},
110+
"size": {
111+
"type": "string",
112+
"enum": [
113+
"sm",
114+
"md",
115+
"lg"
116+
]
117+
},
118+
"children": {
119+
"type": "string",
120+
"description": "Content rendered inside the button"
121+
}
122+
},
123+
"required": [
124+
"children"
125+
],
126+
"additionalProperties": false
127+
}",
128+
"type": "text",
129+
},
130+
],
131+
}
132+
`;
133+
134+
exports[`componentSchemasTool, callback should parse parameters, with trimmed componentName 1`] = `
135+
{
136+
"content": [
137+
{
138+
"text": "{
139+
"$schema": "https://json-schema.org/draft/2020-12/schema",
140+
"type": "object",
141+
"title": "Button Props",
142+
"description": "Props for the Button component",
143+
"properties": {
144+
"variant": {
145+
"type": "string",
146+
"enum": [
147+
"primary",
148+
"secondary"
149+
]
150+
},
151+
"size": {
152+
"type": "string",
153+
"enum": [
154+
"sm",
155+
"md",
156+
"lg"
157+
]
158+
},
159+
"children": {
160+
"type": "string",
161+
"description": "Content rendered inside the button"
162+
}
163+
},
164+
"required": [
165+
"children"
166+
],
167+
"additionalProperties": false
168+
}",
169+
"type": "text",
170+
},
171+
],
172+
}
173+
`;
174+
175+
exports[`componentSchemasTool, callback should parse parameters, with upper case componentName 1`] = `
176+
{
177+
"content": [
178+
{
179+
"text": "{
180+
"$schema": "https://json-schema.org/draft/2020-12/schema",
181+
"type": "object",
182+
"title": "Button Props",
183+
"description": "Props for the Button component",
184+
"properties": {
185+
"variant": {
186+
"type": "string",
187+
"enum": [
188+
"primary",
189+
"secondary"
190+
]
191+
},
192+
"size": {
193+
"type": "string",
194+
"enum": [
195+
"sm",
196+
"md",
197+
"lg"
198+
]
199+
},
200+
"children": {
201+
"type": "string",
202+
"description": "Content rendered inside the button"
203+
}
204+
},
205+
"required": [
206+
"children"
207+
],
208+
"additionalProperties": false
209+
}",
210+
"type": "text",
211+
},
212+
],
213+
}
214+
`;

0 commit comments

Comments
 (0)