Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The Model Context Protocol (MCP) is an open standard that enables AI assistants

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

componentSchemas (get component JSON Schema):

```bash
npx @modelcontextprotocol/inspector-cli \
--config ./mcp-config.json \
--server patternfly-docs \
--cli \
--method tools/call \
--tool-name componentSchemas \
--tool-arg componentName='Button'
```

## Environment variables

- DOC_MCP_FETCH_TIMEOUT_MS: Milliseconds to wait before aborting an HTTP fetch (default: 15000)
Expand Down
28 changes: 28 additions & 0 deletions jest.setupTests.ts
Original file line number Diff line number Diff line change
@@ -1 +1,29 @@
// Shared helpers for all Jest tests

/**
* Note: Mock @patternfly/patternfly-component-schemas/json to avoid top-level await issues in Jest
* - This package uses top-level await which Jest cannot handle without transformation.
* - Individual tests can override this mock if needed
*/
jest.mock('@patternfly/patternfly-component-schemas/json', () => ({
componentNames: ['Button', 'Alert', 'Card', 'Modal', 'AlertGroup', 'Text', 'TextInput'],
getComponentSchema: jest.fn().mockImplementation((name: string) => {
if (name === 'Button') {
return Promise.resolve({
$schema: 'https://json-schema.org/draft/2020-12/schema',
type: 'object',
title: 'Button Props',
description: 'Props for the Button component',
properties: {
variant: { type: 'string', enum: ['primary', 'secondary'] },
size: { type: 'string', enum: ['sm', 'md', 'lg'] },
children: { type: 'string', description: 'Content rendered inside the button' }
},
required: ['children'],
additionalProperties: false
});
}

throw new Error(`Component "${name}" not found`);
})
}), { virtual: true });
19 changes: 19 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "1.19.1",
"@patternfly/patternfly-component-schemas": "1.2.0",
"fastest-levenshtein": "1.0.16",
"zod": "3.25.76"
},
Expand Down
49 changes: 49 additions & 0 deletions src/__tests__/__snapshots__/server.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ exports[`runServer should attempt to run server, use default tools: console 1`]
[
"Registered tool: fetchDocs",
],
[
"Registered tool: componentSchemas",
],
],
"log": [
[
Expand Down Expand Up @@ -629,6 +632,52 @@ exports[`runServer should attempt to run server, use default tools: console 1`]
},
[Function],
],
[
"componentSchemas",
{
"description": "Get JSON Schema for a PatternFly React component. Returns prop definitions, types, and validation rules. Use this for structured component metadata, not documentation.",
"inputSchema": {
"componentName": ZodString {
"_def": {
"checks": [],
"coerce": false,
"description": "Name of the PatternFly component (e.g., "Button", "Table")",
"typeName": "ZodString",
},
"and": [Function],
"array": [Function],
"brand": [Function],
"catch": [Function],
"default": [Function],
"describe": [Function],
"isNullable": [Function],
"isOptional": [Function],
"nullable": [Function],
"nullish": [Function],
"optional": [Function],
"or": [Function],
"parse": [Function],
"parseAsync": [Function],
"pipe": [Function],
"promise": [Function],
"readonly": [Function],
"refine": [Function],
"refinement": [Function],
"safeParse": [Function],
"safeParseAsync": [Function],
"spa": [Function],
"superRefine": [Function],
"transform": [Function],
"~standard": {
"validate": [Function],
"vendor": "zod",
"version": 1,
},
},
},
},
[Function],
],
],
}
`;
214 changes: 214 additions & 0 deletions src/__tests__/__snapshots__/tool.componentSchemas.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`componentSchemasTool should have a consistent return structure: structure 1`] = `
[
"componentSchemas",
{
"description": "Get JSON Schema for a PatternFly React component. Returns prop definitions, types, and validation rules. Use this for structured component metadata, not documentation.",
"inputSchema": {
"componentName": ZodString {
"_def": {
"checks": [],
"coerce": false,
"description": "Name of the PatternFly component (e.g., "Button", "Table")",
"typeName": "ZodString",
},
"and": [Function],
"array": [Function],
"brand": [Function],
"catch": [Function],
"default": [Function],
"describe": [Function],
"isNullable": [Function],
"isOptional": [Function],
"nullable": [Function],
"nullish": [Function],
"optional": [Function],
"or": [Function],
"parse": [Function],
"parseAsync": [Function],
"pipe": [Function],
"promise": [Function],
"readonly": [Function],
"refine": [Function],
"refinement": [Function],
"safeParse": [Function],
"safeParseAsync": [Function],
"spa": [Function],
"superRefine": [Function],
"transform": [Function],
"~standard": {
"validate": [Function],
"vendor": "zod",
"version": 1,
},
},
},
},
[Function],
]
`;

exports[`componentSchemasTool, callback should parse parameters, default 1`] = `
{
"content": [
{
"text": "{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"title": "Button Props",
"description": "Props for the Button component",
"properties": {
"variant": {
"type": "string",
"enum": [
"primary",
"secondary"
]
},
"size": {
"type": "string",
"enum": [
"sm",
"md",
"lg"
]
},
"children": {
"type": "string",
"description": "Content rendered inside the button"
}
},
"required": [
"children"
],
"additionalProperties": false
}",
"type": "text",
},
],
}
`;

exports[`componentSchemasTool, callback should parse parameters, with lower case componentName 1`] = `
{
"content": [
{
"text": "{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"title": "Button Props",
"description": "Props for the Button component",
"properties": {
"variant": {
"type": "string",
"enum": [
"primary",
"secondary"
]
},
"size": {
"type": "string",
"enum": [
"sm",
"md",
"lg"
]
},
"children": {
"type": "string",
"description": "Content rendered inside the button"
}
},
"required": [
"children"
],
"additionalProperties": false
}",
"type": "text",
},
],
}
`;

exports[`componentSchemasTool, callback should parse parameters, with trimmed componentName 1`] = `
{
"content": [
{
"text": "{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"title": "Button Props",
"description": "Props for the Button component",
"properties": {
"variant": {
"type": "string",
"enum": [
"primary",
"secondary"
]
},
"size": {
"type": "string",
"enum": [
"sm",
"md",
"lg"
]
},
"children": {
"type": "string",
"description": "Content rendered inside the button"
}
},
"required": [
"children"
],
"additionalProperties": false
}",
"type": "text",
},
],
}
`;

exports[`componentSchemasTool, callback should parse parameters, with upper case componentName 1`] = `
{
"content": [
{
"text": "{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"title": "Button Props",
"description": "Props for the Button component",
"properties": {
"variant": {
"type": "string",
"enum": [
"primary",
"secondary"
]
},
"size": {
"type": "string",
"enum": [
"sm",
"md",
"lg"
]
},
"children": {
"type": "string",
"description": "Content rendered inside the button"
}
},
"required": [
"children"
],
"additionalProperties": false
}",
"type": "text",
},
],
}
`;
Loading
Loading